add ExternModuleSimulatorState::read_past() and more output when simulator trace is enabled
This commit is contained in:
parent
45fea70c18
commit
df020e9c9b
38 changed files with 12749 additions and 253 deletions
|
|
@ -2326,6 +2326,7 @@ impl<'a> Exporter<'a> {
|
|||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name,
|
||||
parameters,
|
||||
clocks_for_past: _,
|
||||
simulation: _,
|
||||
}) => {
|
||||
let verilog_name = Ident(verilog_name);
|
||||
|
|
|
|||
|
|
@ -41,7 +41,6 @@ use std::{
|
|||
marker::PhantomData,
|
||||
mem,
|
||||
num::NonZeroU64,
|
||||
ops::Deref,
|
||||
rc::Rc,
|
||||
sync::atomic::AtomicU64,
|
||||
};
|
||||
|
|
@ -67,6 +66,8 @@ pub trait ModuleBuildingStatus:
|
|||
type ModuleBody: fmt::Debug;
|
||||
type StmtAnnotations: 'static + Send + Sync + Copy + Eq + Hash + fmt::Debug;
|
||||
type ModuleIOAnnotations;
|
||||
type ExternModuleParameters: fmt::Debug;
|
||||
type ExternModuleClocksForPast: fmt::Debug;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
|
||||
|
|
@ -79,6 +80,8 @@ impl ModuleBuildingStatus for ModuleBuilt {
|
|||
type ModuleBody = Block;
|
||||
type StmtAnnotations = Interned<[TargetedAnnotation]>;
|
||||
type ModuleIOAnnotations = Interned<[TargetedAnnotation]>;
|
||||
type ExternModuleParameters = Interned<[ExternModuleParameter]>;
|
||||
type ExternModuleClocksForPast = Interned<[Target]>;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Default)]
|
||||
|
|
@ -91,6 +94,8 @@ impl ModuleBuildingStatus for ModuleBuilding {
|
|||
type ModuleBody = BuilderModuleBody;
|
||||
type StmtAnnotations = ();
|
||||
type ModuleIOAnnotations = Vec<TargetedAnnotation>;
|
||||
type ExternModuleParameters = Vec<ExternModuleParameter>;
|
||||
type ExternModuleClocksForPast = Vec<Target>;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -1080,26 +1085,65 @@ impl From<NormalModuleBody> for ModuleBody {
|
|||
}
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
fn validate_clock_for_past<S: ModuleBuildingStatus>(
|
||||
clock_for_past: Option<Target>,
|
||||
module_io: &[AnnotatedModuleIO<S>],
|
||||
) -> Target {
|
||||
if let Some(clock_for_past) = clock_for_past {
|
||||
assert_eq!(
|
||||
clock_for_past.canonical_ty(),
|
||||
Clock.canonical(),
|
||||
"clock_for_past: clock is not of type Clock",
|
||||
);
|
||||
if clock_for_past
|
||||
.base()
|
||||
.module_io()
|
||||
.is_some_and(|v| module_io.iter().any(|module_io| module_io.module_io == *v))
|
||||
{
|
||||
let mut target = clock_for_past;
|
||||
while let Target::Child(child) = target {
|
||||
match *child.path_element() {
|
||||
TargetPathElement::BundleField(_) | TargetPathElement::ArrayElement(_) => {}
|
||||
TargetPathElement::DynArrayElement(_) => {
|
||||
panic!(
|
||||
"clock_for_past: clock must be a static target (you can't use `Expr<UInt>` array indexes):\n{clock_for_past:?}"
|
||||
);
|
||||
}
|
||||
}
|
||||
target = *child.parent();
|
||||
}
|
||||
return clock_for_past;
|
||||
}
|
||||
}
|
||||
panic!("clock_for_past: clock must be some part of this module's I/O:\n{clock_for_past:?}");
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||
pub struct ExternModuleBody<
|
||||
P: Deref<Target = [ExternModuleParameter]> = Interned<[ExternModuleParameter]>,
|
||||
> {
|
||||
pub struct ExternModuleBody<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||
pub verilog_name: Interned<str>,
|
||||
pub parameters: P,
|
||||
pub parameters: S::ExternModuleParameters,
|
||||
/// [`Clock`]s that the [`Simulation`] will store the past values of all [`ModuleIO`] for.
|
||||
///
|
||||
/// [`Simulation`]: crate::sim::Simulation
|
||||
pub clocks_for_past: S::ExternModuleClocksForPast,
|
||||
pub simulation: Option<ExternModuleSimulation>,
|
||||
}
|
||||
|
||||
impl From<ExternModuleBody<Vec<ExternModuleParameter>>> for ExternModuleBody {
|
||||
fn from(value: ExternModuleBody<Vec<ExternModuleParameter>>) -> Self {
|
||||
impl From<ExternModuleBody<ModuleBuilding>> for ExternModuleBody {
|
||||
fn from(value: ExternModuleBody<ModuleBuilding>) -> Self {
|
||||
let ExternModuleBody {
|
||||
verilog_name,
|
||||
parameters,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
} = value;
|
||||
let parameters = Intern::intern_owned(parameters);
|
||||
let clocks_for_past = Intern::intern_owned(clocks_for_past);
|
||||
Self {
|
||||
verilog_name,
|
||||
parameters,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
}
|
||||
}
|
||||
|
|
@ -1112,15 +1156,12 @@ impl From<ExternModuleBody> for ModuleBody {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum ModuleBody<
|
||||
S: ModuleBuildingStatus = ModuleBuilt,
|
||||
P: Deref<Target = [ExternModuleParameter]> = Interned<[ExternModuleParameter]>,
|
||||
> {
|
||||
pub enum ModuleBody<S: ModuleBuildingStatus = ModuleBuilt> {
|
||||
Normal(NormalModuleBody<S>),
|
||||
Extern(ExternModuleBody<P>),
|
||||
Extern(ExternModuleBody<S>),
|
||||
}
|
||||
|
||||
pub(crate) type ModuleBodyBuilding = ModuleBody<ModuleBuilding, Vec<ExternModuleParameter>>;
|
||||
pub(crate) type ModuleBodyBuilding = ModuleBody<ModuleBuilding>;
|
||||
|
||||
impl ModuleBodyBuilding {
|
||||
pub(crate) fn builder_normal_body_opt(
|
||||
|
|
@ -1141,9 +1182,7 @@ impl ModuleBodyBuilding {
|
|||
}
|
||||
}
|
||||
#[track_caller]
|
||||
pub(crate) fn builder_extern_body(
|
||||
&mut self,
|
||||
) -> &mut ExternModuleBody<Vec<ExternModuleParameter>> {
|
||||
pub(crate) fn builder_extern_body(&mut self) -> &mut ExternModuleBody<ModuleBuilding> {
|
||||
if let Self::Extern(v) = self {
|
||||
v
|
||||
} else {
|
||||
|
|
@ -1297,11 +1336,13 @@ impl<T: BundleType> fmt::Debug for DebugModuleBody<T> {
|
|||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name,
|
||||
parameters,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
}) => {
|
||||
debug_struct
|
||||
.field("verilog_name", verilog_name)
|
||||
.field("parameters", parameters)
|
||||
.field("clocks_for_past", clocks_for_past)
|
||||
.field("simulation", simulation);
|
||||
}
|
||||
}
|
||||
|
|
@ -1780,8 +1821,13 @@ impl AssertValidityState {
|
|||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
clocks_for_past,
|
||||
simulation: _,
|
||||
}) => {}
|
||||
}) => {
|
||||
for clock_for_past in clocks_for_past {
|
||||
validate_clock_for_past(Some(clock_for_past), &self.module.module_io);
|
||||
}
|
||||
}
|
||||
ModuleBody::Normal(NormalModuleBody { body }) => {
|
||||
let body = self.make_block_index(body);
|
||||
assert_eq!(body, 0);
|
||||
|
|
@ -1811,9 +1857,17 @@ impl<T: BundleType> Module<T> {
|
|||
match &mut body {
|
||||
ModuleBody::Normal(_) => {}
|
||||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
clocks_for_past,
|
||||
simulation: Some(simulation),
|
||||
..
|
||||
}) => {
|
||||
let mut clocks_for_past_set = HashSet::default();
|
||||
*clocks_for_past = clocks_for_past
|
||||
.iter()
|
||||
.copied()
|
||||
.filter(|clock_for_past| clocks_for_past_set.insert(*clock_for_past))
|
||||
.collect();
|
||||
if module_io.iter().any(|io| {
|
||||
!simulation
|
||||
.sim_io_to_generator_map
|
||||
|
|
@ -2186,6 +2240,7 @@ impl ModuleBuilder {
|
|||
ModuleKind::Extern => ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: name.0,
|
||||
parameters: vec![],
|
||||
clocks_for_past: vec![],
|
||||
simulation: None,
|
||||
}),
|
||||
ModuleKind::Normal => ModuleBody::Normal(NormalModuleBody {
|
||||
|
|
@ -2308,6 +2363,20 @@ impl ModuleBuilder {
|
|||
value: ExternModuleParameterValue::RawVerilog(raw_verilog.intern()),
|
||||
});
|
||||
}
|
||||
/// registers a [`Clock`] so you can use it with the [`ExternModuleSimulationState::read_past()`] family of functions.
|
||||
///
|
||||
/// [`ExternModuleSimulationState::read_past()`]: crate::sim::ExternModuleSimulationState::read_past()
|
||||
#[track_caller]
|
||||
pub fn register_clock_for_past(&self, clock_for_past: impl ToExpr<Type = Clock>) {
|
||||
let clock_for_past = clock_for_past.to_expr().target().as_deref().copied();
|
||||
let mut impl_ = self.impl_.borrow_mut();
|
||||
let clock_for_past = validate_clock_for_past(clock_for_past, &impl_.io);
|
||||
impl_
|
||||
.body
|
||||
.builder_extern_body()
|
||||
.clocks_for_past
|
||||
.push(clock_for_past);
|
||||
}
|
||||
#[track_caller]
|
||||
pub fn extern_module_simulation<G: ExternModuleSimGenerator>(&self, generator: G) {
|
||||
let mut impl_ = self.impl_.borrow_mut();
|
||||
|
|
|
|||
|
|
@ -2073,6 +2073,7 @@ impl_run_pass_for_struct! {
|
|||
impl[] RunPass for ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
clocks_for_past: _,
|
||||
simulation: _,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@ use crate::{
|
|||
sim::{
|
||||
compiler::{
|
||||
Compiled, CompiledBundleField, CompiledExternModule, CompiledTypeLayoutBody,
|
||||
CompiledValue,
|
||||
CompiledValue, ExternModuleClockForPast,
|
||||
},
|
||||
interpreter::{
|
||||
BreakAction, BreakpointsSet, RunResult, SmallUInt, State,
|
||||
|
|
@ -57,7 +57,7 @@ use std::{
|
|||
pin::{Pin, pin},
|
||||
ptr,
|
||||
rc::Rc,
|
||||
sync::{Arc, Mutex},
|
||||
sync::{Arc, Mutex, MutexGuard},
|
||||
task::Poll,
|
||||
usize,
|
||||
};
|
||||
|
|
@ -1040,6 +1040,12 @@ impl<T> MaybeNeedsSettle<T> {
|
|||
MaybeNeedsSettle::NoSettleNeeded(v) => MaybeNeedsSettle::NoSettleNeeded(f(v)),
|
||||
}
|
||||
}
|
||||
fn into_inner(self) -> T {
|
||||
match self {
|
||||
MaybeNeedsSettle::NeedsSettle(v) => v,
|
||||
MaybeNeedsSettle::NoSettleNeeded(v) => v,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// workaround implementing FnOnce not being stable
|
||||
|
|
@ -1074,6 +1080,7 @@ struct SimulationModuleState {
|
|||
uninitialized_ios: HashMap<Target, Vec<Target>>,
|
||||
io_targets: HashMap<Target, CompiledValue<CanonicalType>>,
|
||||
did_initial_settle: bool,
|
||||
clocks_for_past: HashMap<CompiledValue<Clock>, SimulationExternModuleClockForPast>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for SimulationModuleState {
|
||||
|
|
@ -1083,23 +1090,37 @@ impl fmt::Debug for SimulationModuleState {
|
|||
uninitialized_ios,
|
||||
io_targets,
|
||||
did_initial_settle,
|
||||
clocks_for_past,
|
||||
} = self;
|
||||
f.debug_struct("SimulationModuleState")
|
||||
.field("base_targets", base_targets)
|
||||
.field("uninitialized_ios", &SortedSetDebug(uninitialized_ios))
|
||||
.field("io_targets", &SortedSetDebug(io_targets))
|
||||
.field("did_initial_settle", did_initial_settle)
|
||||
.field("clocks_for_past", &SortedMapDebug(clocks_for_past))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl SimulationModuleState {
|
||||
fn new(base_targets: impl IntoIterator<Item = (Target, CompiledValue<CanonicalType>)>) -> Self {
|
||||
fn new(
|
||||
base_targets: impl IntoIterator<Item = (Target, CompiledValue<CanonicalType>)>,
|
||||
clocks_for_past: &[ExternModuleClockForPast],
|
||||
) -> Self {
|
||||
let mut retval = Self {
|
||||
base_targets: Vec::new(),
|
||||
uninitialized_ios: HashMap::default(),
|
||||
io_targets: HashMap::default(),
|
||||
did_initial_settle: false,
|
||||
clocks_for_past: clocks_for_past
|
||||
.iter()
|
||||
.map(|clock_for_past| {
|
||||
(
|
||||
clock_for_past.clock_for_past,
|
||||
SimulationExternModuleClockForPast::new(clock_for_past),
|
||||
)
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
for (base_target, value) in base_targets {
|
||||
retval.base_targets.push(base_target);
|
||||
|
|
@ -1255,7 +1276,7 @@ impl SimulationModuleState {
|
|||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn read_helper(
|
||||
fn read_helper_current(
|
||||
&self,
|
||||
io: Expr<CanonicalType>,
|
||||
which_module: WhichModule,
|
||||
|
|
@ -1300,6 +1321,33 @@ impl SimulationModuleState {
|
|||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn read_helper(
|
||||
&self,
|
||||
io: Expr<CanonicalType>,
|
||||
read_time: ReadTime,
|
||||
which_module: WhichModule,
|
||||
) -> MaybeNeedsSettle<CompiledValue<CanonicalType>> {
|
||||
match read_time {
|
||||
ReadTime::Current => self.read_helper_current(io, which_module),
|
||||
ReadTime::Past { clock_for_past } => {
|
||||
let current = self.read_helper_current(io, which_module);
|
||||
let clock_for_past_value = self
|
||||
.read_helper_current(Expr::canonical(clock_for_past), which_module)
|
||||
.into_inner()
|
||||
.map_ty(Clock::from_canonical);
|
||||
let Some(clock_for_past) = self.clocks_for_past.get(&clock_for_past_value) else {
|
||||
panic!(
|
||||
"In order to use the `read_past()` family of functions,\n\
|
||||
you must call `m.register_clock_for_past(my_io.clk)`\n\
|
||||
in the module's body for every clock you use as the\n\
|
||||
second argument of the `read_past()` family."
|
||||
);
|
||||
};
|
||||
current.map(|current| clock_for_past.current_to_past_map[¤t])
|
||||
}
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn write_helper(
|
||||
&mut self,
|
||||
io: Expr<CanonicalType>,
|
||||
|
|
@ -1331,11 +1379,71 @@ impl SimulationModuleState {
|
|||
}
|
||||
}
|
||||
|
||||
struct SimulationExternModuleClockForPast {
|
||||
current_to_past_map: HashMap<CompiledValue<CanonicalType>, CompiledValue<CanonicalType>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for SimulationExternModuleClockForPast {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self {
|
||||
current_to_past_map,
|
||||
} = self;
|
||||
f.debug_struct("SimulationExternModuleClockForPast")
|
||||
.field("current_to_past_map", &SortedMapDebug(current_to_past_map))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl SimulationExternModuleClockForPast {
|
||||
fn new(clock_for_past: &ExternModuleClockForPast) -> Self {
|
||||
let mut retval = Self {
|
||||
current_to_past_map: HashMap::default(),
|
||||
};
|
||||
for (current, past) in clock_for_past.current_to_past_map {
|
||||
retval.add_current_to_past_mapping(current, past);
|
||||
}
|
||||
retval
|
||||
}
|
||||
fn add_current_to_past_mapping(
|
||||
&mut self,
|
||||
current: CompiledValue<CanonicalType>,
|
||||
past: CompiledValue<CanonicalType>,
|
||||
) {
|
||||
self.current_to_past_map.insert(current, past);
|
||||
match current.layout.body {
|
||||
CompiledTypeLayoutBody::Scalar | CompiledTypeLayoutBody::PhantomConst => {}
|
||||
CompiledTypeLayoutBody::Array { .. } => {
|
||||
let current = current.map_ty(Array::from_canonical);
|
||||
let past = past.map_ty(Array::from_canonical);
|
||||
for index in 0..current.layout.ty.len() {
|
||||
self.add_current_to_past_mapping(current.element(index), past.element(index));
|
||||
}
|
||||
}
|
||||
CompiledTypeLayoutBody::Bundle { .. } => {
|
||||
let current = current.map_ty(Bundle::from_canonical);
|
||||
let past = past.map_ty(Bundle::from_canonical);
|
||||
for BundleField { name, .. } in current.layout.ty.fields() {
|
||||
self.add_current_to_past_mapping(
|
||||
current.field_by_name(name),
|
||||
past.field_by_name(name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum ReadTime {
|
||||
Current,
|
||||
Past { clock_for_past: Expr<Clock> },
|
||||
}
|
||||
|
||||
struct SimulationExternModuleState {
|
||||
module_state: SimulationModuleState,
|
||||
sim: ExternModuleSimulation,
|
||||
running_generator: Option<Pin<Box<dyn Future<Output = ()> + 'static>>>,
|
||||
waker: Arc<ExternModuleGeneratorWaker>,
|
||||
debug_name: Interned<str>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for SimulationExternModuleState {
|
||||
|
|
@ -1345,6 +1453,7 @@ impl fmt::Debug for SimulationExternModuleState {
|
|||
sim,
|
||||
running_generator,
|
||||
waker: _,
|
||||
debug_name: _,
|
||||
} = self;
|
||||
f.debug_struct("SimulationExternModuleState")
|
||||
.field("module_state", module_state)
|
||||
|
|
@ -1489,75 +1598,170 @@ impl Hash for HashableWaker {
|
|||
}
|
||||
}
|
||||
|
||||
enum EventWakers {
|
||||
Wakers(HashSet<HashableWaker>),
|
||||
CurrentlyWaking,
|
||||
}
|
||||
|
||||
impl EventWakers {
|
||||
fn start_waking(&mut self) -> HashSet<HashableWaker> {
|
||||
match std::mem::replace(self, Self::CurrentlyWaking) {
|
||||
Self::Wakers(retval) => retval,
|
||||
Self::CurrentlyWaking => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for EventWakers {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self {
|
||||
Self::Wakers(wakers) => f.debug_tuple("Wakers").field(&wakers.len()).finish(),
|
||||
Self::CurrentlyWaking => write!(f, "CurrentlyWaking"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EventQueueData {
|
||||
instant: SimInstant,
|
||||
events: BTreeMap<Event, HashSet<HashableWaker>>,
|
||||
events: BTreeMap<Event, EventWakers>,
|
||||
trace: bool,
|
||||
}
|
||||
|
||||
impl fmt::Debug for EventQueueData {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
struct EventsDebug<'a>(&'a BTreeMap<Event, HashSet<HashableWaker>>);
|
||||
impl fmt::Debug for EventsDebug<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut debug_map = f.debug_map();
|
||||
for (k, v) in self.0 {
|
||||
debug_map.entry(&format_args!("{k:?}"), &v.len());
|
||||
}
|
||||
debug_map.finish()
|
||||
}
|
||||
}
|
||||
let Self { instant, events } = self;
|
||||
let Self {
|
||||
instant,
|
||||
events,
|
||||
trace: _,
|
||||
} = self;
|
||||
f.debug_struct("EventQueueData")
|
||||
.field("instant", instant)
|
||||
.field("events", &EventsDebug(events))
|
||||
.field("events", events)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
struct EventQueueFirstEntry<'a>(
|
||||
std::collections::btree_map::OccupiedEntry<'a, Event, HashSet<HashableWaker>>,
|
||||
);
|
||||
struct EventQueueFirstEvent<'a> {
|
||||
event_queue: Arc<EventQueue>,
|
||||
event_queue_lock: MutexGuard<'a, EventQueueData>,
|
||||
}
|
||||
|
||||
impl<'a> EventQueueFirstEntry<'a> {
|
||||
fn key(&self) -> &Event {
|
||||
self.0.key()
|
||||
impl<'a> EventQueueFirstEvent<'a> {
|
||||
fn event(&self) -> &Event {
|
||||
self.event_queue_lock
|
||||
.events
|
||||
.first_key_value()
|
||||
.expect("known to be non-empty")
|
||||
.0
|
||||
}
|
||||
fn remove(self) -> HashSet<HashableWaker> {
|
||||
self.0.remove()
|
||||
fn remove_and_wake_all_wakers(self) {
|
||||
let Self {
|
||||
event_queue,
|
||||
mut event_queue_lock,
|
||||
} = self;
|
||||
let trace = event_queue_lock.trace;
|
||||
let mut entry = event_queue_lock
|
||||
.events
|
||||
.first_entry()
|
||||
.expect("known to be non-empty");
|
||||
let wakers = entry.get_mut().start_waking();
|
||||
let event = *entry.key();
|
||||
if wakers.is_empty() {
|
||||
entry.remove();
|
||||
if trace {
|
||||
println!(
|
||||
"EventQueue first_event remove_and_wake_all_wakers(): event={event:?} no wakers",
|
||||
);
|
||||
}
|
||||
drop(event_queue_lock);
|
||||
return;
|
||||
}
|
||||
drop(event_queue_lock);
|
||||
if trace {
|
||||
println!(
|
||||
"EventQueue first_event remove_and_wake_all_wakers(): event={event:?} wakers_len={}",
|
||||
wakers.len()
|
||||
);
|
||||
}
|
||||
for waker in wakers {
|
||||
waker.0.wake();
|
||||
}
|
||||
event_queue.lock().events.remove(&event);
|
||||
if trace {
|
||||
println!(
|
||||
"EventQueue first_event remove_and_wake_all_wakers(): event={event:?} finished waking",
|
||||
);
|
||||
}
|
||||
}
|
||||
fn into_event_queue_lock(self) -> MutexGuard<'a, EventQueueData> {
|
||||
self.event_queue_lock
|
||||
}
|
||||
}
|
||||
|
||||
impl EventQueueData {
|
||||
fn new(instant: SimInstant) -> Self {
|
||||
fn new(instant: SimInstant, trace: bool) -> Self {
|
||||
Self {
|
||||
instant,
|
||||
events: BTreeMap::new(),
|
||||
trace,
|
||||
}
|
||||
}
|
||||
fn instant(&self) -> SimInstant {
|
||||
self.instant
|
||||
}
|
||||
fn set_instant(&mut self, instant: SimInstant) {
|
||||
if self.trace {
|
||||
println!("EventQueue set_instant({instant:?})");
|
||||
}
|
||||
self.instant = instant;
|
||||
}
|
||||
fn add_event(&mut self, mut event: Event, waker: Option<std::task::Waker>) {
|
||||
fn add_event(
|
||||
&mut self,
|
||||
mut event: Event,
|
||||
waker: Option<std::task::Waker>,
|
||||
) -> Result<(), std::task::Waker> {
|
||||
event.instant = event.instant.max(self.instant);
|
||||
self.events
|
||||
let wakers = self
|
||||
.events
|
||||
.entry(event)
|
||||
.or_default()
|
||||
.extend(waker.map(HashableWaker));
|
||||
.or_insert_with(|| EventWakers::Wakers(HashSet::default()));
|
||||
let EventWakers::Wakers(wakers) = wakers else {
|
||||
return match waker {
|
||||
Some(waker) => Err(waker),
|
||||
None => Ok(()),
|
||||
};
|
||||
};
|
||||
if self.trace {
|
||||
println!(
|
||||
"EventQueue add_event({event:?}, {:?})",
|
||||
waker.is_some().then_some(format_args!("<waker>"))
|
||||
);
|
||||
}
|
||||
wakers.extend(waker.map(HashableWaker));
|
||||
Ok(())
|
||||
}
|
||||
fn add_event_for_now(&mut self, kind: EventKind, waker: Option<std::task::Waker>) {
|
||||
fn add_event_for_now(&mut self, kind: EventKind) {
|
||||
self.add_event(
|
||||
Event {
|
||||
instant: self.instant,
|
||||
kind,
|
||||
},
|
||||
waker,
|
||||
);
|
||||
None,
|
||||
)
|
||||
.expect("no waker passed in")
|
||||
}
|
||||
fn first_entry(&mut self) -> Option<EventQueueFirstEntry<'_>> {
|
||||
self.events.first_entry().map(EventQueueFirstEntry)
|
||||
fn first_event<'a>(
|
||||
this: MutexGuard<'a, EventQueueData>,
|
||||
event_queue: Arc<EventQueue>,
|
||||
) -> Result<EventQueueFirstEvent<'a>, MutexGuard<'a, EventQueueData>> {
|
||||
if this.events.is_empty() {
|
||||
Err(this)
|
||||
} else {
|
||||
Ok(EventQueueFirstEvent {
|
||||
event_queue,
|
||||
event_queue_lock: this,
|
||||
})
|
||||
}
|
||||
}
|
||||
fn peek_first_event(&self) -> Option<Event> {
|
||||
Some(*self.events.first_key_value()?.0)
|
||||
|
|
@ -1586,11 +1790,11 @@ impl EventQueue {
|
|||
fn new(data: EventQueueData) -> Self {
|
||||
Self(Mutex::new(data))
|
||||
}
|
||||
fn lock(&self) -> std::sync::MutexGuard<'_, EventQueueData> {
|
||||
fn lock(&self) -> MutexGuard<'_, EventQueueData> {
|
||||
self.0.lock().expect("not poisoned")
|
||||
}
|
||||
fn add_event_for_now(&self, kind: EventKind, waker: Option<std::task::Waker>) {
|
||||
self.lock().add_event_for_now(kind, waker);
|
||||
fn add_event_for_now(&self, kind: EventKind) {
|
||||
self.lock().add_event_for_now(kind);
|
||||
}
|
||||
fn peek_first_event_for_now(&self) -> Option<Event> {
|
||||
self.lock().peek_first_event_for_now()
|
||||
|
|
@ -1608,7 +1812,7 @@ impl std::task::Wake for ExternModuleGeneratorWaker {
|
|||
}
|
||||
fn wake_by_ref(self: &Arc<Self>) {
|
||||
if let Some(event_queue) = self.event_queue.upgrade() {
|
||||
event_queue.add_event_for_now(EventKind::ExternModule(self.module_index), None);
|
||||
event_queue.add_event_for_now(EventKind::ExternModule(self.module_index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1808,10 +2012,10 @@ impl SimulationImpl {
|
|||
}
|
||||
fn new(compiled: Compiled<Bundle>) -> Self {
|
||||
let io_target = Target::from(compiled.io);
|
||||
let mut event_queue = EventQueueData::new(SimInstant::START);
|
||||
event_queue.add_event_for_now(EventKind::State, None);
|
||||
let mut event_queue = EventQueueData::new(SimInstant::START, false);
|
||||
event_queue.add_event_for_now(EventKind::State);
|
||||
for module_index in 0..compiled.extern_modules.len() {
|
||||
event_queue.add_event_for_now(EventKind::ExternModule(module_index), None);
|
||||
event_queue.add_event_for_now(EventKind::ExternModule(module_index));
|
||||
}
|
||||
let event_queue = Arc::new(EventQueue::new(event_queue));
|
||||
let extern_modules = Box::from_iter(compiled.extern_modules.iter().enumerate().map(
|
||||
|
|
@ -1820,7 +2024,9 @@ impl SimulationImpl {
|
|||
&CompiledExternModule {
|
||||
module_io_targets,
|
||||
module_io,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
debug_name,
|
||||
},
|
||||
)| {
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -1829,6 +2035,7 @@ impl SimulationImpl {
|
|||
.iter()
|
||||
.copied()
|
||||
.zip(module_io.iter().copied()),
|
||||
&clocks_for_past,
|
||||
),
|
||||
sim: simulation,
|
||||
running_generator: None,
|
||||
|
|
@ -1836,6 +2043,7 @@ impl SimulationImpl {
|
|||
event_queue: Arc::downgrade(&event_queue),
|
||||
module_index,
|
||||
}),
|
||||
debug_name,
|
||||
}
|
||||
},
|
||||
));
|
||||
|
|
@ -1858,6 +2066,7 @@ impl SimulationImpl {
|
|||
value,
|
||||
)
|
||||
}),
|
||||
&[],
|
||||
),
|
||||
extern_modules,
|
||||
trace_decls: compiled.base_module.trace_decls,
|
||||
|
|
@ -2048,6 +2257,9 @@ impl SimulationImpl {
|
|||
// already added
|
||||
return;
|
||||
};
|
||||
if self.breakpoints.as_ref().is_some_and(|v| v.trace) {
|
||||
println!("SimulationImpl::wake_after_change:\n{sensitivity_set:#?}");
|
||||
}
|
||||
let SensitivitySet {
|
||||
debug_id: _,
|
||||
compiled_values: _,
|
||||
|
|
@ -2070,6 +2282,9 @@ impl SimulationImpl {
|
|||
else {
|
||||
return;
|
||||
};
|
||||
if self.breakpoints.as_ref().is_some_and(|v| v.trace) {
|
||||
println!("SimulationImpl::cancel_wake_after_change:\n{sensitivity_set:#?}");
|
||||
}
|
||||
let SensitivitySet {
|
||||
debug_id: _,
|
||||
compiled_values: _,
|
||||
|
|
@ -2099,13 +2314,19 @@ impl SimulationImpl {
|
|||
let Some(instant) = instant(event_queue.instant()) else {
|
||||
return Err(waker);
|
||||
};
|
||||
event_queue.add_event(
|
||||
match event_queue.add_event(
|
||||
Event {
|
||||
instant,
|
||||
kind: EventKind::ExternModule(module_index),
|
||||
},
|
||||
Some(waker),
|
||||
);
|
||||
) {
|
||||
Ok(()) => {}
|
||||
Err(waker) => {
|
||||
drop(event_queue);
|
||||
waker.wake();
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
async fn yield_advance_time_or_settle(
|
||||
|
|
@ -2248,17 +2469,25 @@ impl SimulationImpl {
|
|||
.iter()
|
||||
.any(|i| self.state.small_slots[*i] != 0)
|
||||
{
|
||||
self.event_queue.add_event_for_now(EventKind::State, None);
|
||||
if self.breakpoints.as_ref().is_some_and(|v| v.trace) {
|
||||
println!("SimulationImpl clocks triggered");
|
||||
}
|
||||
self.event_queue.add_event_for_now(EventKind::State);
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn run_extern_module(this_ref: &Rc<RefCell<Self>>, module_index: usize) {
|
||||
let mut this = this_ref.borrow_mut();
|
||||
let trace = this.breakpoints.as_ref().is_some_and(|v| v.trace);
|
||||
let extern_module = &mut this.extern_modules[module_index];
|
||||
let debug_name = extern_module.debug_name;
|
||||
let waker = std::task::Waker::from(extern_module.waker.clone());
|
||||
let mut generator = if !extern_module.module_state.did_initial_settle {
|
||||
let sim = extern_module.sim;
|
||||
drop(this);
|
||||
if trace {
|
||||
println!("{debug_name}: start");
|
||||
}
|
||||
Box::into_pin(sim.run(ExternModuleSimulationState {
|
||||
sim_impl: this_ref.clone(),
|
||||
module_index,
|
||||
|
|
@ -2269,13 +2498,19 @@ impl SimulationImpl {
|
|||
} else {
|
||||
return;
|
||||
};
|
||||
let generator = match generator
|
||||
if trace {
|
||||
println!("{debug_name}: poll");
|
||||
}
|
||||
let poll_result = generator
|
||||
.as_mut()
|
||||
.poll(&mut std::task::Context::from_waker(&waker))
|
||||
{
|
||||
.poll(&mut std::task::Context::from_waker(&waker));
|
||||
let generator = match poll_result {
|
||||
Poll::Ready(()) => None,
|
||||
Poll::Pending => Some(generator),
|
||||
};
|
||||
if trace {
|
||||
println!("{debug_name}: poll returned {poll_result:?}");
|
||||
}
|
||||
this = this_ref.borrow_mut();
|
||||
this.extern_modules[module_index]
|
||||
.module_state
|
||||
|
|
@ -2378,7 +2613,8 @@ impl SimulationImpl {
|
|||
"didn't initialize all inputs",
|
||||
);
|
||||
this.check_waiting_sensitivity_sets();
|
||||
let mut event_queue = this.event_queue.lock();
|
||||
let arc_event_queue = this.event_queue.clone(); // avoid borrow errors
|
||||
let mut event_queue = arc_event_queue.lock();
|
||||
let Some(run_target) = run_target(event_queue.instant()) else {
|
||||
drop(event_queue);
|
||||
panic!("SimInstant overflowed");
|
||||
|
|
@ -2392,10 +2628,14 @@ impl SimulationImpl {
|
|||
}
|
||||
settle_cycle += 1;
|
||||
let event_queue_instant = event_queue.instant();
|
||||
let Some(first_entry) = event_queue.first_entry() else {
|
||||
let changed_time = event_queue_instant != run_target;
|
||||
event_queue.set_instant(run_target);
|
||||
drop(event_queue);
|
||||
let mut changed_time = false;
|
||||
let first_entry = EventQueueData::first_event(event_queue, arc_event_queue.clone())
|
||||
.map_err(|mut event_queue| {
|
||||
changed_time = event_queue_instant != run_target;
|
||||
event_queue.set_instant(run_target);
|
||||
drop(event_queue);
|
||||
});
|
||||
let Ok(first_entry) = first_entry else {
|
||||
if changed_time {
|
||||
this.write_traces_change_time_to(run_target);
|
||||
}
|
||||
|
|
@ -2404,13 +2644,9 @@ impl SimulationImpl {
|
|||
let Event {
|
||||
instant: event_instant,
|
||||
kind: event_kind,
|
||||
} = *first_entry.key();
|
||||
} = *first_entry.event();
|
||||
if event_instant <= event_queue_instant {
|
||||
let wakers = first_entry.remove();
|
||||
drop(event_queue);
|
||||
for HashableWaker(waker) in wakers {
|
||||
waker.wake();
|
||||
}
|
||||
first_entry.remove_and_wake_all_wakers();
|
||||
match event_kind {
|
||||
EventKind::State => this.run_state_settle_cycle(),
|
||||
EventKind::ExternModule(module_index) => {
|
||||
|
|
@ -2422,6 +2658,7 @@ impl SimulationImpl {
|
|||
this.write_traces_after_event();
|
||||
this.check_waiting_sensitivity_sets();
|
||||
} else {
|
||||
event_queue = first_entry.into_event_queue_lock();
|
||||
let new_instant = event_instant.min(run_target);
|
||||
let changed_time = event_queue_instant != new_instant;
|
||||
event_queue.set_instant(new_instant);
|
||||
|
|
@ -2433,7 +2670,7 @@ impl SimulationImpl {
|
|||
return;
|
||||
}
|
||||
}
|
||||
event_queue = this.event_queue.lock();
|
||||
event_queue = arc_event_queue.lock();
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
|
|
@ -2458,10 +2695,11 @@ impl SimulationImpl {
|
|||
fn read_bit(
|
||||
&mut self,
|
||||
io: Expr<CanonicalType>,
|
||||
read_time: ReadTime,
|
||||
which_module: WhichModule,
|
||||
) -> MaybeNeedsSettle<ReadBitFn, bool> {
|
||||
self.get_module(which_module)
|
||||
.read_helper(Expr::canonical(io), which_module)
|
||||
.read_helper(Expr::canonical(io), read_time, which_module)
|
||||
.map(|compiled_value| ReadBitFn { compiled_value })
|
||||
.apply_no_settle(&mut self.state)
|
||||
}
|
||||
|
|
@ -2470,7 +2708,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(io, which_module);
|
||||
self.event_queue.add_event_for_now(EventKind::State, None);
|
||||
self.event_queue.add_event_for_now(EventKind::State);
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => {
|
||||
self.state.small_slots[compiled_value.range.small_slots.start] = value as _;
|
||||
|
|
@ -2480,15 +2718,17 @@ impl SimulationImpl {
|
|||
}
|
||||
Some(TypeLenSingle::SimOnlySlot) | None => unreachable!(),
|
||||
}
|
||||
self.debug_write(compiled_value);
|
||||
}
|
||||
#[track_caller]
|
||||
fn read_bool_or_int<I: BoolOrIntType>(
|
||||
&mut self,
|
||||
io: Expr<I>,
|
||||
read_time: ReadTime,
|
||||
which_module: WhichModule,
|
||||
) -> MaybeNeedsSettle<ReadBoolOrIntFn<I>, I::Value> {
|
||||
self.get_module(which_module)
|
||||
.read_helper(Expr::canonical(io), which_module)
|
||||
.read_helper(Expr::canonical(io), read_time, which_module)
|
||||
.map(|compiled_value| ReadBoolOrIntFn { compiled_value, io })
|
||||
.apply_no_settle(&mut self.state)
|
||||
}
|
||||
|
|
@ -2502,7 +2742,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(Expr::canonical(io), which_module);
|
||||
self.event_queue.add_event_for_now(EventKind::State, None);
|
||||
self.event_queue.add_event_for_now(EventKind::State);
|
||||
let value: BigInt = value.into();
|
||||
match compiled_value.range.len().as_single() {
|
||||
Some(TypeLenSingle::SmallSlot) => {
|
||||
|
|
@ -2517,6 +2757,7 @@ impl SimulationImpl {
|
|||
}
|
||||
Some(TypeLenSingle::SimOnlySlot) | None => unreachable!(),
|
||||
}
|
||||
self.debug_write(compiled_value);
|
||||
}
|
||||
#[track_caller]
|
||||
fn read_write_sim_value_helper<Opaque: ?Sized>(
|
||||
|
|
@ -2569,17 +2810,18 @@ impl SimulationImpl {
|
|||
None => unreachable!(),
|
||||
}
|
||||
}
|
||||
CompiledTypeLayoutBody::Array { element } => {
|
||||
CompiledTypeLayoutBody::Array { elements_non_empty } => {
|
||||
let ty = <Array>::from_canonical(compiled_value.layout.ty);
|
||||
let element_size = ty.element().size();
|
||||
for element_index in 0..ty.len() {
|
||||
Self::read_write_sim_value_helper(
|
||||
state,
|
||||
CompiledValue {
|
||||
layout: *element,
|
||||
range: compiled_value
|
||||
.range
|
||||
.index_array(element.layout.len(), element_index),
|
||||
layout: elements_non_empty[element_index],
|
||||
range: compiled_value.range.index_array(
|
||||
elements_non_empty[element_index].layout.len(),
|
||||
element_index,
|
||||
),
|
||||
write: None,
|
||||
},
|
||||
start_index + element_index * element_size,
|
||||
|
|
@ -2725,12 +2967,15 @@ impl SimulationImpl {
|
|||
fn read(
|
||||
&mut self,
|
||||
io: Expr<CanonicalType>,
|
||||
read_time: ReadTime,
|
||||
which_module: WhichModule,
|
||||
) -> (
|
||||
CompiledValue<CanonicalType>,
|
||||
MaybeNeedsSettle<ReadFn, SimValue<CanonicalType>>,
|
||||
) {
|
||||
let compiled_value = self.get_module(which_module).read_helper(io, which_module);
|
||||
let compiled_value = self
|
||||
.get_module(which_module)
|
||||
.read_helper(io, read_time, which_module);
|
||||
let value = compiled_value
|
||||
.map(|compiled_value| ReadFn { compiled_value, io })
|
||||
.apply_no_settle(&mut self.state);
|
||||
|
|
@ -2738,6 +2983,18 @@ impl SimulationImpl {
|
|||
| MaybeNeedsSettle::NoSettleNeeded(compiled_value)) = compiled_value;
|
||||
(compiled_value, value)
|
||||
}
|
||||
fn debug_write(&self, compiled_value: CompiledValue<CanonicalType>) {
|
||||
if self.breakpoints.as_ref().is_some_and(|v| v.trace) {
|
||||
println!(
|
||||
"wrote: {:#?}",
|
||||
compiler::DebugCompiledValueStateAsMap {
|
||||
compiled_value,
|
||||
state_layout: self.state.insns.state_layout(),
|
||||
state: &self.state,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
#[track_caller]
|
||||
fn write(
|
||||
&mut self,
|
||||
|
|
@ -2748,7 +3005,7 @@ impl SimulationImpl {
|
|||
let compiled_value = self
|
||||
.get_module_mut(which_module)
|
||||
.write_helper(io, which_module);
|
||||
self.event_queue.add_event_for_now(EventKind::State, None);
|
||||
self.event_queue.add_event_for_now(EventKind::State);
|
||||
assert_eq!(Expr::ty(io), SimValue::ty(value));
|
||||
Self::read_write_sim_value_helper(
|
||||
&mut self.state,
|
||||
|
|
@ -2781,6 +3038,7 @@ impl SimulationImpl {
|
|||
value.clone_from(&opaque.sim_only_values()[index]);
|
||||
},
|
||||
);
|
||||
self.debug_write(compiled_value);
|
||||
}
|
||||
#[track_caller]
|
||||
fn settle_if_needed<F, O>(this_ref: &Rc<RefCell<Self>>, v: MaybeNeedsSettle<F, O>) -> O
|
||||
|
|
@ -2946,11 +3204,14 @@ impl<T: fmt::Debug, V> fmt::Debug for SortedSetDebug<'_, T, V> {
|
|||
}
|
||||
}
|
||||
|
||||
struct SortedMapDebug<'a, K: 'static + Send + Sync, V>(&'a BTreeMap<Interned<K>, V>);
|
||||
struct SortedMapDebug<'a, T>(&'a T);
|
||||
|
||||
impl<K: 'static + Send + Sync + fmt::Debug, V: fmt::Debug> fmt::Debug for SortedMapDebug<'_, K, V> {
|
||||
impl<'a, K: fmt::Debug + 'a, V: fmt::Debug + 'a, T> fmt::Debug for SortedMapDebug<'a, T>
|
||||
where
|
||||
&'a T: IntoIterator<Item = (&'a K, &'a V)>,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut entries = Vec::from_iter(self.0.iter().map(|(k, v)| {
|
||||
let mut entries = Vec::from_iter(self.0.into_iter().map(|(k, v)| {
|
||||
if f.alternate() {
|
||||
(format!("{k:#?}"), format!("{v:#?}"))
|
||||
} else {
|
||||
|
|
@ -3001,7 +3262,7 @@ macro_rules! impl_simulation_methods {
|
|||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bool_or_int(io, $which_module);
|
||||
.read_bool_or_int(io, ReadTime::Current, $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
$(#[$track_caller])?
|
||||
|
|
@ -3032,7 +3293,7 @@ macro_rules! impl_simulation_methods {
|
|||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
.read_bit(Expr::canonical(io), ReadTime::Current, $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
$(#[$track_caller])?
|
||||
|
|
@ -3046,7 +3307,7 @@ macro_rules! impl_simulation_methods {
|
|||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
.read_bit(Expr::canonical(io), ReadTime::Current, $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
$(#[$track_caller])?
|
||||
|
|
@ -3060,7 +3321,7 @@ macro_rules! impl_simulation_methods {
|
|||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read_bit(Expr::canonical(io), $which_module);
|
||||
.read_bit(Expr::canonical(io), ReadTime::Current, $which_module);
|
||||
$self.settle_if_needed(retval)$(.$await)?
|
||||
}
|
||||
#[track_caller]
|
||||
|
|
@ -3075,7 +3336,7 @@ macro_rules! impl_simulation_methods {
|
|||
let retval = $self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read(Expr::canonical(io), $which_module).1;
|
||||
.read(Expr::canonical(io), ReadTime::Current, $which_module).1;
|
||||
SimValue::from_canonical($self.settle_if_needed(retval)$(.$await)?)
|
||||
}
|
||||
$(#[$track_caller])?
|
||||
|
|
@ -3152,11 +3413,13 @@ impl<T: BundleType> Simulation<T> {
|
|||
#[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) {
|
||||
self.sim_impl.borrow_mut().breakpoints = Some(BreakpointsSet {
|
||||
let mut sim_impl = self.sim_impl.borrow_mut();
|
||||
sim_impl.breakpoints = Some(BreakpointsSet {
|
||||
last_was_break: false,
|
||||
set: pcs,
|
||||
trace,
|
||||
});
|
||||
sim_impl.event_queue.lock().trace = trace;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3211,7 +3474,10 @@ impl ExternModuleSimulationState {
|
|||
};
|
||||
for io in iter {
|
||||
let io = Expr::canonical(io.to_expr());
|
||||
let (key, value) = self.sim_impl.borrow_mut().read(io, which_module);
|
||||
let (key, value) = self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read(io, ReadTime::Current, which_module);
|
||||
let value = self.settle_if_needed(value).await;
|
||||
let key = Rc::new(key);
|
||||
if sensitivity_set.compiled_values.insert(key.clone()) {
|
||||
|
|
@ -3469,6 +3735,102 @@ impl ExternModuleSimulationState {
|
|||
.expect("filled by running all futures to completion"),
|
||||
}
|
||||
}
|
||||
/// Reads the value of `io` from right before the last clock edge of `clock_for_past`.
|
||||
///
|
||||
/// In order to use the `read_past()` family of functions, you must call [`m.register_clock_for_past(my_io.clk)`]
|
||||
/// in the module's body for every clock you use as the second argument of the `read_past()` family.
|
||||
///
|
||||
/// [`m.register_clock_for_past(my_io.clk)`]: crate::module::ModuleBuilder::register_clock_for_past
|
||||
pub async fn read_past_bool_or_int<I: BoolOrIntType>(
|
||||
&mut self,
|
||||
io: Expr<I>,
|
||||
clock_for_past: Expr<Clock>,
|
||||
) -> I::Value {
|
||||
let retval = self.sim_impl.borrow_mut().read_bool_or_int(
|
||||
io,
|
||||
ReadTime::Past { clock_for_past },
|
||||
WhichModule::Extern {
|
||||
module_index: self.module_index,
|
||||
},
|
||||
);
|
||||
self.settle_if_needed(retval).await
|
||||
}
|
||||
/// Reads the value of `io` from right before the last clock edge of `clock_for_past`.
|
||||
///
|
||||
/// In order to use the `read_past()` family of functions, you must call [`m.register_clock_for_past(my_io.clk)`]
|
||||
/// in the module's body for every clock you use as the second argument of the `read_past()` family.
|
||||
///
|
||||
/// [`m.register_clock_for_past(my_io.clk)`]: crate::module::ModuleBuilder::register_clock_for_past
|
||||
pub async fn read_past_clock(&mut self, io: Expr<Clock>, clock_for_past: Expr<Clock>) -> bool {
|
||||
let retval = self.sim_impl.borrow_mut().read_bit(
|
||||
Expr::canonical(io),
|
||||
ReadTime::Past { clock_for_past },
|
||||
WhichModule::Extern {
|
||||
module_index: self.module_index,
|
||||
},
|
||||
);
|
||||
self.settle_if_needed(retval).await
|
||||
}
|
||||
/// Reads the value of `io` from right before the last clock edge of `clock_for_past`.
|
||||
///
|
||||
/// In order to use the `read_past()` family of functions, you must call [`m.register_clock_for_past(my_io.clk)`]
|
||||
/// in the module's body for every clock you use as the second argument of the `read_past()` family.
|
||||
///
|
||||
/// [`m.register_clock_for_past(my_io.clk)`]: crate::module::ModuleBuilder::register_clock_for_past
|
||||
pub async fn read_past_bool(&mut self, io: Expr<Bool>, clock_for_past: Expr<Clock>) -> bool {
|
||||
let retval = self.sim_impl.borrow_mut().read_bit(
|
||||
Expr::canonical(io),
|
||||
ReadTime::Past { clock_for_past },
|
||||
WhichModule::Extern {
|
||||
module_index: self.module_index,
|
||||
},
|
||||
);
|
||||
self.settle_if_needed(retval).await
|
||||
}
|
||||
/// Reads the value of `io` from right before the last clock edge of `clock_for_past`.
|
||||
///
|
||||
/// In order to use the `read_past()` family of functions, you must call [`m.register_clock_for_past(my_io.clk)`]
|
||||
/// in the module's body for every clock you use as the second argument of the `read_past()` family.
|
||||
///
|
||||
/// [`m.register_clock_for_past(my_io.clk)`]: crate::module::ModuleBuilder::register_clock_for_past
|
||||
pub async fn read_past_reset<R: ResetType>(
|
||||
&mut self,
|
||||
io: Expr<R>,
|
||||
clock_for_past: Expr<Clock>,
|
||||
) -> bool {
|
||||
let retval = self.sim_impl.borrow_mut().read_bit(
|
||||
Expr::canonical(io),
|
||||
ReadTime::Past { clock_for_past },
|
||||
WhichModule::Extern {
|
||||
module_index: self.module_index,
|
||||
},
|
||||
);
|
||||
self.settle_if_needed(retval).await
|
||||
}
|
||||
/// Reads the value of `io` from right before the last clock edge of `clock_for_past`.
|
||||
///
|
||||
/// In order to use the `read_past()` family of functions, you must call [`m.register_clock_for_past(my_io.clk)`]
|
||||
/// in the module's body for every clock you use as the second argument of the `read_past()` family.
|
||||
///
|
||||
/// [`m.register_clock_for_past(my_io.clk)`]: crate::module::ModuleBuilder::register_clock_for_past
|
||||
pub async fn read_past<IO: Type>(
|
||||
&mut self,
|
||||
io: Expr<IO>,
|
||||
clock_for_past: Expr<Clock>,
|
||||
) -> SimValue<IO> {
|
||||
let retval = self
|
||||
.sim_impl
|
||||
.borrow_mut()
|
||||
.read(
|
||||
Expr::canonical(io),
|
||||
ReadTime::Past { clock_for_past },
|
||||
WhichModule::Extern {
|
||||
module_index: self.module_index,
|
||||
},
|
||||
)
|
||||
.1;
|
||||
SimValue::from_canonical(self.settle_if_needed(retval).await)
|
||||
}
|
||||
impl_simulation_methods!(
|
||||
async_await = (async, await),
|
||||
track_caller = (),
|
||||
|
|
@ -3803,7 +4165,7 @@ impl fmt::Debug for ExternModuleSimulation {
|
|||
.field("generator", &self.generator)
|
||||
.field(
|
||||
"sim_io_to_generator_map",
|
||||
&SortedMapDebug(&self.sim_io_to_generator_map),
|
||||
&SortedMapDebug(&*self.sim_io_to_generator_map),
|
||||
)
|
||||
.field("source_location", &self.source_location)
|
||||
.finish()
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ use crate::{
|
|||
TraceMemoryLocation, TraceModule, TraceModuleIO, TracePhantomConst, TraceReg, TraceSInt,
|
||||
TraceScalarId, TraceScope, TraceSimOnly, TraceSyncReset, TraceUInt, TraceWire,
|
||||
interpreter::{
|
||||
Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding,
|
||||
InsnsBuildingDone, InsnsBuildingKind, Label, SmallUInt, StatePartArrayIndex,
|
||||
StatePartArrayIndexed,
|
||||
self, Insn, InsnField, InsnFieldKind, InsnFieldType, InsnOrLabel, Insns, InsnsBuilding,
|
||||
InsnsBuildingDone, InsnsBuildingKind, Label, PrefixLinesWrapper, SmallUInt,
|
||||
StatePartArrayIndex, StatePartArrayIndexed,
|
||||
parts::{
|
||||
MemoryData, SlotDebugData, StatePartIndex, StatePartIndexRange, StatePartKind,
|
||||
StatePartKindBigSlots, StatePartKindMemories, StatePartKindSimOnlySlots,
|
||||
|
|
@ -82,20 +82,73 @@ pub(crate) struct CompiledBundleField {
|
|||
pub(crate) ty: CompiledTypeLayout<CanonicalType>,
|
||||
}
|
||||
|
||||
impl CompiledBundleField {
|
||||
fn with_prefixed_debug_names(self, prefix: &str) -> Self {
|
||||
let Self { offset, ty } = self;
|
||||
Self {
|
||||
offset,
|
||||
ty: ty.with_prefixed_debug_names(prefix),
|
||||
}
|
||||
}
|
||||
fn with_anonymized_debug_info(self) -> Self {
|
||||
let Self { offset, ty } = self;
|
||||
Self {
|
||||
offset,
|
||||
ty: ty.with_anonymized_debug_info(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub(crate) enum CompiledTypeLayoutBody {
|
||||
Scalar,
|
||||
PhantomConst,
|
||||
Array {
|
||||
/// debug names are ignored, use parent's layout instead
|
||||
element: Interned<CompiledTypeLayout<CanonicalType>>,
|
||||
/// always has at least one element even for zero-sized arrays
|
||||
elements_non_empty: Interned<[CompiledTypeLayout<CanonicalType>]>,
|
||||
},
|
||||
Bundle {
|
||||
/// debug names are ignored, use parent's layout instead
|
||||
fields: Interned<[CompiledBundleField]>,
|
||||
},
|
||||
}
|
||||
|
||||
impl CompiledTypeLayoutBody {
|
||||
fn with_prefixed_debug_names(self, prefix: &str) -> Self {
|
||||
match self {
|
||||
CompiledTypeLayoutBody::Scalar | CompiledTypeLayoutBody::PhantomConst => self,
|
||||
CompiledTypeLayoutBody::Array { elements_non_empty } => CompiledTypeLayoutBody::Array {
|
||||
elements_non_empty: elements_non_empty
|
||||
.iter()
|
||||
.map(|element| element.with_prefixed_debug_names(prefix))
|
||||
.collect(),
|
||||
},
|
||||
CompiledTypeLayoutBody::Bundle { fields } => CompiledTypeLayoutBody::Bundle {
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| field.with_prefixed_debug_names(prefix))
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
fn with_anonymized_debug_info(self) -> Self {
|
||||
match self {
|
||||
CompiledTypeLayoutBody::Scalar | CompiledTypeLayoutBody::PhantomConst => self,
|
||||
CompiledTypeLayoutBody::Array { elements_non_empty } => CompiledTypeLayoutBody::Array {
|
||||
elements_non_empty: elements_non_empty
|
||||
.iter()
|
||||
.map(|element| element.with_anonymized_debug_info())
|
||||
.collect(),
|
||||
},
|
||||
CompiledTypeLayoutBody::Bundle { fields } => CompiledTypeLayoutBody::Bundle {
|
||||
fields: fields
|
||||
.iter()
|
||||
.map(|field| field.with_anonymized_debug_info())
|
||||
.collect(),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Hash, Clone, Copy)]
|
||||
pub(crate) struct CompiledTypeLayout<T: Type> {
|
||||
pub(crate) ty: T,
|
||||
|
|
@ -109,7 +162,7 @@ impl<T: Type> CompiledTypeLayout<T> {
|
|||
Self {
|
||||
ty,
|
||||
layout: layout.with_prefixed_debug_names(prefix),
|
||||
body,
|
||||
body: body.with_prefixed_debug_names(prefix),
|
||||
}
|
||||
}
|
||||
fn with_anonymized_debug_info(self) -> Self {
|
||||
|
|
@ -117,7 +170,7 @@ impl<T: Type> CompiledTypeLayout<T> {
|
|||
Self {
|
||||
ty,
|
||||
layout: layout.with_anonymized_debug_info(),
|
||||
body,
|
||||
body: body.with_anonymized_debug_info(),
|
||||
}
|
||||
}
|
||||
fn get(ty: T) -> Self {
|
||||
|
|
@ -152,18 +205,22 @@ impl<T: Type> CompiledTypeLayout<T> {
|
|||
}
|
||||
CanonicalType::Array(array) => {
|
||||
let mut layout = TypeLayout::empty();
|
||||
let element = CompiledTypeLayout::get(array.element()).intern_sized();
|
||||
let element = CompiledTypeLayout::get(array.element());
|
||||
let mut elements_non_empty = vec![];
|
||||
for index in 0..array.len() {
|
||||
layout.allocate(
|
||||
&element
|
||||
.layout
|
||||
.with_prefixed_debug_names(&format!("[{index}]")),
|
||||
);
|
||||
let element = element.with_prefixed_debug_names(&format!("[{index}]"));
|
||||
layout.allocate(&element.layout);
|
||||
elements_non_empty.push(element);
|
||||
}
|
||||
if array.is_empty() {
|
||||
elements_non_empty.push(element.with_prefixed_debug_names("[<none>]"));
|
||||
}
|
||||
CompiledTypeLayout {
|
||||
ty: *input,
|
||||
layout: layout.into(),
|
||||
body: CompiledTypeLayoutBody::Array { element },
|
||||
body: CompiledTypeLayoutBody::Array {
|
||||
elements_non_empty: elements_non_empty.intern_deref(),
|
||||
},
|
||||
}
|
||||
}
|
||||
CanonicalType::PhantomConst(_) => CompiledTypeLayout {
|
||||
|
|
@ -182,13 +239,9 @@ impl<T: Type> CompiledTypeLayout<T> {
|
|||
flipped: _,
|
||||
ty,
|
||||
}| {
|
||||
let ty = CompiledTypeLayout::get(*ty);
|
||||
let offset = layout
|
||||
.allocate(
|
||||
&ty.layout
|
||||
.with_prefixed_debug_names(&format!(".{name}")),
|
||||
)
|
||||
.start();
|
||||
let ty = CompiledTypeLayout::get(*ty)
|
||||
.with_prefixed_debug_names(&format!(".{name}"));
|
||||
let offset = layout.allocate(&ty.layout).start();
|
||||
CompiledBundleField { offset, ty }
|
||||
},
|
||||
)
|
||||
|
|
@ -271,6 +324,39 @@ impl<T: Type> CompiledValue<T> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) struct DebugCompiledValueStateAsMap<'a> {
|
||||
pub(crate) compiled_value: CompiledValue<CanonicalType>,
|
||||
pub(crate) state_layout: &'a interpreter::parts::StateLayout<InsnsBuildingDone>,
|
||||
pub(crate) state: &'a interpreter::State,
|
||||
}
|
||||
|
||||
impl fmt::Debug for DebugCompiledValueStateAsMap<'_> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
use fmt::Write;
|
||||
if self.compiled_value.range.is_empty() {
|
||||
return f.write_str("{}");
|
||||
}
|
||||
writeln!(f, "{{")?;
|
||||
let mut f = PrefixLinesWrapper::new(f, true, " ");
|
||||
macro_rules! debug_fmt {
|
||||
(
|
||||
type_plural_fields = [$($type_plural_field:ident,)*];
|
||||
) => {
|
||||
$(for slot in self.compiled_value.range.$type_plural_field.iter() {
|
||||
slot.debug_fmt(&mut f, ":", " ", " ", "", Some(self.state_layout), Some(self.state))?;
|
||||
writeln!(f, ",")?;
|
||||
})*
|
||||
};
|
||||
}
|
||||
get_state_part_kinds! {
|
||||
debug_fmt! {
|
||||
type_plural_fields;
|
||||
}
|
||||
}
|
||||
write!(f.into_inner(), "}}")
|
||||
}
|
||||
}
|
||||
|
||||
impl CompiledValue<Bundle> {
|
||||
fn field_by_index(self, field_index: usize) -> CompiledValue<CanonicalType> {
|
||||
self.map(|layout, range| {
|
||||
|
|
@ -299,10 +385,13 @@ impl CompiledValue<Bundle> {
|
|||
impl CompiledValue<Array> {
|
||||
pub(crate) fn element(self, index: usize) -> CompiledValue<CanonicalType> {
|
||||
self.map(|layout, range| {
|
||||
let CompiledTypeLayoutBody::Array { element } = layout.body else {
|
||||
let CompiledTypeLayoutBody::Array { elements_non_empty } = layout.body else {
|
||||
unreachable!();
|
||||
};
|
||||
(*element, range.index_array(element.layout.len(), index))
|
||||
(
|
||||
elements_non_empty[index],
|
||||
range.index_array(elements_non_empty[index].layout.len(), index),
|
||||
)
|
||||
})
|
||||
}
|
||||
fn element_dyn(
|
||||
|
|
@ -555,10 +644,11 @@ impl CompiledExpr<Array> {
|
|||
self,
|
||||
index_slot: StatePartIndex<StatePartKindSmallSlots>,
|
||||
) -> CompiledExpr<CanonicalType> {
|
||||
let CompiledTypeLayoutBody::Array { element } = self.static_part.layout.body else {
|
||||
let CompiledTypeLayoutBody::Array { elements_non_empty } = self.static_part.layout.body
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
let stride = element.layout.len();
|
||||
let stride = elements_non_empty[0].layout.len();
|
||||
let indexes = self.indexes.join(TypeArrayIndex::from_parts(
|
||||
index_slot,
|
||||
self.static_part.layout.ty.len(),
|
||||
|
|
@ -566,10 +656,10 @@ impl CompiledExpr<Array> {
|
|||
));
|
||||
CompiledExpr {
|
||||
static_part: self.static_part.map(|layout, range| {
|
||||
let CompiledTypeLayoutBody::Array { element } = layout.body else {
|
||||
let CompiledTypeLayoutBody::Array { elements_non_empty } = layout.body else {
|
||||
unreachable!();
|
||||
};
|
||||
(*element, range.index_array(stride, 0))
|
||||
(elements_non_empty[0], range.index_array(stride, 0))
|
||||
}),
|
||||
indexes,
|
||||
}
|
||||
|
|
@ -1548,6 +1638,13 @@ struct ClockTrigger {
|
|||
source_location: SourceLocation,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||
pub(crate) struct ExternModuleClockForPast {
|
||||
pub(crate) clock_for_past: CompiledValue<Clock>,
|
||||
pub(crate) current_to_past_map:
|
||||
Interned<[(CompiledValue<CanonicalType>, CompiledValue<CanonicalType>)]>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Register {
|
||||
value: CompiledValue<CanonicalType>,
|
||||
|
|
@ -1635,7 +1732,9 @@ impl<T> fmt::Debug for DebugOpaque<T> {
|
|||
pub(crate) struct CompiledExternModule {
|
||||
pub(crate) module_io_targets: Interned<[Target]>,
|
||||
pub(crate) module_io: Interned<[CompiledValue<CanonicalType>]>,
|
||||
pub(crate) clocks_for_past: Interned<[ExternModuleClockForPast]>,
|
||||
pub(crate) simulation: ExternModuleSimulation,
|
||||
pub(crate) debug_name: Interned<str>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -3915,18 +4014,15 @@ impl Compiler {
|
|||
self.enum_discriminants.insert(enum_value, retval);
|
||||
retval
|
||||
}
|
||||
fn compile_stmt_reg<R: ResetType>(
|
||||
fn compile_reg<R: ResetType>(
|
||||
&mut self,
|
||||
stmt_reg: StmtReg<R>,
|
||||
clk: CompiledValue<Clock>,
|
||||
reset_and_init: Option<(Expr<R>, CompiledValue<CanonicalType>)>,
|
||||
source_location: SourceLocation,
|
||||
instantiated_module: InstantiatedModule,
|
||||
value: CompiledValue<CanonicalType>,
|
||||
) {
|
||||
let StmtReg { annotations, reg } = stmt_reg;
|
||||
let clk = self.compile_expr(instantiated_module, Expr::canonical(reg.clock_domain().clk));
|
||||
let clk = self
|
||||
.compiled_expr_to_value(clk, reg.source_location())
|
||||
.map_ty(Clock::from_canonical);
|
||||
let clk = self.compile_clock(clk, reg.source_location());
|
||||
let clk = self.compile_clock(clk, source_location);
|
||||
struct Dispatch;
|
||||
impl ResetTypeDispatch for Dispatch {
|
||||
type Input<T: ResetType> = ();
|
||||
|
|
@ -3945,18 +4041,15 @@ impl Compiler {
|
|||
true
|
||||
}
|
||||
}
|
||||
let reset = if let Some(init) = reg.init() {
|
||||
let init = self.compile_expr(instantiated_module, init);
|
||||
let init = self.compiled_expr_to_value(init, reg.source_location());
|
||||
let rst =
|
||||
self.compile_expr(instantiated_module, Expr::canonical(reg.clock_domain().rst));
|
||||
let rst = self.compiled_expr_to_value(rst, reg.source_location());
|
||||
let rst = self.compiled_value_bool_dest_is_small(rst, reg.source_location());
|
||||
let reset = if let Some((rst_expr, init)) = reset_and_init {
|
||||
let rst = self.compile_expr(instantiated_module, Expr::canonical(rst_expr));
|
||||
let rst = self.compiled_expr_to_value(rst, source_location);
|
||||
let rst = self.compiled_value_bool_dest_is_small(rst, source_location);
|
||||
let is_async = R::dispatch((), Dispatch);
|
||||
if is_async {
|
||||
let cond = Expr::canonical(reg.clock_domain().rst.cast_to(Bool));
|
||||
let cond = Expr::canonical(rst_expr.cast_to(Bool));
|
||||
let cond = self.compile_expr(instantiated_module, cond);
|
||||
let cond = self.compiled_expr_to_value(cond, reg.source_location());
|
||||
let cond = self.compiled_expr_to_value(cond, source_location);
|
||||
let cond = cond.map_ty(Bool::from_canonical);
|
||||
// write to the register's current value since asynchronous reset is combinational
|
||||
let lhs = CompiledValue {
|
||||
|
|
@ -3968,12 +4061,12 @@ impl Compiler {
|
|||
self.compile_simple_connect(
|
||||
[Cond {
|
||||
body: CondBody::IfTrue { cond },
|
||||
source_location: reg.source_location(),
|
||||
source_location: source_location,
|
||||
}]
|
||||
.intern_slice(),
|
||||
lhs,
|
||||
init,
|
||||
reg.source_location(),
|
||||
source_location,
|
||||
);
|
||||
}
|
||||
Some(RegisterReset {
|
||||
|
|
@ -3988,9 +4081,33 @@ impl Compiler {
|
|||
value,
|
||||
clk_triggered: clk.clk_triggered,
|
||||
reset,
|
||||
source_location: reg.source_location(),
|
||||
source_location,
|
||||
});
|
||||
}
|
||||
fn compile_stmt_reg<R: ResetType>(
|
||||
&mut self,
|
||||
stmt_reg: StmtReg<R>,
|
||||
instantiated_module: InstantiatedModule,
|
||||
value: CompiledValue<CanonicalType>,
|
||||
) {
|
||||
let StmtReg { annotations, reg } = stmt_reg;
|
||||
let clk = self.compile_expr(instantiated_module, Expr::canonical(reg.clock_domain().clk));
|
||||
let clk = self
|
||||
.compiled_expr_to_value(clk, reg.source_location())
|
||||
.map_ty(Clock::from_canonical);
|
||||
let reset_and_init = reg.init().map(|init| {
|
||||
let init = self.compile_expr(instantiated_module, init);
|
||||
let init = self.compiled_expr_to_value(init, reg.source_location());
|
||||
(reg.clock_domain().rst, init)
|
||||
});
|
||||
self.compile_reg(
|
||||
clk,
|
||||
reset_and_init,
|
||||
reg.source_location(),
|
||||
instantiated_module,
|
||||
value,
|
||||
);
|
||||
}
|
||||
fn compile_declaration(
|
||||
&mut self,
|
||||
declaration: StmtDeclaration,
|
||||
|
|
@ -4256,24 +4373,24 @@ impl Compiler {
|
|||
insns.push(end_label.into());
|
||||
}
|
||||
}
|
||||
CompiledTypeLayoutBody::Array { element } => {
|
||||
CompiledTypeLayoutBody::Array { elements_non_empty } => {
|
||||
let CompiledTypeLayoutBody::Array {
|
||||
element: mask_element,
|
||||
elements_non_empty: mask_elements_non_empty,
|
||||
} = mask_layout.body
|
||||
else {
|
||||
unreachable!();
|
||||
};
|
||||
let ty = <Array>::from_canonical(data_layout.ty);
|
||||
let element_bit_width = ty.element().bit_width();
|
||||
let element_size = element.layout.len();
|
||||
let mask_element_size = mask_element.layout.len();
|
||||
let element_size = elements_non_empty[0].layout.len();
|
||||
let mask_element_size = mask_elements_non_empty[0].layout.len();
|
||||
for element_index in 0..ty.len() {
|
||||
self.compile_memory_port_rw_helper(
|
||||
memory,
|
||||
stride,
|
||||
start,
|
||||
*element,
|
||||
*mask_element,
|
||||
elements_non_empty[element_index],
|
||||
mask_elements_non_empty[element_index],
|
||||
read.as_mut().map(
|
||||
|MemoryPortReadInsns {
|
||||
addr,
|
||||
|
|
@ -4880,6 +4997,88 @@ impl Compiler {
|
|||
}
|
||||
}
|
||||
}
|
||||
fn compile_extern_module_clock_for_past(
|
||||
&mut self,
|
||||
instantiated_module: InstantiatedModule,
|
||||
clock_for_past: Target,
|
||||
) -> ExternModuleClockForPast {
|
||||
let clock_for_past = TargetInInstantiatedModule {
|
||||
instantiated_module,
|
||||
target: clock_for_past,
|
||||
};
|
||||
let clock_for_past = self
|
||||
.compile_value(clock_for_past)
|
||||
.map_ty(Clock::from_canonical);
|
||||
let clock_for_past_debug_name = match clock_for_past
|
||||
.range
|
||||
.len()
|
||||
.as_single()
|
||||
.expect("Clock is a single slot")
|
||||
{
|
||||
TypeLenSingle::BigSlot => {
|
||||
self.insns
|
||||
.state_layout
|
||||
.ty
|
||||
.big_slots
|
||||
.debug_data(clock_for_past.range.start().big_slots)
|
||||
.name
|
||||
}
|
||||
TypeLenSingle::SmallSlot => {
|
||||
self.insns
|
||||
.state_layout
|
||||
.ty
|
||||
.small_slots
|
||||
.debug_data(clock_for_past.range.start().small_slots)
|
||||
.name
|
||||
}
|
||||
TypeLenSingle::SimOnlySlot => {
|
||||
unreachable!()
|
||||
}
|
||||
};
|
||||
let module_prefix = format!("{instantiated_module:?}.");
|
||||
let trimmed_clock_for_past_debug_name = clock_for_past_debug_name
|
||||
.strip_prefix(&module_prefix)
|
||||
.unwrap_or(&clock_for_past_debug_name);
|
||||
let current_to_past_map = instantiated_module
|
||||
.leaf_module()
|
||||
.module_io()
|
||||
.iter()
|
||||
.map(
|
||||
|&AnnotatedModuleIO {
|
||||
annotations: _,
|
||||
module_io,
|
||||
}| {
|
||||
let target_base = TargetBase::from(module_io);
|
||||
let current = self.compile_value(TargetInInstantiatedModule {
|
||||
instantiated_module,
|
||||
target: target_base.into(),
|
||||
});
|
||||
let unprefixed_layout = CompiledTypeLayout::get(module_io.ty());
|
||||
let past_layout = unprefixed_layout.with_prefixed_debug_names(&format!(
|
||||
"{module_prefix}{:?}$past({trimmed_clock_for_past_debug_name})",
|
||||
target_base.target_name(),
|
||||
));
|
||||
let past = CompiledValue {
|
||||
range: self.insns.allocate_variable(&past_layout.layout),
|
||||
layout: past_layout,
|
||||
write: Some((current.layout, current.range)),
|
||||
};
|
||||
self.compile_reg::<SyncReset>(
|
||||
clock_for_past,
|
||||
None,
|
||||
module_io.source_location(),
|
||||
instantiated_module,
|
||||
past,
|
||||
);
|
||||
(current, past)
|
||||
},
|
||||
)
|
||||
.collect();
|
||||
ExternModuleClockForPast {
|
||||
clock_for_past,
|
||||
current_to_past_map,
|
||||
}
|
||||
}
|
||||
fn compile_module(&mut self, module: Interned<InstantiatedModule>) -> &CompiledModule {
|
||||
let mut trace_decls = Vec::new();
|
||||
let module_io = module
|
||||
|
|
@ -4908,6 +5107,7 @@ impl Compiler {
|
|||
ModuleBody::Extern(ExternModuleBody {
|
||||
verilog_name: _,
|
||||
parameters: _,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
}) => {
|
||||
let Some(simulation) = simulation else {
|
||||
|
|
@ -4924,10 +5124,18 @@ impl Compiler {
|
|||
Target::from(*simulation.sim_io_to_generator_map[&v.module_io.intern()])
|
||||
})
|
||||
.collect();
|
||||
let clocks_for_past = clocks_for_past
|
||||
.iter()
|
||||
.map(|clock_for_past| {
|
||||
self.compile_extern_module_clock_for_past(*module, *clock_for_past)
|
||||
})
|
||||
.collect();
|
||||
self.extern_modules.push(CompiledExternModule {
|
||||
module_io_targets,
|
||||
module_io,
|
||||
clocks_for_past,
|
||||
simulation,
|
||||
debug_name: format!("{module:?}").intern_deref(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -196,13 +196,27 @@ impl fmt::Debug for Insn {
|
|||
}
|
||||
}
|
||||
|
||||
struct PrefixLinesWrapper<'a, W> {
|
||||
pub(crate) struct PrefixLinesWrapper<'a, W> {
|
||||
writer: W,
|
||||
at_beginning_of_line: bool,
|
||||
blank_line_prefix: &'a str,
|
||||
line_prefix: &'a str,
|
||||
}
|
||||
|
||||
impl<'a, W> PrefixLinesWrapper<'a, W> {
|
||||
pub(crate) fn new(writer: W, at_beginning_of_line: bool, line_prefix: &'a str) -> Self {
|
||||
Self {
|
||||
writer,
|
||||
at_beginning_of_line,
|
||||
blank_line_prefix: line_prefix.trim_end(),
|
||||
line_prefix,
|
||||
}
|
||||
}
|
||||
pub(crate) fn into_inner(self) -> W {
|
||||
self.writer
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: fmt::Write> fmt::Write for PrefixLinesWrapper<'_, T> {
|
||||
fn write_str(&mut self, input: &str) -> fmt::Result {
|
||||
for part in input.split_inclusive('\n') {
|
||||
|
|
@ -239,12 +253,7 @@ impl Insn {
|
|||
if fields.len() == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
let mut f = PrefixLinesWrapper {
|
||||
writer: f,
|
||||
at_beginning_of_line: false,
|
||||
blank_line_prefix: "",
|
||||
line_prefix: " ",
|
||||
};
|
||||
let mut f = PrefixLinesWrapper::new(f, false, " ");
|
||||
writeln!(f, " {{")?;
|
||||
for (field_name, field) in fields {
|
||||
write!(f, "{field_name}: ")?;
|
||||
|
|
@ -320,7 +329,7 @@ impl Insn {
|
|||
}
|
||||
writeln!(f, ",")?;
|
||||
}
|
||||
write!(f.writer, "}}")
|
||||
write!(f.into_inner(), "}}")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
Insn, InsnsBuilding, InsnsBuildingDone, InsnsBuildingKind, PrefixLinesWrapper,
|
||||
SmallSInt, SmallUInt, State,
|
||||
},
|
||||
value::{DynSimOnlyValue, DynSimOnly},
|
||||
value::{DynSimOnly, DynSimOnlyValue},
|
||||
},
|
||||
ty::CanonicalType,
|
||||
util::{chain, const_str_cmp},
|
||||
|
|
@ -435,12 +435,7 @@ impl<K: StatePartKind> StatePartIndex<K> {
|
|||
if state.is_some() || debug_data.is_some() {
|
||||
f.write_str(comment_start)?;
|
||||
}
|
||||
let mut f = PrefixLinesWrapper {
|
||||
writer: f,
|
||||
at_beginning_of_line: false,
|
||||
blank_line_prefix: comment_line_start.trim_end(),
|
||||
line_prefix: comment_line_start,
|
||||
};
|
||||
let mut f = PrefixLinesWrapper::new(f, false, comment_line_start);
|
||||
if let Some(state) = state {
|
||||
f.write_str("(")?;
|
||||
K::debug_fmt_state_value(state, *self, &mut f)?;
|
||||
|
|
@ -453,7 +448,7 @@ impl<K: StatePartKind> StatePartIndex<K> {
|
|||
write!(f, "{debug_data:?}")?;
|
||||
}
|
||||
if state.is_some() || debug_data.is_some() {
|
||||
f.writer.write_str(comment_end)?;
|
||||
f.into_inner().write_str(comment_end)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -394,6 +394,30 @@ impl SimValuePartialEq<Bool> for Bool {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValuePartialEq for Clock {
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
|
||||
**this == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl SimValuePartialEq for Reset {
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
|
||||
**this == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl SimValuePartialEq for SyncReset {
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
|
||||
**this == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl SimValuePartialEq for AsyncReset {
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
|
||||
**this == **other
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToSimValue: ToSimValueWithType<<Self as ToSimValue>::Type> {
|
||||
type Type: Type;
|
||||
|
||||
|
|
@ -1302,6 +1326,20 @@ impl<T: SimOnlyValueTrait> ToSimValue for SimOnlyValue<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl SimValuePartialEq for DynSimOnly {
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<Self>) -> bool {
|
||||
**this == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait + PartialEq<U>, U: SimOnlyValueTrait> SimValuePartialEq<SimOnly<U>>
|
||||
for SimOnly<T>
|
||||
{
|
||||
fn sim_value_eq(this: &SimValue<Self>, other: &SimValue<SimOnly<U>>) -> bool {
|
||||
***this == ***other
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
|||
|
|
@ -206,9 +206,25 @@ impl<T: SimOnlyValueTrait> Default for SimOnly<T> {
|
|||
}
|
||||
|
||||
/// a value that can only be used in a Fayalite simulation, it can't be converted to FIRRTL
|
||||
#[derive(Clone, Eq, PartialEq, Hash, Default, PartialOrd, Ord)]
|
||||
#[derive(Clone, Eq, Hash, Default, Ord)]
|
||||
pub struct SimOnlyValue<T: SimOnlyValueTrait>(Rc<T>);
|
||||
|
||||
impl<T: SimOnlyValueTrait + PartialEq<U>, U: SimOnlyValueTrait> PartialEq<SimOnlyValue<U>>
|
||||
for SimOnlyValue<T>
|
||||
{
|
||||
fn eq(&self, other: &SimOnlyValue<U>) -> bool {
|
||||
<T as PartialEq<U>>::eq(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait + PartialOrd<U>, U: SimOnlyValueTrait> PartialOrd<SimOnlyValue<U>>
|
||||
for SimOnlyValue<T>
|
||||
{
|
||||
fn partial_cmp(&self, other: &SimOnlyValue<U>) -> Option<std::cmp::Ordering> {
|
||||
<T as PartialOrd<U>>::partial_cmp(self, other)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: SimOnlyValueTrait> SimOnlyValue<T> {
|
||||
pub fn with_dyn_ref<F: FnOnce(&DynSimOnlyValue) -> R, R>(&self, f: F) -> R {
|
||||
// Safety: creating a copied `Rc<T>` is safe as long as the copy isn't dropped and isn't changed
|
||||
|
|
|
|||
|
|
@ -2375,3 +2375,123 @@ fn test_phantom_const() {
|
|||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl_module(outline_generated, extern)]
|
||||
pub fn sim_read_past<const N: usize>()
|
||||
where
|
||||
ConstUsize<N>: KnownSize,
|
||||
{
|
||||
#[hdl]
|
||||
let clocks: Array<Clock, N> = m.input();
|
||||
#[hdl]
|
||||
let outputs: Array<UInt<8>, N> = m.output();
|
||||
#[hdl]
|
||||
let past_clocks: Array<Clock, N> = m.output();
|
||||
#[hdl]
|
||||
let past_outputs: Array<UInt<8>, N> = m.output();
|
||||
for clock in clocks {
|
||||
m.register_clock_for_past(clock);
|
||||
}
|
||||
m.extern_module_simulation_fn(
|
||||
(clocks, outputs, past_clocks, past_outputs),
|
||||
|(clocks, outputs, past_clocks, past_outputs), mut sim| async move {
|
||||
sim.write(outputs, [0u8; N]).await;
|
||||
sim.write(past_clocks, [false; N]).await;
|
||||
sim.write(past_outputs, [0u8; N]).await;
|
||||
loop {
|
||||
sim.fork_join_scope(|scope, _| async move {
|
||||
for (clock, output) in clocks.into_iter().zip(outputs) {
|
||||
scope.spawn_detached(
|
||||
move |_, mut sim: ExternModuleSimulationState| async move {
|
||||
sim.wait_for_clock_edge(clock).await;
|
||||
dbg!(clock);
|
||||
let v = sim
|
||||
.read_bool_or_int(output)
|
||||
.await
|
||||
.to_bigint()
|
||||
.try_into()
|
||||
.expect("known to be in range");
|
||||
sim.write(output, 1u8.wrapping_add(v)).await;
|
||||
let past_outputs_v = sim.read_past(outputs, clock).await;
|
||||
dbg!(&past_outputs_v);
|
||||
sim.write(past_outputs, past_outputs_v).await;
|
||||
let past_clocks_v = sim.read_past(clocks, clock).await;
|
||||
dbg!(&past_clocks_v);
|
||||
sim.write(past_clocks, past_clocks_v).await;
|
||||
},
|
||||
);
|
||||
}
|
||||
})
|
||||
.await;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_sim_read_past() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
const N: usize = 3;
|
||||
let mut sim = Simulation::new(sim_read_past::<N>());
|
||||
// sim.set_breakpoints_unstable(Default::default(), true);
|
||||
let mut writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
sim.write(sim.io().clocks, [false; N]);
|
||||
let mut clocks_triggered = [false; N];
|
||||
let mut expected = [0u8; N];
|
||||
let mut past_clocks_expected = [false; N];
|
||||
let mut past_expected = expected;
|
||||
for i0 in 0..N {
|
||||
for i1 in 0..N {
|
||||
for i2 in 0..N {
|
||||
for i3 in 0..N {
|
||||
let indexes = [i0, i1, i2, i3];
|
||||
for i in indexes {
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
sim.write(sim.io().clocks[i], true);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
sim.write(sim.io().clocks[i], false);
|
||||
if !clocks_triggered[i] {
|
||||
past_expected = expected;
|
||||
expected[i] = expected[i].wrapping_add(1);
|
||||
past_clocks_expected = [false; N];
|
||||
past_clocks_expected[i] = true;
|
||||
}
|
||||
dbg!(past_expected);
|
||||
clocks_triggered[i] = true;
|
||||
if clocks_triggered == [true; N] {
|
||||
clocks_triggered = [false; N];
|
||||
}
|
||||
let output = sim.read(sim.io().outputs);
|
||||
assert_eq!(output, expected.to_sim_value(), "indexes={indexes:?} i={i}");
|
||||
let past_clocks = sim.read(sim.io().past_clocks);
|
||||
assert_eq!(
|
||||
past_clocks,
|
||||
past_clocks_expected
|
||||
.to_sim_value_with_type(Array::<Clock, N>::default()),
|
||||
"indexes={indexes:?} i={i}"
|
||||
);
|
||||
let past_outputs = sim.read(sim.io().past_outputs);
|
||||
dbg!(&past_outputs);
|
||||
assert_eq!(
|
||||
past_outputs,
|
||||
past_expected.to_sim_value(),
|
||||
"indexes={indexes:?} i={i}"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sim.flush_traces().unwrap();
|
||||
let vcd = String::from_utf8(writer.take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
if vcd != include_str!("sim/expected/sim_read_past.vcd") {
|
||||
panic!();
|
||||
}
|
||||
let sim_debug = format!("{sim:#?}");
|
||||
println!("#######\n{sim_debug}\n#######");
|
||||
if sim_debug != include_str!("sim/expected/sim_read_past.txt") {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -826,6 +826,7 @@ Simulation {
|
|||
}.write_index,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ Simulation {
|
|||
}.i,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -98,6 +98,7 @@ Simulation {
|
|||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -141,6 +141,7 @@ Simulation {
|
|||
}.reset_out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -100,51 +100,51 @@ Simulation {
|
|||
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: AsyncReset },
|
||||
},
|
||||
3: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.clk", ty: Clock },
|
||||
},
|
||||
4: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
3: Const {
|
||||
5: Const {
|
||||
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
|
||||
value: 0x3,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:3:1
|
||||
4: BranchIfZero {
|
||||
target: 6,
|
||||
6: BranchIfZero {
|
||||
target: 8,
|
||||
value: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
5: Copy {
|
||||
7: Copy {
|
||||
dest: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
|
||||
src: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
6: Add {
|
||||
8: Add {
|
||||
dest: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
|
||||
lhs: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
|
||||
rhs: StatePartIndex<BigSlots>(7), // (0x1) SlotDebugData { name: "", ty: UInt<1> },
|
||||
},
|
||||
7: CastToUInt {
|
||||
9: CastToUInt {
|
||||
dest: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
|
||||
src: StatePartIndex<BigSlots>(8), // (0x4) SlotDebugData { name: "", ty: UInt<5> },
|
||||
dest_width: 4,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:4:1
|
||||
8: Copy {
|
||||
10: Copy {
|
||||
dest: StatePartIndex<BigSlots>(4), // (0x4) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg$next", ty: UInt<4> },
|
||||
src: StatePartIndex<BigSlots>(9), // (0x4) SlotDebugData { name: "", ty: UInt<4> },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:6:1
|
||||
9: Copy {
|
||||
11: Copy {
|
||||
dest: StatePartIndex<BigSlots>(2), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count", ty: UInt<4> },
|
||||
src: StatePartIndex<BigSlots>(3), // (0x3) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::count_reg", ty: UInt<4> },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:3:1
|
||||
10: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.clk", ty: Clock },
|
||||
},
|
||||
11: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
12: BranchIfSmallNonZero {
|
||||
target: 16,
|
||||
value: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
|
|
@ -261,6 +261,7 @@ Simulation {
|
|||
}.count,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -112,21 +112,21 @@ Simulation {
|
|||
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.rst", ty: SyncReset },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
6: Const {
|
||||
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
|
||||
value: 0x3,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:3:1
|
||||
7: IsNonZeroDestIsSmall {
|
||||
6: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(counter: counter).counter::cd.clk", ty: Clock },
|
||||
},
|
||||
8: AndSmall {
|
||||
7: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
8: Const {
|
||||
dest: StatePartIndex<BigSlots>(5), // (0x3) SlotDebugData { name: "", ty: UInt<4> },
|
||||
value: 0x3,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:3:1
|
||||
9: BranchIfSmallZero {
|
||||
target: 14,
|
||||
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
|
|
@ -242,6 +242,7 @@ Simulation {
|
|||
}.count,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ Simulation {
|
|||
uninitialized_ios: {},
|
||||
io_targets: {},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -1003,65 +1003,64 @@ Simulation {
|
|||
dest: StatePartIndex<SmallSlots>(5), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::cd.rst", ty: SyncReset },
|
||||
},
|
||||
97: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::cd.clk", ty: Clock },
|
||||
},
|
||||
98: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
97: Const {
|
||||
99: Const {
|
||||
dest: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> },
|
||||
value: 0x0,
|
||||
},
|
||||
98: Copy {
|
||||
100: Copy {
|
||||
dest: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
src: StatePartIndex<BigSlots>(25), // (0x0) SlotDebugData { name: "", ty: UInt<6> },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:12:1
|
||||
99: BranchIfZero {
|
||||
target: 107,
|
||||
101: BranchIfZero {
|
||||
target: 109,
|
||||
value: StatePartIndex<BigSlots>(2), // (0x1) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::en", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:13:1
|
||||
100: BranchIfZero {
|
||||
target: 102,
|
||||
102: BranchIfZero {
|
||||
target: 104,
|
||||
value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:14:1
|
||||
101: Copy {
|
||||
103: Copy {
|
||||
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
src: StatePartIndex<BigSlots>(26), // (0x0) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:13:1
|
||||
102: BranchIfNonZero {
|
||||
target: 107,
|
||||
104: BranchIfNonZero {
|
||||
target: 109,
|
||||
value: StatePartIndex<BigSlots>(46), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:15:1
|
||||
103: BranchIfZero {
|
||||
target: 105,
|
||||
105: BranchIfZero {
|
||||
target: 107,
|
||||
value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:16:1
|
||||
104: Copy {
|
||||
106: Copy {
|
||||
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
src: StatePartIndex<BigSlots>(65), // (0xd) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:15:1
|
||||
105: BranchIfNonZero {
|
||||
target: 107,
|
||||
107: BranchIfNonZero {
|
||||
target: 109,
|
||||
value: StatePartIndex<BigSlots>(48), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:17:1
|
||||
106: Copy {
|
||||
108: Copy {
|
||||
dest: StatePartIndex<BigSlots>(24), // (0x3e) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::the_reg$next", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
src: StatePartIndex<BigSlots>(87), // (0x3e) SlotDebugData { name: "", ty: Enum {A, B(Bundle {0: UInt<1>, 1: Bool}), C(Bundle {a: Array<UInt<1>, 2>, b: SInt<2>})} },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:11:1
|
||||
107: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::cd.clk", ty: Clock },
|
||||
},
|
||||
108: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(4), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(2), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:10:1
|
||||
109: Copy {
|
||||
dest: StatePartIndex<BigSlots>(15), // (0x0) SlotDebugData { name: "InstantiatedModule(enums: enums).enums::b2_out", ty: Enum {HdlNone, HdlSome(Bundle {0: UInt<1>, 1: Bool})} },
|
||||
|
|
@ -1454,6 +1453,7 @@ Simulation {
|
|||
}.which_out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -102,6 +102,7 @@ Simulation {
|
|||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -136,6 +137,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -228,7 +230,7 @@ Simulation {
|
|||
index: StatePartIndex<BigSlots>(1),
|
||||
},
|
||||
state: 0x1,
|
||||
last_state: 0x1,
|
||||
last_state: 0x0,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
|
|
@ -245,7 +247,14 @@ Simulation {
|
|||
event_queue: EventQueue(EventQueueData {
|
||||
instant: 20 μs,
|
||||
events: {
|
||||
Event { instant: 20.500000000000 μs, kind: ExternModule(0) }: 1,
|
||||
Event {
|
||||
instant: 20.500000000000 μs,
|
||||
kind: ExternModule(
|
||||
0,
|
||||
),
|
||||
}: Wakers(
|
||||
1,
|
||||
),
|
||||
},
|
||||
}),
|
||||
waiting_sensitivity_sets_by_address: {},
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ Simulation {
|
|||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -167,6 +168,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
|
|||
|
|
@ -3834,6 +3834,7 @@ Simulation {
|
|||
}.w[7].mask,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -719,6 +719,7 @@ Simulation {
|
|||
}.w.mask.1,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -677,6 +677,7 @@ Simulation {
|
|||
}.rw.wmode,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -1761,6 +1761,7 @@ Simulation {
|
|||
}.w.mask[7],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -274,6 +274,7 @@ Simulation {
|
|||
}.o.o2,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -240,6 +240,7 @@ Simulation {
|
|||
}.out[1],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -743,6 +743,7 @@ Simulation {
|
|||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -777,6 +778,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -860,6 +862,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -943,6 +946,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
|
|||
|
|
@ -128,21 +128,21 @@ Simulation {
|
|||
dest: StatePartIndex<SmallSlots>(3), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(1), // (0x0) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.rst", ty: SyncReset },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
6: Const {
|
||||
dest: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
value: 0x0,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:5:1
|
||||
7: IsNonZeroDestIsSmall {
|
||||
6: IsNonZeroDestIsSmall {
|
||||
dest: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
src: StatePartIndex<BigSlots>(0), // (0x1) SlotDebugData { name: "InstantiatedModule(shift_register: shift_register).shift_register::cd.clk", ty: Clock },
|
||||
},
|
||||
8: AndSmall {
|
||||
7: AndSmall {
|
||||
dest: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
lhs: StatePartIndex<SmallSlots>(2), // (0x1 1) SlotDebugData { name: "", ty: Bool },
|
||||
rhs: StatePartIndex<SmallSlots>(0), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
8: Const {
|
||||
dest: StatePartIndex<BigSlots>(6), // (0x0) SlotDebugData { name: "", ty: Bool },
|
||||
value: 0x0,
|
||||
},
|
||||
// at: module-XXXXXXXXXX.rs:5:1
|
||||
9: BranchIfSmallZero {
|
||||
target: 14,
|
||||
value: StatePartIndex<SmallSlots>(1), // (0x0 0) SlotDebugData { name: "", ty: Bool },
|
||||
|
|
@ -337,6 +337,7 @@ Simulation {
|
|||
}.q,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [],
|
||||
trace_decls: TraceModule {
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ Simulation {
|
|||
}.outputs[2],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -234,6 +235,7 @@ Simulation {
|
|||
}[2],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -433,7 +435,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::clocks[0]",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -482,7 +484,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_fork_join: sim_fork_join).sim_fork_join::clocks[0]",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -164,6 +164,7 @@ Simulation {
|
|||
}.outputs[2],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -234,6 +235,7 @@ Simulation {
|
|||
}[2],
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -433,7 +435,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_fork_join_scope: sim_fork_join_scope).sim_fork_join_scope::clocks[0]",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -482,7 +484,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_fork_join_scope: sim_fork_join_scope).sim_fork_join_scope::clocks[0]",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -557,6 +557,7 @@ Simulation {
|
|||
}.out3,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -635,6 +636,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -794,6 +796,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -1559,7 +1562,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_only_connects.helper1: sim_only_connects_helper).sim_only_connects_helper::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -1609,7 +1612,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_only_connects.helper2: sim_only_connects_helper).sim_only_connects_helper::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -1658,7 +1661,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_only_connects.helper1: sim_only_connects_helper).sim_only_connects_helper::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -1707,7 +1710,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_only_connects.helper2: sim_only_connects_helper).sim_only_connects_helper::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
9724
crates/fayalite/tests/sim/expected/sim_read_past.txt
Normal file
9724
crates/fayalite/tests/sim/expected/sim_read_past.txt
Normal file
File diff suppressed because it is too large
Load diff
1908
crates/fayalite/tests/sim/expected/sim_read_past.vcd
Normal file
1908
crates/fayalite/tests/sim/expected/sim_read_past.vcd
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -121,6 +121,7 @@ Simulation {
|
|||
}.out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -187,6 +188,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -361,7 +363,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst",
|
||||
ty: AsyncReset,
|
||||
},
|
||||
],
|
||||
|
|
@ -411,7 +413,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -460,7 +462,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst",
|
||||
ty: AsyncReset,
|
||||
},
|
||||
],
|
||||
|
|
@ -509,7 +511,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ Simulation {
|
|||
}.out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -187,6 +188,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -361,7 +363,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst",
|
||||
ty: AsyncReset,
|
||||
},
|
||||
],
|
||||
|
|
@ -411,7 +413,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -460,7 +462,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.rst",
|
||||
ty: AsyncReset,
|
||||
},
|
||||
],
|
||||
|
|
@ -509,7 +511,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ Simulation {
|
|||
}.out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -187,6 +188,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -361,7 +363,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -411,7 +413,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -460,7 +462,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ Simulation {
|
|||
}.out,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
|
|
@ -187,6 +188,7 @@ Simulation {
|
|||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
clocks_for_past: {},
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
|
|
@ -361,7 +363,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -411,7 +413,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
@ -460,7 +462,7 @@ Simulation {
|
|||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "",
|
||||
name: "InstantiatedModule(sim_resettable_counter: sim_resettable_counter).sim_resettable_counter::cd.clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
|
|
|
|||
|
|
@ -162,6 +162,7 @@
|
|||
"$kind": "Struct",
|
||||
"verilog_name": "Visible",
|
||||
"parameters": "Visible",
|
||||
"clocks_for_past": "Visible",
|
||||
"simulation": "Visible"
|
||||
}
|
||||
},
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue