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,
|
memory::PortKind,
|
||||||
module::{
|
module::{
|
||||||
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, Id, InstantiatedModule,
|
transform::deduce_resets::deduce_resets, AnnotatedModuleIO, Block, ExternModuleBody, Id,
|
||||||
ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect, StmtDeclaration,
|
InstantiatedModule, ModuleBody, NameId, NormalModuleBody, ScopedNameId, Stmt, StmtConnect,
|
||||||
StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire, TargetInInstantiatedModule,
|
StmtDeclaration, StmtFormal, StmtIf, StmtInstance, StmtMatch, StmtReg, StmtWire,
|
||||||
|
TargetInInstantiatedModule,
|
||||||
},
|
},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reset::{ResetType, ResetTypeDispatch},
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct Compiler {
|
pub struct Compiler {
|
||||||
insns: Insns<InsnsBuilding>,
|
insns: Insns<InsnsBuilding>,
|
||||||
original_base_module: Interned<Module<Bundle>>,
|
original_base_module: Interned<Module<Bundle>>,
|
||||||
base_module: Interned<Module<Bundle>>,
|
base_module: Interned<Module<Bundle>>,
|
||||||
modules: HashMap<InstantiatedModule, CompiledModule>,
|
modules: HashMap<InstantiatedModule, CompiledModule>,
|
||||||
|
extern_modules: Vec<CompiledExternModule>,
|
||||||
compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue<CanonicalType>>,
|
compiled_values: HashMap<TargetInInstantiatedModule, CompiledValue<CanonicalType>>,
|
||||||
compiled_exprs: HashMap<Expr<CanonicalType>, CompiledExpr<CanonicalType>>,
|
compiled_exprs: HashMap<Expr<CanonicalType>, CompiledExpr<CanonicalType>>,
|
||||||
compiled_exprs_to_values: HashMap<CompiledExpr<CanonicalType>, CompiledValue<CanonicalType>>,
|
compiled_exprs_to_values: HashMap<CompiledExpr<CanonicalType>, CompiledValue<CanonicalType>>,
|
||||||
|
@ -1665,6 +1675,7 @@ impl Compiler {
|
||||||
original_base_module,
|
original_base_module,
|
||||||
base_module,
|
base_module,
|
||||||
modules: HashMap::new(),
|
modules: HashMap::new(),
|
||||||
|
extern_modules: Vec::new(),
|
||||||
compiled_values: HashMap::new(),
|
compiled_values: HashMap::new(),
|
||||||
compiled_exprs: HashMap::new(),
|
compiled_exprs: HashMap::new(),
|
||||||
compiled_exprs_to_values: HashMap::new(),
|
compiled_exprs_to_values: HashMap::new(),
|
||||||
|
@ -4690,8 +4701,28 @@ impl Compiler {
|
||||||
ModuleBody::Normal(NormalModuleBody { body }) => {
|
ModuleBody::Normal(NormalModuleBody { body }) => {
|
||||||
self.compile_block(module, body, Interned::default(), &mut trace_decls);
|
self.compile_block(module, body, Interned::default(), &mut trace_decls);
|
||||||
}
|
}
|
||||||
ModuleBody::Extern(_extern_module_body) => {
|
ModuleBody::Extern(ExternModuleBody {
|
||||||
todo!("simulating extern module: {:?}", module);
|
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 {
|
let hashbrown::hash_map::Entry::Vacant(entry) = self.modules.entry(*module) else {
|
||||||
|
@ -4972,6 +5003,7 @@ impl Compiler {
|
||||||
Compiled {
|
Compiled {
|
||||||
insns: Insns::from(self.insns).intern_sized(),
|
insns: Insns::from(self.insns).intern_sized(),
|
||||||
base_module,
|
base_module,
|
||||||
|
extern_modules: Intern::intern_owned(self.extern_modules),
|
||||||
io: Instance::new_unchecked(
|
io: Instance::new_unchecked(
|
||||||
ScopedNameId(
|
ScopedNameId(
|
||||||
NameId("<simulator>".intern(), Id::new()),
|
NameId("<simulator>".intern(), Id::new()),
|
||||||
|
@ -5004,6 +5036,7 @@ struct CompiledModule {
|
||||||
pub struct Compiled<T: BundleType> {
|
pub struct Compiled<T: BundleType> {
|
||||||
insns: Interned<Insns<InsnsBuildingDone>>,
|
insns: Interned<Insns<InsnsBuildingDone>>,
|
||||||
base_module: CompiledModule,
|
base_module: CompiledModule,
|
||||||
|
extern_modules: Interned<[CompiledExternModule]>,
|
||||||
io: Instance<T>,
|
io: Instance<T>,
|
||||||
traces: SimTraces<Interned<[SimTrace<SimTraceKind, ()>]>>,
|
traces: SimTraces<Interned<[SimTrace<SimTraceKind, ()>]>>,
|
||||||
trace_memories: Interned<[(StatePartIndex<StatePartKindMemories>, TraceMem)]>,
|
trace_memories: Interned<[(StatePartIndex<StatePartKindMemories>, TraceMem)]>,
|
||||||
|
@ -5018,6 +5051,7 @@ impl<T: BundleType> Compiled<T> {
|
||||||
let Self {
|
let Self {
|
||||||
insns,
|
insns,
|
||||||
base_module,
|
base_module,
|
||||||
|
extern_modules,
|
||||||
io,
|
io,
|
||||||
traces,
|
traces,
|
||||||
trace_memories,
|
trace_memories,
|
||||||
|
@ -5026,6 +5060,7 @@ impl<T: BundleType> Compiled<T> {
|
||||||
Compiled {
|
Compiled {
|
||||||
insns,
|
insns,
|
||||||
base_module,
|
base_module,
|
||||||
|
extern_modules,
|
||||||
io: Instance::from_canonical(io.canonical()),
|
io: Instance::from_canonical(io.canonical()),
|
||||||
traces,
|
traces,
|
||||||
trace_memories,
|
trace_memories,
|
||||||
|
@ -5036,6 +5071,7 @@ impl<T: BundleType> Compiled<T> {
|
||||||
let Compiled {
|
let Compiled {
|
||||||
insns,
|
insns,
|
||||||
base_module,
|
base_module,
|
||||||
|
extern_modules,
|
||||||
io,
|
io,
|
||||||
traces,
|
traces,
|
||||||
trace_memories,
|
trace_memories,
|
||||||
|
@ -5044,6 +5080,7 @@ impl<T: BundleType> Compiled<T> {
|
||||||
Self {
|
Self {
|
||||||
insns,
|
insns,
|
||||||
base_module,
|
base_module,
|
||||||
|
extern_modules,
|
||||||
io: Instance::from_canonical(io.canonical()),
|
io: Instance::from_canonical(io.canonical()),
|
||||||
traces,
|
traces,
|
||||||
trace_memories,
|
trace_memories,
|
||||||
|
@ -6785,6 +6822,7 @@ impl Ord for WaitTarget {
|
||||||
|
|
||||||
struct SimulationExternModuleState {
|
struct SimulationExternModuleState {
|
||||||
module_state: SimulationModuleState,
|
module_state: SimulationModuleState,
|
||||||
|
io_ty: Bundle,
|
||||||
sim: ExternModuleSimulation<Bundle>,
|
sim: ExternModuleSimulation<Bundle>,
|
||||||
running_generator: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
running_generator: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||||
wait_target: Option<WaitTarget>,
|
wait_target: Option<WaitTarget>,
|
||||||
|
@ -6794,12 +6832,14 @@ impl fmt::Debug for SimulationExternModuleState {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
let Self {
|
let Self {
|
||||||
module_state,
|
module_state,
|
||||||
|
io_ty,
|
||||||
sim,
|
sim,
|
||||||
running_generator,
|
running_generator,
|
||||||
wait_target,
|
wait_target,
|
||||||
} = self;
|
} = self;
|
||||||
f.debug_struct("SimulationExternModuleState")
|
f.debug_struct("SimulationExternModuleState")
|
||||||
.field("module_state", module_state)
|
.field("module_state", module_state)
|
||||||
|
.field("io_ty", io_ty)
|
||||||
.field("sim", sim)
|
.field("sim", sim)
|
||||||
.field(
|
.field(
|
||||||
"running_generator",
|
"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 {
|
struct SimulationImpl {
|
||||||
state: interpreter::State,
|
state: interpreter::State,
|
||||||
io: Expr<Bundle>,
|
io: Expr<Bundle>,
|
||||||
main_module: SimulationModuleState,
|
main_module: SimulationModuleState,
|
||||||
extern_modules: Box<[SimulationExternModuleState]>,
|
extern_modules: Box<[SimulationExternModuleState]>,
|
||||||
needs_settle: bool,
|
state_ready_to_run: bool,
|
||||||
trace_decls: TraceModule,
|
trace_decls: TraceModule,
|
||||||
traces: SimTraces<Box<[SimTrace<SimTraceKind, BitVec>]>>,
|
traces: SimTraces<Box<[SimTrace<SimTraceKind, BitVec>]>>,
|
||||||
trace_memories: HashMap<StatePartIndex<StatePartKindMemories>, TraceMem>,
|
trace_memories: HashMap<StatePartIndex<StatePartKindMemories>, TraceMem>,
|
||||||
|
@ -6923,7 +6980,7 @@ impl SimulationImpl {
|
||||||
io: self_io,
|
io: self_io,
|
||||||
main_module,
|
main_module,
|
||||||
extern_modules,
|
extern_modules,
|
||||||
needs_settle,
|
state_ready_to_run,
|
||||||
trace_decls,
|
trace_decls,
|
||||||
traces,
|
traces,
|
||||||
trace_memories,
|
trace_memories,
|
||||||
|
@ -6938,7 +6995,7 @@ impl SimulationImpl {
|
||||||
.field("io", io.unwrap_or(self_io))
|
.field("io", io.unwrap_or(self_io))
|
||||||
.field("main_module", main_module)
|
.field("main_module", main_module)
|
||||||
.field("extern_modules", extern_modules)
|
.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("trace_decls", trace_decls)
|
||||||
.field("traces", traces)
|
.field("traces", traces)
|
||||||
.field("trace_memories", trace_memories)
|
.field("trace_memories", trace_memories)
|
||||||
|
@ -6949,8 +7006,27 @@ impl SimulationImpl {
|
||||||
}
|
}
|
||||||
fn new(compiled: Compiled<Bundle>) -> Self {
|
fn new(compiled: Compiled<Bundle>) -> Self {
|
||||||
let io_target = Target::from(compiled.io);
|
let io_target = Target::from(compiled.io);
|
||||||
// TODO: add extern_modules
|
let extern_modules = Box::from_iter(compiled.extern_modules.iter().map(
|
||||||
let extern_modules: Box<[SimulationExternModuleState]> = Box::new([]);
|
|&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 {
|
Self {
|
||||||
state: State::new(compiled.insns),
|
state: State::new(compiled.insns),
|
||||||
io: compiled.io.to_expr(),
|
io: compiled.io.to_expr(),
|
||||||
|
@ -6972,7 +7048,7 @@ impl SimulationImpl {
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
extern_modules,
|
extern_modules,
|
||||||
needs_settle: true,
|
state_ready_to_run: true,
|
||||||
trace_decls: compiled.base_module.trace_decls,
|
trace_decls: compiled.base_module.trace_decls,
|
||||||
traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map(
|
traces: SimTraces(Box::from_iter(compiled.traces.0.iter().map(
|
||||||
|&SimTrace {
|
|&SimTrace {
|
||||||
|
@ -7129,20 +7205,9 @@ impl SimulationImpl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn advance_time(this: &Rc<RefCell<Self>>, duration: SimDuration) {
|
fn advance_time(this_ref: &Rc<RefCell<Self>>, duration: SimDuration) {
|
||||||
Self::settle(this);
|
let instant = this_ref.borrow().instant + duration;
|
||||||
let mut this = this.borrow_mut();
|
Self::run_until(this_ref, WaitTarget::Instant(instant));
|
||||||
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)
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn yield_advance_time_or_settle(
|
fn yield_advance_time_or_settle(
|
||||||
|
@ -7197,86 +7262,157 @@ impl SimulationImpl {
|
||||||
target,
|
target,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn get_ready_external_modules(&mut self, run_list: &mut Vec<usize>) -> Option<WaitTarget> {
|
/// returns the next `WaitTarget` and the set of things ready to run then.
|
||||||
run_list.clear();
|
fn get_ready_to_run_set(&self, ready_to_run_set: &mut ReadyToRunSet) -> Option<WaitTarget> {
|
||||||
let mut iter = self.extern_modules.iter_mut().enumerate().filter_map(
|
ready_to_run_set.clear();
|
||||||
|(module_index, extern_module)| Some((module_index, extern_module.wait_target?)),
|
let mut wait_target = None;
|
||||||
);
|
if self.state_ready_to_run {
|
||||||
let (first_module_index, mut wait_target) = iter.next()?;
|
ready_to_run_set.state_ready_to_run = true;
|
||||||
run_list.push(first_module_index);
|
wait_target = Some(WaitTarget::Settle);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
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]
|
#[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 this = this_ref.borrow_mut();
|
||||||
|
let mut ready_to_run_set = ReadyToRunSet::default();
|
||||||
|
let generator_waker = this.generator_waker.clone();
|
||||||
assert!(
|
assert!(
|
||||||
this.main_module.uninitialized_ios.is_empty(),
|
this.main_module.uninitialized_ios.is_empty(),
|
||||||
"didn't initialize all inputs",
|
"didn't initialize all inputs",
|
||||||
);
|
);
|
||||||
let mut run_list = Vec::new();
|
match run_target {
|
||||||
let generator_waker = this.generator_waker.clone();
|
WaitTarget::Settle => {}
|
||||||
for _ in 0..100000 {
|
WaitTarget::Instant(run_target) => assert!(run_target >= this.instant),
|
||||||
if !this.needs_settle {
|
}
|
||||||
if let Some(wait_target) = this.get_ready_external_modules(&mut run_list) {
|
let mut settle_cycle = 0;
|
||||||
if wait_target > WaitTarget::Instant(this.instant) {
|
let mut run_extern_modules = true;
|
||||||
return;
|
loop {
|
||||||
}
|
assert!(settle_cycle < 100000, "settle(): took too many steps");
|
||||||
for module_index in run_list.drain(..) {
|
settle_cycle += 1;
|
||||||
this.extern_modules[module_index].wait_target = None;
|
let next_wait_target = match this.get_ready_to_run_set(&mut ready_to_run_set) {
|
||||||
let Some(mut generator) =
|
Some(next_wait_target) if next_wait_target <= run_target => next_wait_target,
|
||||||
this.extern_modules[module_index].running_generator.take()
|
_ => break,
|
||||||
else {
|
};
|
||||||
continue;
|
match next_wait_target {
|
||||||
};
|
WaitTarget::Settle => {}
|
||||||
drop(this);
|
WaitTarget::Instant(instant) => {
|
||||||
let generator = match generator
|
settle_cycle = 0;
|
||||||
.as_mut()
|
this.set_instant_no_sim(instant);
|
||||||
.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;
|
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
this.state.setup_call(0);
|
if run_extern_modules {
|
||||||
if this.breakpoints.is_some() {
|
for module_index in ready_to_run_set.extern_modules_ready_to_run.drain(..) {
|
||||||
loop {
|
let extern_module = &mut this.extern_modules[module_index];
|
||||||
let this = &mut *this;
|
extern_module.wait_target = None;
|
||||||
match this
|
let mut generator = if !extern_module.module_state.did_initial_settle {
|
||||||
.state
|
let sim = extern_module.sim;
|
||||||
.run(this.breakpoints.as_mut().expect("just checked"))
|
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) => {
|
Poll::Ready(()) => None,
|
||||||
println!(
|
Poll::Pending => Some(generator),
|
||||||
"hit breakpoint at:\n{:?}",
|
};
|
||||||
this.state.debug_insn_at(this.state.pc),
|
this = this_ref.borrow_mut();
|
||||||
);
|
this.extern_modules[module_index]
|
||||||
match break_action {
|
.module_state
|
||||||
BreakAction::DumpStateAndContinue => {
|
.did_initial_settle = true;
|
||||||
println!("{this:#?}");
|
if !this.extern_modules[module_index]
|
||||||
}
|
.module_state
|
||||||
BreakAction::Continue => {}
|
.uninitialized_ios
|
||||||
}
|
.is_empty()
|
||||||
}
|
{
|
||||||
RunResult::Return(()) => break,
|
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 {
|
if this.main_module.did_initial_settle {
|
||||||
this.read_traces::<false>();
|
this.read_traces::<false>();
|
||||||
|
@ -7286,10 +7422,6 @@ impl SimulationImpl {
|
||||||
this.state.memory_write_log.sort_unstable();
|
this.state.memory_write_log.sort_unstable();
|
||||||
this.state.memory_write_log.dedup();
|
this.state.memory_write_log.dedup();
|
||||||
this.main_module.did_initial_settle = true;
|
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| {
|
this.for_each_trace_writer_storing_error(|this, trace_writer_state| {
|
||||||
Ok(match trace_writer_state {
|
Ok(match trace_writer_state {
|
||||||
TraceWriterState::Decls(trace_writer_decls) => TraceWriterState::Running(
|
TraceWriterState::Decls(trace_writer_decls) => TraceWriterState::Running(
|
||||||
|
@ -7310,7 +7442,14 @@ impl SimulationImpl {
|
||||||
});
|
});
|
||||||
this.state.memory_write_log.clear();
|
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 {
|
fn get_module(&self, which_module: WhichModule) -> &SimulationModuleState {
|
||||||
match which_module {
|
match which_module {
|
||||||
|
@ -7342,7 +7481,7 @@ impl SimulationImpl {
|
||||||
let compiled_value = self
|
let compiled_value = self
|
||||||
.get_module_mut(which_module)
|
.get_module_mut(which_module)
|
||||||
.write_helper(io, which_module);
|
.write_helper(io, which_module);
|
||||||
self.needs_settle = true;
|
self.state_ready_to_run = true;
|
||||||
match compiled_value.range.len() {
|
match compiled_value.range.len() {
|
||||||
TypeLen::A_SMALL_SLOT => {
|
TypeLen::A_SMALL_SLOT => {
|
||||||
self.state.small_slots[compiled_value.range.small_slots.start] = value as _;
|
self.state.small_slots[compiled_value.range.small_slots.start] = value as _;
|
||||||
|
@ -7374,7 +7513,7 @@ impl SimulationImpl {
|
||||||
let compiled_value = self
|
let compiled_value = self
|
||||||
.get_module_mut(which_module)
|
.get_module_mut(which_module)
|
||||||
.write_helper(Expr::canonical(io), which_module);
|
.write_helper(Expr::canonical(io), which_module);
|
||||||
self.needs_settle = true;
|
self.state_ready_to_run = true;
|
||||||
let value: BigInt = value.into();
|
let value: BigInt = value.into();
|
||||||
match compiled_value.range.len() {
|
match compiled_value.range.len() {
|
||||||
TypeLen::A_SMALL_SLOT => {
|
TypeLen::A_SMALL_SLOT => {
|
||||||
|
@ -7495,7 +7634,7 @@ impl SimulationImpl {
|
||||||
let compiled_value = self
|
let compiled_value = self
|
||||||
.get_module_mut(which_module)
|
.get_module_mut(which_module)
|
||||||
.write_helper(io, which_module);
|
.write_helper(io, which_module);
|
||||||
self.needs_settle = true;
|
self.state_ready_to_run = true;
|
||||||
assert_eq!(Expr::ty(io), value.ty());
|
assert_eq!(Expr::ty(io), value.ty());
|
||||||
Self::read_write_sim_value_helper(
|
Self::read_write_sim_value_helper(
|
||||||
&mut self.state,
|
&mut self.state,
|
||||||
|
@ -7531,7 +7670,6 @@ impl SimulationImpl {
|
||||||
MaybeNeedsSettle::NoSettleNeeded(v) => v,
|
MaybeNeedsSettle::NoSettleNeeded(v) => v,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
|
||||||
async fn yield_settle_if_needed<F, O>(
|
async fn yield_settle_if_needed<F, O>(
|
||||||
this_ref: &Rc<RefCell<Self>>,
|
this_ref: &Rc<RefCell<Self>>,
|
||||||
module_index: usize,
|
module_index: usize,
|
||||||
|
@ -7713,18 +7851,22 @@ impl<T: BundleType> fmt::Debug for Simulation<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_simulation_methods {
|
macro_rules! impl_simulation_methods {
|
||||||
(async_await = ($($async:tt, $await:tt)?)) => {
|
(
|
||||||
#[track_caller]
|
async_await = ($($async:tt, $await:tt)?),
|
||||||
pub $($async)? fn read_bool_or_int<I: BoolOrIntType>(&mut self, io: Expr<I>) -> I::Value {
|
track_caller = ($(#[$track_caller:tt])?),
|
||||||
let retval = self
|
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
|
.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.read_bool_or_int(io, WhichModule::Main);
|
.read_bool_or_int(io, $which_module);
|
||||||
self.settle_if_needed(retval)$(.$await)?
|
$self.settle_if_needed(retval)$(.$await)?
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn write_bool_or_int<I: BoolOrIntType>(
|
pub $($async)? fn write_bool_or_int<I: BoolOrIntType>(
|
||||||
&mut self,
|
&mut $self,
|
||||||
io: Expr<I>,
|
io: Expr<I>,
|
||||||
value: impl ToExpr<Type = I>,
|
value: impl ToExpr<Type = I>,
|
||||||
) {
|
) {
|
||||||
|
@ -7733,68 +7875,68 @@ macro_rules! impl_simulation_methods {
|
||||||
let value = value
|
let value = value
|
||||||
.to_literal_bits()
|
.to_literal_bits()
|
||||||
.expect("the value that is being written to an input must be a literal");
|
.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,
|
io,
|
||||||
I::bits_to_value(Cow::Borrowed(&value)),
|
I::bits_to_value(Cow::Borrowed(&value)),
|
||||||
WhichModule::Main,
|
$which_module,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn write_clock(&mut self, io: Expr<Clock>, value: bool) {
|
pub $($async)? fn write_clock(&mut $self, io: Expr<Clock>, value: bool) {
|
||||||
self.sim_impl
|
$self.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
.write_bit(Expr::canonical(io), value, $which_module);
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn read_clock(&mut self, io: Expr<Clock>) -> bool {
|
pub $($async)? fn read_clock(&mut $self, io: Expr<Clock>) -> bool {
|
||||||
let retval = self
|
let retval = $self
|
||||||
.sim_impl
|
.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
.read_bit(Expr::canonical(io), $which_module);
|
||||||
self.settle_if_needed(retval)$(.$await)?
|
$self.settle_if_needed(retval)$(.$await)?
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn write_bool(&mut self, io: Expr<Bool>, value: bool) {
|
pub $($async)? fn write_bool(&mut $self, io: Expr<Bool>, value: bool) {
|
||||||
self.sim_impl
|
$self.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
.write_bit(Expr::canonical(io), value, $which_module);
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn read_bool(&mut self, io: Expr<Bool>) -> bool {
|
pub $($async)? fn read_bool(&mut $self, io: Expr<Bool>) -> bool {
|
||||||
let retval = self
|
let retval = $self
|
||||||
.sim_impl
|
.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
.read_bit(Expr::canonical(io), $which_module);
|
||||||
self.settle_if_needed(retval)$(.$await)?
|
$self.settle_if_needed(retval)$(.$await)?
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn write_reset<R: ResetType>(&mut self, io: Expr<R>, value: bool) {
|
pub $($async)? fn write_reset<R: ResetType>(&mut $self, io: Expr<R>, value: bool) {
|
||||||
self.sim_impl
|
$self.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.write_bit(Expr::canonical(io), value, WhichModule::Main);
|
.write_bit(Expr::canonical(io), value, $which_module);
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn read_reset<R: ResetType>(&mut self, io: Expr<R>) -> bool {
|
pub $($async)? fn read_reset<R: ResetType>(&mut $self, io: Expr<R>) -> bool {
|
||||||
let retval = self
|
let retval = $self
|
||||||
.sim_impl
|
.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.read_bit(Expr::canonical(io), WhichModule::Main);
|
.read_bit(Expr::canonical(io), $which_module);
|
||||||
self.settle_if_needed(retval)$(.$await)?
|
$self.settle_if_needed(retval)$(.$await)?
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn read<IO: Type>(&mut self, io: Expr<IO>) -> SimValue<IO> {
|
pub $($async)? fn read<IO: Type>(&mut $self, io: Expr<IO>) -> SimValue<IO> {
|
||||||
let retval = self
|
let retval = $self
|
||||||
.sim_impl
|
.sim_impl
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.read(Expr::canonical(io), WhichModule::Main);
|
.read(Expr::canonical(io), $which_module);
|
||||||
SimValue::from_canonical(self.settle_if_needed(retval)$(.$await)?)
|
SimValue::from_canonical($self.settle_if_needed(retval)$(.$await)?)
|
||||||
}
|
}
|
||||||
#[track_caller]
|
$(#[$track_caller])?
|
||||||
pub $($async)? fn write<IO: Type, V: ToSimValue<IO>>(&mut self, io: Expr<IO>, value: V) {
|
pub $($async)? fn write<IO: Type, V: ToSimValue<IO>>(&mut $self, io: Expr<IO>, value: V) {
|
||||||
self.sim_impl.borrow_mut().write(
|
$self.sim_impl.borrow_mut().write(
|
||||||
Expr::canonical(io),
|
Expr::canonical(io),
|
||||||
value.into_sim_value(Expr::ty(io)).into_canonical(),
|
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)
|
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)]
|
#[doc(hidden)]
|
||||||
/// This is explicitly unstable and may be changed/removed at any time
|
/// This is explicitly unstable and may be changed/removed at any time
|
||||||
pub fn set_breakpoints_unstable(&mut self, pcs: HashSet<usize>, trace: bool) {
|
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()),
|
io_ty: T::from_canonical(io_ty.canonical()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[track_caller]
|
|
||||||
pub async fn settle(&mut self) {
|
pub async fn settle(&mut self) {
|
||||||
SimulationImpl::yield_advance_time_or_settle(self.sim_impl.clone(), self.module_index, None)
|
SimulationImpl::yield_advance_time_or_settle(self.sim_impl.clone(), self.module_index, None)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
#[track_caller]
|
|
||||||
pub async fn advance_time(&mut self, duration: SimDuration) {
|
pub async fn advance_time(&mut self, duration: SimDuration) {
|
||||||
SimulationImpl::yield_advance_time_or_settle(
|
SimulationImpl::yield_advance_time_or_settle(
|
||||||
self.sim_impl.clone(),
|
self.sim_impl.clone(),
|
||||||
|
@ -7927,14 +8071,17 @@ impl<T: BundleType> ExternModuleSimulationState<T> {
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
#[track_caller]
|
|
||||||
async fn settle_if_needed<F, O>(&mut self, v: MaybeNeedsSettle<F, O>) -> O
|
async fn settle_if_needed<F, O>(&mut self, v: MaybeNeedsSettle<F, O>) -> O
|
||||||
where
|
where
|
||||||
for<'a> F: MaybeNeedsSettleFn<&'a mut interpreter::State, Output = O>,
|
for<'a> F: MaybeNeedsSettleFn<&'a mut interpreter::State, Output = O>,
|
||||||
{
|
{
|
||||||
SimulationImpl::yield_settle_if_needed(&self.sim_impl, self.module_index, v).await
|
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:
|
pub trait ExternModuleSimGenerator:
|
||||||
|
|
|
@ -5,11 +5,14 @@ use fayalite::{
|
||||||
int::UIntValue,
|
int::UIntValue,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
reset::ResetType,
|
reset::ResetType,
|
||||||
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation, ToSimValue},
|
sim::{
|
||||||
|
time::SimDuration, vcd::VcdWriterDecls, ExternModuleSimGenerator,
|
||||||
|
ExternModuleSimulationState, Simulation, ToSimValue,
|
||||||
|
},
|
||||||
ty::StaticType,
|
ty::StaticType,
|
||||||
util::RcWriter,
|
util::RcWriter,
|
||||||
};
|
};
|
||||||
use std::num::NonZeroUsize;
|
use std::{future::IntoFuture, num::NonZeroUsize};
|
||||||
|
|
||||||
#[hdl_module(outline_generated)]
|
#[hdl_module(outline_generated)]
|
||||||
pub fn connect_const() {
|
pub fn connect_const() {
|
||||||
|
@ -1443,3 +1446,61 @@ fn test_conditional_assignment_last() {
|
||||||
panic!();
|
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,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "array_rw",
|
name: "array_rw",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -115,7 +115,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "conditional_assignment_last",
|
name: "conditional_assignment_last",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -91,7 +91,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "connect_const",
|
name: "connect_const",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -134,7 +134,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "connect_const_reset",
|
name: "connect_const_reset",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -254,7 +254,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "counter",
|
name: "counter",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -235,7 +235,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "counter",
|
name: "counter",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -95,7 +95,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "duplicate_names",
|
name: "duplicate_names",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1336,7 +1336,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "enums",
|
name: "enums",
|
||||||
children: [
|
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,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "memories",
|
name: "memories",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -670,7 +670,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "memories2",
|
name: "memories2",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -1754,7 +1754,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "memories3",
|
name: "memories3",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -267,7 +267,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "mod1",
|
name: "mod1",
|
||||||
children: [
|
children: [
|
||||||
|
|
|
@ -330,7 +330,7 @@ Simulation {
|
||||||
did_initial_settle: true,
|
did_initial_settle: true,
|
||||||
},
|
},
|
||||||
extern_modules: [],
|
extern_modules: [],
|
||||||
needs_settle: false,
|
state_ready_to_run: false,
|
||||||
trace_decls: TraceModule {
|
trace_decls: TraceModule {
|
||||||
name: "shift_register",
|
name: "shift_register",
|
||||||
children: [
|
children: [
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue