forked from libre-chip/fayalite
simple extern module simulation works!
This commit is contained in:
parent
f378b9a1d2
commit
a5a7284483
17 changed files with 650 additions and 167 deletions
|
@ -20,9 +20,10 @@ use crate::{
|
|||
},
|
||||
memory::PortKind,
|
||||
module::{
|
||||
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
|
||||
ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration,
|
||||
StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
|
||||
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, ExternModuleBody, Id,
|
||||
InstantiatedModule, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect,
|
||||
StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire,
|
||||
TargetInInstantiatedModule,
|
||||
},
|
||||
prelude::*,
|
||||
reset::{ResetType, ResetTypeDispatch},
|
||||
|
@ -1631,12 +1632,21 @@ impl<T> fmt::Debug for DebugOpaque<T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||
struct CompiledExternModule {
|
||||
io_ty: Bundle,
|
||||
module_io_targets: Interned<[Target]>,
|
||||
module_io: Interned<[CompiledValue<CanonicalType>]>,
|
||||
simulation: ExternModuleSimulation<Bundle>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Compiler {
|
||||
insns: Insns<InsnsBuilding>,
|
||||
original_base_module: Interned<Module<Bundle>>,
|
||||
base_module: Interned<Module<Bundle>>,
|
||||
modules: HashMap<InstantiatedModule, CompiledModule>,
|
||||
extern_modules: Vec<CompiledExternModule>,
|
||||
compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue<CanonicalType>>,
|
||||
compiled_exprs: HashMap<Expr<CanonicalType>, CompiledExpr<CanonicalType>>,
|
||||
compiled_exprs_to_values: HashMap<CompiledExpr<CanonicalType>, CompiledValue<CanonicalType>>,
|
||||
|
@ -1665,6 +1675,7 @@ impl Compiler {
|
|||
original_base_module,
|
||||
base_module,
|
||||
modules: HashMap::new(),
|
||||
extern_modules: Vec::new(),
|
||||
compiled_values: HashMap::new(),
|
||||
compiled_exprs: HashMap::new(),
|
||||
compiled_exprs_to_values: HashMap::new(),
|
||||
|
@ -4690,8 +4701,28 @@ impl Compiler {
|
|||
ModuleBody::Normal(NormalModuleBody { body }) => {
|
||||
self.compile_block(module, body, Interned::default(), &mut trace_decls);
|
||||
}
|
||||
ModuleBody::Extern(_extern_module_body) => {
|
||||
todo!("simulating extern module: {:?}", module);
|
||||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
simulation,
|
||||
}) => {
|
||||
let Some(simulation) = simulation else {
|
||||
panic!(
|
||||
"can't simulate extern module without extern_module_simulation: {}",
|
||||
module.leaf_module().source_location()
|
||||
);
|
||||
};
|
||||
self.extern_modules.push(CompiledExternModule {
|
||||
io_ty: module.leaf_module().io_ty(),
|
||||
module_io_targets: module
|
||||
.leaf_module()
|
||||
.module_io()
|
||||
.iter()
|
||||
.map(|v| Target::from(v.module_io))
|
||||
.collect(),
|
||||
module_io,
|
||||
simulation,
|
||||
});
|
||||
}
|
||||
}
|
||||
let hashbrown::hash_map::Entry::Vacant(entry) = self.modules.entry(*module) else {
|
||||
|
@ -4972,6 +5003,7 @@ impl Compiler {
|
|||
Compiled {
|
||||
insns: Insns::from(self.insns).intern_sized(),
|
||||
base_module,
|
||||
extern_modules: Intern::intern_owned(self.extern_modules),
|
||||
io: Instance::new_unchecked(
|
||||
ScopedNameId(
|
||||
NameId("<simulator>".intern(), Id::new()),
|
||||
|
@ -5004,6 +5036,7 @@ struct CompiledModule {
|
|||
pub struct Compiled<T: BundleType> {
|
||||
insns: Interned<Insns<InsnsBuildingDone>>,
|
||||
base_module: CompiledModule,
|
||||
extern_modules: Interned<[CompiledExternModule]>,
|
||||
io: Instance<T>,
|
||||
traces: SimTraces<Interned<[SimTrace<SimTraceKind, ()>]>>,
|
||||
trace_memories: Interned<[(StatePartIndex<StatePartKindMemories>, TraceMem)]>,
|
||||
|
@ -5018,6 +5051,7 @@ impl<T: BundleType> Compiled<T> {
|
|||
let Self {
|
||||
insns,
|
||||
base_module,
|
||||
extern_modules,
|
||||
io,
|
||||
traces,
|
||||
trace_memories,
|
||||
|
@ -5026,6 +5060,7 @@ impl<T: BundleType> Compiled<T> {
|
|||
Compiled {
|
||||
insns,
|
||||
base_module,
|
||||
extern_modules,
|
||||
io: Instance::from_canonical(io.canonical()),
|
||||
traces,
|
||||
trace_memories,
|
||||
|
@ -5036,6 +5071,7 @@ impl<T: BundleType> Compiled<T> {
|
|||
let Compiled {
|
||||
insns,
|
||||
base_module,
|
||||
extern_modules,
|
||||
io,
|
||||
traces,
|
||||
trace_memories,
|
||||
|
@ -5044,6 +5080,7 @@ impl<T: BundleType> Compiled<T> {
|
|||
Self {
|
||||
insns,
|
||||
base_module,
|
||||
extern_modules,
|
||||
io: Instance::from_canonical(io.canonical()),
|
||||
traces,
|
||||
trace_memories,
|
||||
|
@ -6785,6 +6822,7 @@ impl Ord for WaitTarget {
|
|||
|
||||
struct SimulationExternModuleState {
|
||||
module_state: SimulationModuleState,
|
||||
io_ty: Bundle,
|
||||
sim: ExternModuleSimulation<Bundle>,
|
||||
running_generator: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
wait_target: Option<WaitTarget>,
|
||||
|
@ -6794,12 +6832,14 @@ impl fmt::Debug for SimulationExternModuleState {
|
|||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self {
|
||||
module_state,
|
||||
io_ty,
|
||||
sim,
|
||||
running_generator,
|
||||
wait_target,
|
||||
} = self;
|
||||
f.debug_struct("SimulationExternModuleState")
|
||||
.field("module_state", module_state)
|
||||
.field("io_ty", io_ty)
|
||||
.field("sim", sim)
|
||||
.field(
|
||||
"running_generator",
|
||||
|
@ -6894,12 +6934,29 @@ impl std::task::Wake for GeneratorWaker {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ReadyToRunSet {
|
||||
state_ready_to_run: bool,
|
||||
extern_modules_ready_to_run: Vec<usize>,
|
||||
}
|
||||
|
||||
impl ReadyToRunSet {
|
||||
fn clear(&mut self) {
|
||||
let Self {
|
||||
state_ready_to_run,
|
||||
extern_modules_ready_to_run,
|
||||
} = self;
|
||||
*state_ready_to_run = false;
|
||||
extern_modules_ready_to_run.clear();
|
||||
}
|
||||
}
|
||||
|
||||
struct SimulationImpl {
|
||||
state: interpreter::State,
|
||||
io: Expr<Bundle>,
|
||||
main_module: SimulationModuleState,
|
||||
extern_modules: Box<[SimulationExternModuleState]>,
|
||||
needs_settle: bool,
|
||||
state_ready_to_run: bool,
|
||||
trace_decls: TraceModule,
|
||||
traces: SimTraces<Box<[SimTrace<SimTraceKind, BitVec>]>>,
|
||||
trace_memories: HashMap<StatePartIndex<StatePartKindMemories>, TraceMem>,
|
||||
|
@ -6923,7 +6980,7 @@ impl SimulationImpl {
|
|||
io: self_io,
|
||||
main_module,
|
||||
extern_modules,
|
||||
needs_settle,
|
||||
state_ready_to_run,
|
||||
trace_decls,
|
||||
traces,
|
||||
trace_memories,
|
||||
|
@ -6938,7 +6995,7 @@ impl SimulationImpl {
|
|||
.field("io", io.unwrap_or(self_io))
|
||||
.field("main_module", main_module)
|
||||
.field("extern_modules", extern_modules)
|
||||
.field("needs_settle", needs_settle)
|
||||
.field("state_ready_to_run", state_ready_to_run)
|
||||
.field("trace_decls", trace_decls)
|
||||
.field("traces", traces)
|
||||
.field("trace_memories", trace_memories)
|
||||
|
@ -6949,8 +7006,27 @@ impl SimulationImpl {
|
|||
}
|
||||
fn new(compiled: Compiled<Bundle>) -> Self {
|
||||
let io_target = Target::from(compiled.io);
|
||||
// TODO: add extern_modules
|
||||
let extern_modules: Box<[SimulationExternModuleState]> = Box::new([]);
|
||||
let extern_modules = Box::from_iter(compiled.extern_modules.iter().map(
|
||||
|&CompiledExternModule {
|
||||
io_ty,
|
||||
module_io_targets,
|
||||
module_io,
|
||||
simulation,
|
||||
}| {
|
||||
SimulationExternModuleState {
|
||||
module_state: SimulationModuleState::new(
|
||||
module_io_targets
|
||||
.iter()
|
||||
.copied()
|
||||
.zip(module_io.iter().copied()),
|
||||
),
|
||||
io_ty,
|
||||
sim: simulation,
|
||||
running_generator: None,
|
||||
wait_target: Some(WaitTarget::Settle),
|
||||
}
|
||||
},
|
||||
));
|
||||
Self {
|
||||
state: State::new(compiled.insns),
|
||||
io: compiled.io.to_expr(),
|
||||
|
@ -6972,7 +7048,7 @@ impl SimulationImpl {
|
|||
}),
|
||||
),
|
||||
extern_modules,
|
||||
needs_settle: true,
|
||||
state_ready_to_run: true,
|
||||
trace_decls: compiled.base_module.trace_decls,
|
||||
traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map(
|
||||
|&SimTrace {
|
||||
|
@ -7129,20 +7205,9 @@ impl SimulationImpl {
|
|||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn advance_time(this: &Rc<RefCell<Self>>, duration: SimDuration) {
|
||||
Self::settle(this);
|
||||
let mut this = this.borrow_mut();
|
||||
this.instant += duration;
|
||||
this.for_each_trace_writer_storing_error(|this, mut trace_writer_state| {
|
||||
match &mut trace_writer_state {
|
||||
TraceWriterState::Decls(_) | TraceWriterState::Init(_) => unreachable!(),
|
||||
TraceWriterState::Running(trace_writer) => {
|
||||
trace_writer.change_time_to(this.instant)?;
|
||||
}
|
||||
TraceWriterState::Errored(_) => {}
|
||||
}
|
||||
Ok(trace_writer_state)
|
||||
});
|
||||
fn advance_time(this_ref: &Rc<RefCell<Self>>, duration: SimDuration) {
|
||||
let instant = this_ref.borrow().instant + duration;
|
||||
Self::run_until(this_ref, WaitTarget::Instant(instant));
|
||||
}
|
||||
#[must_use]
|
||||
fn yield_advance_time_or_settle(
|
||||
|
@ -7197,86 +7262,157 @@ impl SimulationImpl {
|
|||
target,
|
||||
}
|
||||
}
|
||||
fn get_ready_external_modules(&mut self, run_list: &mut Vec<usize>) -> Option<WaitTarget> {
|
||||
run_list.clear();
|
||||
let mut iter = self.extern_modules.iter_mut().enumerate().filter_map(
|
||||
|(module_index, extern_module)| Some((module_index, extern_module.wait_target?)),
|
||||
);
|
||||
let (first_module_index, mut wait_target) = iter.next()?;
|
||||
run_list.push(first_module_index);
|
||||
for (next_module_index, next_wait_target) in iter {
|
||||
match next_wait_target.cmp(&wait_target) {
|
||||
std::cmp::Ordering::Less => run_list.clear(),
|
||||
std::cmp::Ordering::Equal => {}
|
||||
std::cmp::Ordering::Greater => continue,
|
||||
}
|
||||
run_list.push(next_module_index);
|
||||
wait_target = next_wait_target;
|
||||
/// returns the next `WaitTarget` and the set of things ready to run then.
|
||||
fn get_ready_to_run_set(&self, ready_to_run_set: &mut ReadyToRunSet) -> Option<WaitTarget> {
|
||||
ready_to_run_set.clear();
|
||||
let mut wait_target = None;
|
||||
if self.state_ready_to_run {
|
||||
ready_to_run_set.state_ready_to_run = true;
|
||||
wait_target = Some(WaitTarget::Settle);
|
||||
}
|
||||
Some(wait_target)
|
||||
for (module_index, extern_module) in self.extern_modules.iter().enumerate() {
|
||||
let Some(extern_module_wait_target) = extern_module.wait_target else {
|
||||
continue;
|
||||
};
|
||||
if let Some(wait_target) = &mut wait_target {
|
||||
match extern_module_wait_target.cmp(wait_target) {
|
||||
std::cmp::Ordering::Less => ready_to_run_set.clear(),
|
||||
std::cmp::Ordering::Equal => {}
|
||||
std::cmp::Ordering::Greater => continue,
|
||||
}
|
||||
} else {
|
||||
wait_target = Some(extern_module_wait_target);
|
||||
}
|
||||
ready_to_run_set
|
||||
.extern_modules_ready_to_run
|
||||
.push(module_index);
|
||||
}
|
||||
wait_target
|
||||
}
|
||||
fn set_instant_no_sim(&mut self, instant: SimInstant) {
|
||||
self.instant = instant;
|
||||
self.for_each_trace_writer_storing_error(|this, mut trace_writer_state| {
|
||||
match &mut trace_writer_state {
|
||||
TraceWriterState::Decls(_) | TraceWriterState::Init(_) => unreachable!(),
|
||||
TraceWriterState::Running(trace_writer) => {
|
||||
trace_writer.change_time_to(this.instant)?;
|
||||
}
|
||||
TraceWriterState::Errored(_) => {}
|
||||
}
|
||||
Ok(trace_writer_state)
|
||||
});
|
||||
}
|
||||
#[track_caller]
|
||||
fn settle(this_ref: &Rc<RefCell<Self>>) {
|
||||
fn run_until(this_ref: &Rc<RefCell<Self>>, run_target: WaitTarget) {
|
||||
let mut this = this_ref.borrow_mut();
|
||||
let mut ready_to_run_set = ReadyToRunSet::default();
|
||||
let generator_waker = this.generator_waker.clone();
|
||||
assert!(
|
||||
this.main_module.uninitialized_ios.is_empty(),
|
||||
"didn't initialize all inputs",
|
||||
);
|
||||
let mut run_list = Vec::new();
|
||||
let generator_waker = this.generator_waker.clone();
|
||||
for _ in 0..100000 {
|
||||
if !this.needs_settle {
|
||||
if let Some(wait_target) = this.get_ready_external_modules(&mut run_list) {
|
||||
if wait_target > WaitTarget::Instant(this.instant) {
|
||||
return;
|
||||
}
|
||||
for module_index in run_list.drain(..) {
|
||||
this.extern_modules[module_index].wait_target = None;
|
||||
let Some(mut generator) =
|
||||
this.extern_modules[module_index].running_generator.take()
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
drop(this);
|
||||
let generator = match generator
|
||||
.as_mut()
|
||||
.poll(&mut std::task::Context::from_waker(&generator_waker))
|
||||
{
|
||||
Poll::Ready(()) => None,
|
||||
Poll::Pending => Some(generator),
|
||||
};
|
||||
this = this_ref.borrow_mut();
|
||||
this.extern_modules[module_index].running_generator = generator;
|
||||
}
|
||||
continue;
|
||||
match run_target {
|
||||
WaitTarget::Settle => {}
|
||||
WaitTarget::Instant(run_target) => assert!(run_target >= this.instant),
|
||||
}
|
||||
let mut settle_cycle = 0;
|
||||
let mut run_extern_modules = true;
|
||||
loop {
|
||||
assert!(settle_cycle < 100000, "settle(): took too many steps");
|
||||
settle_cycle += 1;
|
||||
let next_wait_target = match this.get_ready_to_run_set(&mut ready_to_run_set) {
|
||||
Some(next_wait_target) if next_wait_target <= run_target => next_wait_target,
|
||||
_ => break,
|
||||
};
|
||||
match next_wait_target {
|
||||
WaitTarget::Settle => {}
|
||||
WaitTarget::Instant(instant) => {
|
||||
settle_cycle = 0;
|
||||
this.set_instant_no_sim(instant);
|
||||
}
|
||||
return;
|
||||
}
|
||||
this.state.setup_call(0);
|
||||
if this.breakpoints.is_some() {
|
||||
loop {
|
||||
let this = &mut *this;
|
||||
match this
|
||||
.state
|
||||
.run(this.breakpoints.as_mut().expect("just checked"))
|
||||
if run_extern_modules {
|
||||
for module_index in ready_to_run_set.extern_modules_ready_to_run.drain(..) {
|
||||
let extern_module = &mut this.extern_modules[module_index];
|
||||
extern_module.wait_target = None;
|
||||
let mut generator = if !extern_module.module_state.did_initial_settle {
|
||||
let sim = extern_module.sim;
|
||||
let io_ty = extern_module.io_ty;
|
||||
drop(this);
|
||||
Box::into_pin(sim.run(ExternModuleSimulationState {
|
||||
sim_impl: this_ref.clone(),
|
||||
module_index,
|
||||
io_ty,
|
||||
}))
|
||||
} else if let Some(generator) = extern_module.running_generator.take() {
|
||||
drop(this);
|
||||
generator
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
let generator = match generator
|
||||
.as_mut()
|
||||
.poll(&mut std::task::Context::from_waker(&generator_waker))
|
||||
{
|
||||
RunResult::Break(break_action) => {
|
||||
println!(
|
||||
"hit breakpoint at:\n{:?}",
|
||||
this.state.debug_insn_at(this.state.pc),
|
||||
);
|
||||
match break_action {
|
||||
BreakAction::DumpStateAndContinue => {
|
||||
println!("{this:#?}");
|
||||
}
|
||||
BreakAction::Continue => {}
|
||||
}
|
||||
}
|
||||
RunResult::Return(()) => break,
|
||||
Poll::Ready(()) => None,
|
||||
Poll::Pending => Some(generator),
|
||||
};
|
||||
this = this_ref.borrow_mut();
|
||||
this.extern_modules[module_index]
|
||||
.module_state
|
||||
.did_initial_settle = true;
|
||||
if !this.extern_modules[module_index]
|
||||
.module_state
|
||||
.uninitialized_ios
|
||||
.is_empty()
|
||||
{
|
||||
panic!(
|
||||
"extern module didn't initialize all outputs before \
|
||||
waiting, settling, or reading any inputs: {}",
|
||||
this.extern_modules[module_index].sim.source_location
|
||||
);
|
||||
}
|
||||
this.extern_modules[module_index].running_generator = generator;
|
||||
}
|
||||
}
|
||||
if ready_to_run_set.state_ready_to_run {
|
||||
this.state_ready_to_run = false;
|
||||
run_extern_modules = true;
|
||||
this.state.setup_call(0);
|
||||
if this.breakpoints.is_some() {
|
||||
loop {
|
||||
let this = &mut *this;
|
||||
match this
|
||||
.state
|
||||
.run(this.breakpoints.as_mut().expect("just checked"))
|
||||
{
|
||||
RunResult::Break(break_action) => {
|
||||
println!(
|
||||
"hit breakpoint at:\n{:?}",
|
||||
this.state.debug_insn_at(this.state.pc),
|
||||
);
|
||||
match break_action {
|
||||
BreakAction::DumpStateAndContinue => {
|
||||
println!("{this:#?}");
|
||||
}
|
||||
BreakAction::Continue => {}
|
||||
}
|
||||
}
|
||||
RunResult::Return(()) => break,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let RunResult::Return(()) = this.state.run(());
|
||||
}
|
||||
if this
|
||||
.clocks_triggered
|
||||
.iter()
|
||||
.any(|i| this.state.small_slots[*i] != 0)
|
||||
{
|
||||
this.state_ready_to_run = true;
|
||||
// wait for clocks to settle before running extern modules again
|
||||
run_extern_modules = false;
|
||||
}
|
||||
} else {
|
||||
let RunResult::Return(()) = this.state.run(());
|
||||
}
|
||||
if this.main_module.did_initial_settle {
|
||||
this.read_traces::<false>();
|
||||
|
@ -7286,10 +7422,6 @@ impl SimulationImpl {
|
|||
this.state.memory_write_log.sort_unstable();
|
||||
this.state.memory_write_log.dedup();
|
||||
this.main_module.did_initial_settle = true;
|
||||
this.needs_settle = this
|
||||
.clocks_triggered
|
||||
.iter()
|
||||
.any(|i| this.state.small_slots[*i] != 0);
|
||||
this.for_each_trace_writer_storing_error(|this, trace_writer_state| {
|
||||
Ok(match trace_writer_state {
|
||||
TraceWriterState::Decls(trace_writer_decls) => TraceWriterState::Running(
|
||||
|
@ -7310,7 +7442,14 @@ impl SimulationImpl {
|
|||
});
|
||||
this.state.memory_write_log.clear();
|
||||
}
|
||||
panic!("settle(): took too many steps");
|
||||
match run_target {
|
||||
WaitTarget::Settle => {}
|
||||
WaitTarget::Instant(instant) => this.set_instant_no_sim(instant),
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn settle(this_ref: &Rc<RefCell<Self>>) {
|
||||
Self::run_until(this_ref, WaitTarget::Settle);
|
||||
}
|
||||
fn get_module(&self, which_module: WhichModule) -> &SimulationModuleState {
|
||||
match which_module {
|
||||
|
@ -7342,7 +7481,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(io, which_module);
|
||||
self.needs_settle = true;
|
||||
self.state_ready_to_run = true;
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => {
|
||||
self.state.small_slots[compiled_value.range.small_slots.start] = value as _;
|
||||
|
@ -7374,7 +7513,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(Expr::canonical(io), which_module);
|
||||
self.needs_settle = true;
|
||||
self.state_ready_to_run = true;
|
||||
let value: BigInt = value.into();
|
||||
match compiled_value.range.len() {
|
||||
TypeLen::A_SMALL_SLOT => {
|
||||
|
@ -7495,7 +7634,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(io, which_module);
|
||||
self.needs_settle = true;
|
||||
self.state_ready_to_run = true;
|
||||
assert_eq!(Expr::ty(io), value.ty());
|
||||
Self::read_write_sim_value_helper(
|
||||
&mut self.state,
|
||||
|
@ -7531,7 +7670,6 @@ impl SimulationImpl {
|
|||
MaybeNeedsSettle::NoSettleNeeded(v) => v,
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
async fn yield_settle_if_needed<F, O>(
|
||||
this_ref: &Rc<RefCell<Self>>,
|
||||
module_index: usize,
|
||||
|
@ -7713,18 +7851,22 @@ impl<T: BundleType> fmt::Debug for Simulation<T> {
|
|||
}
|
||||
|
||||
macro_rules! impl_simulation_methods {
|
||||
(async_await = ($($async:tt, $await:tt)?)) => {
|
||||
#[track_caller]
|
||||
pub $($async)? fn read_bool_or_int<I: BoolOrIntType>(&mut self, io: Expr<I>) -> I::Value {
|
||||
let retval = self
|
||||
(
|
||||
async_await = ($($async:tt, $await:tt)?),
|
||||
track_caller = ($(#[$track_caller:tt])?),
|
||||
which_module = |$self:ident| $which_module:expr,
|
||||
) => {
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn read_bool_or_int<I: BoolOrIntType>(&mut $self, io: Expr<I>) -> I::Value {
|
||||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bool_or_int(io, WhichModule::Main);
|
||||
self.settle_if_needed(retval)$(.$await)?
|
||||
.read_bool_or_int(io, $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
#[track_caller]
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn write_bool_or_int<I: BoolOrIntType>(
|
||||
&mut self,
|
||||
&mut $self,
|
||||
io: Expr<I>,
|
||||
value: impl ToExpr<Type = I>,
|
||||
) {
|
||||
|
@ -7733,68 +7875,68 @@ macro_rules! impl_simulation_methods {
|
|||
let value = value
|
||||
.to_literal_bits()
|
||||
.expect("the value that is being written to an input must be a literal");
|
||||
self.sim_impl.borrow_mut().write_bool_or_int(
|
||||
$self.sim_impl.borrow_mut().write_bool_or_int(
|
||||
io,
|
||||
I::bits_to_value(Cow::Borrowed(&value)),
|
||||
WhichModule::Main,
|
||||
$which_module,
|
||||
);
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn write_clock(&mut self, io: Expr<Clock>, value: bool) {
|
||||
self.sim_impl
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn write_clock(&mut $self, io: Expr<Clock>, value: bool) {
|
||||
$self.sim_impl
|
||||
.borrow_mut()
|
||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
||||
.write_bit(Expr::canonical(io), value, $which_module);
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn read_clock(&mut self, io: Expr<Clock>) -> bool {
|
||||
let retval = self
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn read_clock(&mut $self, io: Expr<Clock>) -> bool {
|
||||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
||||
self.settle_if_needed(retval)$(.$await)?
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn write_bool(&mut self, io: Expr<Bool>, value: bool) {
|
||||
self.sim_impl
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn write_bool(&mut $self, io: Expr<Bool>, value: bool) {
|
||||
$self.sim_impl
|
||||
.borrow_mut()
|
||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
||||
.write_bit(Expr::canonical(io), value, $which_module);
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn read_bool(&mut self, io: Expr<Bool>) -> bool {
|
||||
let retval = self
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn read_bool(&mut $self, io: Expr<Bool>) -> bool {
|
||||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
||||
self.settle_if_needed(retval)$(.$await)?
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn write_reset<R: ResetType>(&mut self, io: Expr<R>, value: bool) {
|
||||
self.sim_impl
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn write_reset<R: ResetType>(&mut $self, io: Expr<R>, value: bool) {
|
||||
$self.sim_impl
|
||||
.borrow_mut()
|
||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
||||
.write_bit(Expr::canonical(io), value, $which_module);
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn read_reset<R: ResetType>(&mut self, io: Expr<R>) -> bool {
|
||||
let retval = self
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn read_reset<R: ResetType>(&mut $self, io: Expr<R>) -> bool {
|
||||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
||||
self.settle_if_needed(retval)$(.$await)?
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn read<IO: Type>(&mut self, io: Expr<IO>) -> SimValue<IO> {
|
||||
let retval = self
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn read<IO: Type>(&mut $self, io: Expr<IO>) -> SimValue<IO> {
|
||||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read(Expr::canonical(io), WhichModule::Main);
|
||||
SimValue::from_canonical(self.settle_if_needed(retval)$(.$await)?)
|
||||
.read(Expr::canonical(io), $which_module);
|
||||
SimValue::from_canonical($self.settle_if_needed(retval)$(.$await)?)
|
||||
}
|
||||
#[track_caller]
|
||||
pub $($async)? fn write<IO: Type, V: ToSimValue<IO>>(&mut self, io: Expr<IO>, value: V) {
|
||||
self.sim_impl.borrow_mut().write(
|
||||
$(#[$track_caller])?
|
||||
pub $($async)? fn write<IO: Type, V: ToSimValue<IO>>(&mut $self, io: Expr<IO>, value: V) {
|
||||
$self.sim_impl.borrow_mut().write(
|
||||
Expr::canonical(io),
|
||||
value.into_sim_value(Expr::ty(io)).into_canonical(),
|
||||
WhichModule::Main,
|
||||
$which_module,
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -7855,7 +7997,11 @@ impl<T: BundleType> Simulation<T> {
|
|||
{
|
||||
SimulationImpl::settle_if_needed(&self.sim_impl, v)
|
||||
}
|
||||
impl_simulation_methods!(async_await = ());
|
||||
impl_simulation_methods!(
|
||||
async_await = (),
|
||||
track_caller = (#[track_caller]),
|
||||
which_module = |self| WhichModule::Main,
|
||||
);
|
||||
#[doc(hidden)]
|
||||
/// This is explicitly unstable and may be changed/removed at any time
|
||||
pub fn set_breakpoints_unstable(&mut self, pcs: HashSet<usize>, trace: bool) {
|
||||
|
@ -7913,12 +8059,10 @@ impl<T: BundleType> ExternModuleSimulationState<T> {
|
|||
io_ty: T::from_canonical(io_ty.canonical()),
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
pub async fn settle(&mut self) {
|
||||
SimulationImpl::yield_advance_time_or_settle(self.sim_impl.clone(), self.module_index, None)
|
||||
.await
|
||||
}
|
||||
#[track_caller]
|
||||
pub async fn advance_time(&mut self, duration: SimDuration) {
|
||||
SimulationImpl::yield_advance_time_or_settle(
|
||||
self.sim_impl.clone(),
|
||||
|
@ -7927,14 +8071,17 @@ impl<T: BundleType> ExternModuleSimulationState<T> {
|
|||
)
|
||||
.await
|
||||
}
|
||||
#[track_caller]
|
||||
async fn settle_if_needed<F, O>(&mut self, v: MaybeNeedsSettle<F, O>) -> O
|
||||
where
|
||||
for<'a> F: MaybeNeedsSettleFn<&'a mut interpreter::State, Output = O>,
|
||||
{
|
||||
SimulationImpl::yield_settle_if_needed(&self.sim_impl, self.module_index, v).await
|
||||
}
|
||||
impl_simulation_methods!(async_await = (async, await));
|
||||
impl_simulation_methods!(
|
||||
async_await = (async, await),
|
||||
track_caller = (),
|
||||
which_module = |self| WhichModule::Extern { module_index: self.module_index },
|
||||
);
|
||||
}
|
||||
|
||||
pub trait ExternModuleSimGenerator:
|
||||
|
|
|
@ -5,11 +5,14 @@ use fayalite::{
|
|||
int::UIntValue,
|
||||
prelude::*,
|
||||
reset::ResetType,
|
||||
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation, ToSimValue},
|
||||
sim::{
|
||||
time::SimDuration, vcd::VcdWriterDecls, ExternModuleSimGenerator,
|
||||
ExternModuleSimulationState, Simulation, ToSimValue,
|
||||
},
|
||||
ty::StaticType,
|
||||
util::RcWriter,
|
||||
};
|
||||
use std::num::NonZeroUsize;
|
||||
use std::{future::IntoFuture, num::NonZeroUsize};
|
||||
|
||||
#[hdl_module(outline_generated)]
|
||||
pub fn connect_const() {
|
||||
|
@ -1443,3 +1446,61 @@ fn test_conditional_assignment_last() {
|
|||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl_module(outline_generated, extern)]
|
||||
pub fn extern_module() {
|
||||
#[hdl]
|
||||
let i: Bool = m.input();
|
||||
#[hdl]
|
||||
let o: Bool = m.output();
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Debug)]
|
||||
struct Sim {
|
||||
i: Expr<Bool>,
|
||||
o: Expr<Bool>,
|
||||
}
|
||||
impl ExternModuleSimGenerator for Sim {
|
||||
type IOType = extern_module;
|
||||
|
||||
fn run<'a>(
|
||||
&'a self,
|
||||
mut sim: ExternModuleSimulationState<Self::IOType>,
|
||||
) -> impl IntoFuture<Output = ()> + 'a {
|
||||
let Self { i, o } = *self;
|
||||
async move {
|
||||
sim.write(o, true).await;
|
||||
sim.advance_time(SimDuration::from_nanos(500)).await;
|
||||
let mut invert = false;
|
||||
loop {
|
||||
sim.advance_time(SimDuration::from_micros(1)).await;
|
||||
let v = sim.read_bool(i).await;
|
||||
sim.write(o, v ^ invert).await;
|
||||
invert = !invert;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
m.extern_module_simulation(Sim { i, o });
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extern_module() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let mut sim = Simulation::new(extern_module());
|
||||
let mut writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
sim.write(sim.io().i, false);
|
||||
sim.advance_time(SimDuration::from_micros(10));
|
||||
sim.write(sim.io().i, true);
|
||||
sim.advance_time(SimDuration::from_micros(10));
|
||||
sim.flush_traces().unwrap();
|
||||
let vcd = String::from_utf8(writer.take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
if vcd != include_str!("sim/expected/extern_module.vcd") {
|
||||
panic!();
|
||||
}
|
||||
let sim_debug = format!("{sim:#?}");
|
||||
println!("#######\n{sim_debug}\n#######");
|
||||
if sim_debug != include_str!("sim/expected/extern_module.txt") {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -819,7 +819,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "array_rw",
|
||||
children: [
|
||||
|
|
|
@ -115,7 +115,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "conditional_assignment_last",
|
||||
children: [
|
||||
|
|
|
@ -91,7 +91,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "connect_const",
|
||||
children: [
|
||||
|
|
|
@ -134,7 +134,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "connect_const_reset",
|
||||
children: [
|
||||
|
|
|
@ -254,7 +254,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "counter",
|
||||
children: [
|
||||
|
|
|
@ -235,7 +235,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "counter",
|
||||
children: [
|
||||
|
|
|
@ -95,7 +95,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "duplicate_names",
|
||||
children: [
|
||||
|
|
|
@ -1336,7 +1336,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "enums",
|
||||
children: [
|
||||
|
|
224
crates/fayalite/tests/sim/expected/extern_module.txt
Normal file
224
crates/fayalite/tests/sim/expected/extern_module.txt
Normal file
|
@ -0,0 +1,224 @@
|
|||
Simulation {
|
||||
state: State {
|
||||
insns: Insns {
|
||||
state_layout: StateLayout {
|
||||
ty: TypeLayout {
|
||||
small_slots: StatePartLayout<SmallSlots> {
|
||||
len: 0,
|
||||
debug_data: [],
|
||||
..
|
||||
},
|
||||
big_slots: StatePartLayout<BigSlots> {
|
||||
len: 2,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module: extern_module).extern_module::i",
|
||||
ty: Bool,
|
||||
},
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module: extern_module).extern_module::o",
|
||||
ty: Bool,
|
||||
},
|
||||
],
|
||||
..
|
||||
},
|
||||
},
|
||||
memories: StatePartLayout<Memories> {
|
||||
len: 0,
|
||||
debug_data: [],
|
||||
layout_data: [],
|
||||
..
|
||||
},
|
||||
},
|
||||
insns: [
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
0: Return,
|
||||
],
|
||||
..
|
||||
},
|
||||
pc: 0,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
small_slots: StatePart {
|
||||
value: [],
|
||||
},
|
||||
big_slots: StatePart {
|
||||
value: [
|
||||
1,
|
||||
1,
|
||||
],
|
||||
},
|
||||
},
|
||||
io: Instance {
|
||||
name: <simulator>::extern_module,
|
||||
instantiated: Module {
|
||||
name: extern_module,
|
||||
..
|
||||
},
|
||||
},
|
||||
main_module: SimulationModuleState {
|
||||
base_targets: [
|
||||
Instance {
|
||||
name: <simulator>::extern_module,
|
||||
instantiated: Module {
|
||||
name: extern_module,
|
||||
..
|
||||
},
|
||||
}.i,
|
||||
Instance {
|
||||
name: <simulator>::extern_module,
|
||||
instantiated: Module {
|
||||
name: extern_module,
|
||||
..
|
||||
},
|
||||
}.o,
|
||||
],
|
||||
uninitialized_ios: {},
|
||||
io_targets: {
|
||||
Instance {
|
||||
name: <simulator>::extern_module,
|
||||
instantiated: Module {
|
||||
name: extern_module,
|
||||
..
|
||||
},
|
||||
}.i,
|
||||
Instance {
|
||||
name: <simulator>::extern_module,
|
||||
instantiated: Module {
|
||||
name: extern_module,
|
||||
..
|
||||
},
|
||||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
module_state: SimulationModuleState {
|
||||
base_targets: [
|
||||
ModuleIO {
|
||||
name: extern_module::i,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module::o,
|
||||
is_input: false,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
],
|
||||
uninitialized_ios: {},
|
||||
io_targets: {
|
||||
ModuleIO {
|
||||
name: extern_module::i,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module::o,
|
||||
is_input: false,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
},
|
||||
io_ty: Bundle {
|
||||
#[hdl(flip)] /* offset = 0 */
|
||||
i: Bool,
|
||||
/* offset = 1 */
|
||||
o: Bool,
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: Sim {
|
||||
i: ModuleIO {
|
||||
name: extern_module::i,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
o: ModuleIO {
|
||||
name: extern_module::o,
|
||||
is_input: false,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
},
|
||||
source_location: SourceLocation(
|
||||
module-XXXXXXXXXX.rs:4:1,
|
||||
),
|
||||
_phantom: PhantomData<fayalite::bundle::Bundle>,
|
||||
},
|
||||
running_generator: Some(
|
||||
...,
|
||||
),
|
||||
wait_target: Some(
|
||||
Instant(
|
||||
20.500000000000 μs,
|
||||
),
|
||||
),
|
||||
},
|
||||
],
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "extern_module",
|
||||
children: [
|
||||
TraceModuleIO {
|
||||
name: "i",
|
||||
child: TraceBool {
|
||||
location: TraceScalarId(0),
|
||||
name: "i",
|
||||
flow: Source,
|
||||
},
|
||||
ty: Bool,
|
||||
flow: Source,
|
||||
},
|
||||
TraceModuleIO {
|
||||
name: "o",
|
||||
child: TraceBool {
|
||||
location: TraceScalarId(1),
|
||||
name: "o",
|
||||
flow: Sink,
|
||||
},
|
||||
ty: Bool,
|
||||
flow: Sink,
|
||||
},
|
||||
],
|
||||
},
|
||||
traces: [
|
||||
SimTrace {
|
||||
id: TraceScalarId(0),
|
||||
kind: BigBool {
|
||||
index: StatePartIndex<BigSlots>(0),
|
||||
},
|
||||
state: 0x1,
|
||||
last_state: 0x1,
|
||||
},
|
||||
SimTrace {
|
||||
id: TraceScalarId(1),
|
||||
kind: BigBool {
|
||||
index: StatePartIndex<BigSlots>(1),
|
||||
},
|
||||
state: 0x1,
|
||||
last_state: 0x1,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
finished_init: true,
|
||||
timescale: 1 ps,
|
||||
..
|
||||
},
|
||||
),
|
||||
],
|
||||
instant: 20 μs,
|
||||
clocks_triggered: [],
|
||||
..
|
||||
}
|
51
crates/fayalite/tests/sim/expected/extern_module.vcd
Normal file
51
crates/fayalite/tests/sim/expected/extern_module.vcd
Normal file
|
@ -0,0 +1,51 @@
|
|||
$timescale 1 ps $end
|
||||
$scope module extern_module $end
|
||||
$var wire 1 ! i $end
|
||||
$var wire 1 " o $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$dumpvars
|
||||
0!
|
||||
1"
|
||||
$end
|
||||
#500000
|
||||
#1500000
|
||||
0"
|
||||
#2500000
|
||||
1"
|
||||
#3500000
|
||||
0"
|
||||
#4500000
|
||||
1"
|
||||
#5500000
|
||||
0"
|
||||
#6500000
|
||||
1"
|
||||
#7500000
|
||||
0"
|
||||
#8500000
|
||||
1"
|
||||
#9500000
|
||||
0"
|
||||
#10000000
|
||||
1!
|
||||
#10500000
|
||||
#11500000
|
||||
1"
|
||||
#12500000
|
||||
0"
|
||||
#13500000
|
||||
1"
|
||||
#14500000
|
||||
0"
|
||||
#15500000
|
||||
1"
|
||||
#16500000
|
||||
0"
|
||||
#17500000
|
||||
1"
|
||||
#18500000
|
||||
0"
|
||||
#19500000
|
||||
1"
|
||||
#20000000
|
|
@ -712,7 +712,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "memories",
|
||||
children: [
|
||||
|
|
|
@ -670,7 +670,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "memories2",
|
||||
children: [
|
||||
|
|
|
@ -1754,7 +1754,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "memories3",
|
||||
children: [
|
||||
|
|
|
@ -267,7 +267,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "mod1",
|
||||
children: [
|
||||
|
|
|
@ -330,7 +330,7 @@ Simulation {
|
|||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [],
|
||||
needs_settle: false,
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "shift_register",
|
||||
children: [
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue