sim: add WIP memory test
This commit is contained in:
parent
8616ee4737
commit
393f78a14d
File diff suppressed because it is too large
Load diff
|
@ -990,6 +990,7 @@ macro_rules! make_state_part_kinds {
|
|||
pub(crate) struct State {
|
||||
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
||||
pub(crate) pc: usize,
|
||||
pub(crate) memory_write_log: Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
||||
$(pub(crate) $state_field: StatePart<$StateKind>,)*
|
||||
$(pub(crate) $type_field: StatePart<$TypeKind>,)*
|
||||
}
|
||||
|
@ -999,6 +1000,7 @@ macro_rules! make_state_part_kinds {
|
|||
Self {
|
||||
insns,
|
||||
pc: 0,
|
||||
memory_write_log: Vec::with_capacity(32),
|
||||
$($state_field: StatePart::new(&insns.state_layout.$state_field.layout_data),)*
|
||||
$($type_field: StatePart::new(&insns.state_layout.ty.$type_field.layout_data),)*
|
||||
}
|
||||
|
@ -1009,6 +1011,7 @@ macro_rules! make_state_part_kinds {
|
|||
insns: &self.insns.insns,
|
||||
pc: self.pc,
|
||||
orig_pc: &mut self.pc,
|
||||
memory_write_log: &mut self.memory_write_log,
|
||||
$($state_field: self.$state_field.borrow(),)*
|
||||
$($type_field: self.$type_field.borrow(),)*
|
||||
}
|
||||
|
@ -1021,6 +1024,7 @@ macro_rules! make_state_part_kinds {
|
|||
pub(crate) insns: &'a [Insn],
|
||||
pub(crate) orig_pc: &'a mut usize,
|
||||
pub(crate) pc: usize,
|
||||
pub(crate) memory_write_log: &'a mut Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
||||
$(pub(crate) $state_field: BorrowedStatePart<'a, $StateKind>,)*
|
||||
$(pub(crate) $type_field: BorrowedStatePart<'a, $TypeKind>,)*
|
||||
}
|
||||
|
@ -2146,6 +2150,7 @@ impl State {
|
|||
let Self {
|
||||
insns: _,
|
||||
pc,
|
||||
memory_write_log: _,
|
||||
memories: _,
|
||||
small_slots: _,
|
||||
big_slots: _,
|
||||
|
@ -2172,6 +2177,18 @@ impl BorrowedState<'_> {
|
|||
}
|
||||
Some(retval)
|
||||
}
|
||||
fn log_memory_write(&mut self, memory: StatePartIndex<StatePartKindMemories>, addr: SmallUInt) {
|
||||
let Ok(addr) = usize::try_from(addr) else {
|
||||
return;
|
||||
};
|
||||
if addr < self.memories.value.len() {
|
||||
let log_entry = (memory, addr);
|
||||
if self.memory_write_log.last().copied() == Some(log_entry) {
|
||||
return;
|
||||
}
|
||||
self.memory_write_log.push(log_entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TypeIndexRange {
|
||||
|
@ -2898,6 +2915,7 @@ impl_insns! {
|
|||
} => {
|
||||
let addr = state.small_slots[addr];
|
||||
memory_write_big::<UInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
||||
state.log_memory_write(memory, addr);
|
||||
next!();
|
||||
}
|
||||
MemoryWriteSInt {
|
||||
|
@ -2916,6 +2934,7 @@ impl_insns! {
|
|||
} => {
|
||||
let addr = state.small_slots[addr];
|
||||
memory_write_big::<SInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
||||
state.log_memory_write(memory, addr);
|
||||
next!();
|
||||
}
|
||||
Return => {
|
||||
|
|
|
@ -9,13 +9,14 @@ use crate::{
|
|||
time::{SimDuration, SimInstant},
|
||||
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
||||
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
||||
TraceMemPort, TraceModule, TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId,
|
||||
TraceScope, TraceSyncReset, TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
||||
TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule,
|
||||
TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSyncReset,
|
||||
TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
||||
},
|
||||
};
|
||||
use bitvec::slice::BitSlice;
|
||||
use bitvec::{order::Lsb0, slice::BitSlice};
|
||||
use std::{
|
||||
fmt::{self, Display},
|
||||
fmt,
|
||||
io::{self, Write},
|
||||
mem,
|
||||
};
|
||||
|
@ -112,20 +113,20 @@ macro_rules! trait_arg {
|
|||
(
|
||||
trait $Arg:ident {
|
||||
$(
|
||||
fn $fn:ident(self) -> $ty:ty;
|
||||
fn $fn:ident(&mut self) -> $ty:ty;
|
||||
)*
|
||||
}
|
||||
) => {
|
||||
trait $Arg: Sized {
|
||||
$(fn $fn(self) -> $ty {
|
||||
$(fn $fn(&mut self) -> $ty {
|
||||
unreachable!()
|
||||
})*
|
||||
}
|
||||
|
||||
$(
|
||||
impl $Arg for $ty {
|
||||
fn $fn(self) -> $ty {
|
||||
self
|
||||
fn $fn(&mut self) -> $ty {
|
||||
self.reborrow()
|
||||
}
|
||||
}
|
||||
)*
|
||||
|
@ -134,21 +135,52 @@ macro_rules! trait_arg {
|
|||
|
||||
trait_arg! {
|
||||
trait Arg {
|
||||
fn module(self) -> ArgModule;
|
||||
fn module_body(self) -> ArgModuleBody;
|
||||
fn in_type(self) -> ArgInType;
|
||||
fn module(&mut self) -> ArgModule<'_>;
|
||||
fn module_body(&mut self) -> ArgModuleBody<'_>;
|
||||
fn in_type(&mut self) -> ArgInType<'_>;
|
||||
}
|
||||
}
|
||||
|
||||
struct ArgModule {}
|
||||
struct ArgModule<'a> {
|
||||
properties: &'a mut VcdWriterProperties,
|
||||
}
|
||||
|
||||
struct ArgModuleBody {}
|
||||
impl<'a> ArgModule<'a> {
|
||||
fn reborrow(&mut self) -> ArgModule<'_> {
|
||||
ArgModule {
|
||||
properties: self.properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct ArgInType {
|
||||
struct ArgModuleBody<'a> {
|
||||
properties: &'a mut VcdWriterProperties,
|
||||
}
|
||||
|
||||
impl<'a> ArgModuleBody<'a> {
|
||||
fn reborrow(&mut self) -> ArgModuleBody<'_> {
|
||||
ArgModuleBody {
|
||||
properties: self.properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ArgInType<'a> {
|
||||
source_var_type: &'static str,
|
||||
sink_var_type: &'static str,
|
||||
duplex_var_type: &'static str,
|
||||
properties: &'a mut VcdWriterProperties,
|
||||
}
|
||||
|
||||
impl<'a> ArgInType<'a> {
|
||||
fn reborrow(&mut self) -> ArgInType<'_> {
|
||||
ArgInType {
|
||||
source_var_type: self.source_var_type,
|
||||
sink_var_type: self.sink_var_type,
|
||||
duplex_var_type: self.duplex_var_type,
|
||||
properties: self.properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait WriteTrace: Copy {
|
||||
|
@ -179,11 +211,10 @@ impl WriteTrace for TraceScalar {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_scalar_id<W: io::Write>(writer: &mut W, id: TraceScalarId) -> io::Result<()> {
|
||||
fn write_vcd_id<W: io::Write>(writer: &mut W, mut id: usize) -> io::Result<()> {
|
||||
let min_char = b'!';
|
||||
let max_char = b'~';
|
||||
let base = (max_char - min_char + 1) as usize;
|
||||
let mut id = id.as_usize();
|
||||
loop {
|
||||
let digit = (id % base) as u8 + min_char;
|
||||
id /= base;
|
||||
|
@ -195,7 +226,7 @@ fn write_scalar_id<W: io::Write>(writer: &mut W, id: TraceScalarId) -> io::Resul
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn write_escaped<W: io::Write>(writer: &mut W, value: impl Display) -> io::Result<()> {
|
||||
fn write_escaped<W: io::Write>(writer: &mut W, value: impl fmt::Display) -> io::Result<()> {
|
||||
// escaping rules from function GTKWave uses to decode VCD strings:
|
||||
// https://github.com/gtkwave/gtkwave/blob/491f24d7e8619cfc1fcc65704ee5c967d1083c18/lib/libfst/fstapi.c#L7090
|
||||
struct Wrapper<W>(W);
|
||||
|
@ -247,14 +278,47 @@ fn is_unescaped_verilog_identifier(ident: &str) -> bool {
|
|||
}
|
||||
|
||||
fn write_vcd_var<W: io::Write>(
|
||||
properties: &mut VcdWriterProperties,
|
||||
memory_element_part_body: MemoryElementPartBody,
|
||||
writer: &mut W,
|
||||
var_type: &str,
|
||||
size: usize,
|
||||
id: TraceScalarId,
|
||||
location: TraceLocation,
|
||||
name: &str,
|
||||
) -> io::Result<()> {
|
||||
let id = match location {
|
||||
TraceLocation::Scalar(id) => id.as_usize(),
|
||||
TraceLocation::Memory(TraceMemoryLocation {
|
||||
id,
|
||||
depth,
|
||||
stride: _,
|
||||
start,
|
||||
len,
|
||||
}) => {
|
||||
let MemoryProperties {
|
||||
element_parts,
|
||||
element_part_index,
|
||||
element_index,
|
||||
} = &mut properties.memory_properties[id.as_usize()];
|
||||
let first_id;
|
||||
if let Some(element_part) = element_parts.get(*element_part_index) {
|
||||
first_id = element_part.first_id;
|
||||
} else {
|
||||
first_id = properties.next_scalar_id;
|
||||
properties.next_scalar_id += depth;
|
||||
element_parts.push(MemoryElementPart {
|
||||
first_id,
|
||||
start,
|
||||
len,
|
||||
body: memory_element_part_body,
|
||||
});
|
||||
}
|
||||
*element_part_index += 1;
|
||||
first_id + *element_index
|
||||
}
|
||||
};
|
||||
write!(writer, "$var {var_type} {size} ")?;
|
||||
write_scalar_id(writer, id)?;
|
||||
write_vcd_id(writer, id)?;
|
||||
writer.write_all(b" ")?;
|
||||
if !is_unescaped_verilog_identifier(name) {
|
||||
writer.write_all(b"\\")?;
|
||||
|
@ -264,31 +328,49 @@ fn write_vcd_var<W: io::Write>(
|
|||
}
|
||||
|
||||
impl WriteTrace for TraceUInt {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgInType {
|
||||
source_var_type,
|
||||
sink_var_type,
|
||||
duplex_var_type,
|
||||
properties,
|
||||
} = arg.in_type();
|
||||
let Self { id, name, ty, flow } = self;
|
||||
let var_type = match flow {
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
ty,
|
||||
flow,
|
||||
} = self;
|
||||
let mut var_type = match flow {
|
||||
Flow::Source => source_var_type,
|
||||
Flow::Sink => sink_var_type,
|
||||
Flow::Duplex => duplex_var_type,
|
||||
};
|
||||
if ty.width() == 0 {
|
||||
write_vcd_var(writer, "string", ty.width(), id, &name)
|
||||
} else {
|
||||
write_vcd_var(writer, var_type, ty.width(), id, &name)
|
||||
var_type = "string";
|
||||
}
|
||||
write_vcd_var(
|
||||
properties,
|
||||
MemoryElementPartBody::Scalar,
|
||||
writer,
|
||||
var_type,
|
||||
ty.width(),
|
||||
location,
|
||||
&name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceSInt {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, ty, flow } = self;
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
ty,
|
||||
flow,
|
||||
} = self;
|
||||
TraceUInt {
|
||||
id,
|
||||
location,
|
||||
name,
|
||||
ty: UInt::new_dyn(ty.width()),
|
||||
flow,
|
||||
|
@ -299,9 +381,13 @@ impl WriteTrace for TraceSInt {
|
|||
|
||||
impl WriteTrace for TraceBool {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, flow } = self;
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
} = self;
|
||||
TraceUInt {
|
||||
id,
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
ty: UInt::new_dyn(1),
|
||||
|
@ -312,46 +398,93 @@ impl WriteTrace for TraceBool {
|
|||
|
||||
impl WriteTrace for TraceFieldlessEnum {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, ty, flow } = self;
|
||||
TraceEnumDiscriminant { id, name, ty, flow }.write_trace(writer, arg)
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
ty,
|
||||
flow,
|
||||
} = self;
|
||||
TraceEnumDiscriminant {
|
||||
location,
|
||||
name,
|
||||
ty,
|
||||
flow,
|
||||
}
|
||||
.write_trace(writer, arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceEnumDiscriminant {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgInType {
|
||||
source_var_type: _,
|
||||
sink_var_type: _,
|
||||
duplex_var_type: _,
|
||||
properties,
|
||||
} = arg.in_type();
|
||||
let Self {
|
||||
id,
|
||||
location,
|
||||
name,
|
||||
ty: _,
|
||||
ty,
|
||||
flow: _,
|
||||
} = self;
|
||||
write_vcd_var(writer, "string", 1, id, &name)
|
||||
write_vcd_var(
|
||||
properties,
|
||||
MemoryElementPartBody::EnumDiscriminant { ty },
|
||||
writer,
|
||||
"string",
|
||||
1,
|
||||
location,
|
||||
&name,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceClock {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, flow } = self;
|
||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
} = self;
|
||||
TraceBool {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
}
|
||||
.write_trace(writer, arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceSyncReset {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, flow } = self;
|
||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
} = self;
|
||||
TraceBool {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
}
|
||||
.write_trace(writer, arg)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceAsyncReset {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let Self { id, name, flow } = self;
|
||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
||||
let Self {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
} = self;
|
||||
TraceBool {
|
||||
location,
|
||||
name,
|
||||
flow,
|
||||
}
|
||||
.write_trace(writer, arg)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,6 +493,7 @@ impl WriteTrace for TraceScope {
|
|||
match self {
|
||||
Self::Module(v) => v.write_trace(writer, arg),
|
||||
Self::Instance(v) => v.write_trace(writer, arg),
|
||||
Self::Mem(v) => v.write_trace(writer, arg),
|
||||
Self::MemPort(v) => v.write_trace(writer, arg),
|
||||
Self::Wire(v) => v.write_trace(writer, arg),
|
||||
Self::Reg(v) => v.write_trace(writer, arg),
|
||||
|
@ -372,12 +506,12 @@ impl WriteTrace for TraceScope {
|
|||
}
|
||||
|
||||
impl WriteTrace for TraceModule {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let ArgModule {} = arg.module();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModule { properties } = arg.module();
|
||||
let Self { name, children } = self;
|
||||
write_vcd_scope(writer, "module", &name, |writer| {
|
||||
for child in children {
|
||||
child.write_trace(writer, ArgModuleBody {})?;
|
||||
child.write_trace(writer, ArgModuleBody { properties })?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -385,8 +519,8 @@ impl WriteTrace for TraceModule {
|
|||
}
|
||||
|
||||
impl WriteTrace for TraceInstance {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody {} = arg.module_body();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
name: _,
|
||||
instance_io,
|
||||
|
@ -399,21 +533,74 @@ impl WriteTrace for TraceInstance {
|
|||
source_var_type: "wire",
|
||||
sink_var_type: "wire",
|
||||
duplex_var_type: "wire",
|
||||
properties,
|
||||
},
|
||||
)?;
|
||||
module.write_trace(writer, ArgModule {})
|
||||
module.write_trace(writer, ArgModule { properties })
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceMem {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
id,
|
||||
name,
|
||||
stride: _,
|
||||
element_type,
|
||||
ports,
|
||||
array_type,
|
||||
} = self;
|
||||
write_vcd_scope(writer, "struct", &*name, |writer| {
|
||||
write_vcd_scope(writer, "struct", "contents", |writer| {
|
||||
for element_index in 0..array_type.len() {
|
||||
write_vcd_scope(writer, "struct", &format!("[{element_index}]"), |writer| {
|
||||
properties.memory_properties[id.as_usize()].element_index = element_index;
|
||||
properties.memory_properties[id.as_usize()].element_part_index = 0;
|
||||
element_type.write_trace(
|
||||
writer,
|
||||
ArgInType {
|
||||
source_var_type: "reg",
|
||||
sink_var_type: "reg",
|
||||
duplex_var_type: "reg",
|
||||
properties,
|
||||
},
|
||||
)
|
||||
})?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
for port in ports {
|
||||
port.write_trace(writer, ArgModuleBody { properties })?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceMemPort {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
todo!()
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
name: _,
|
||||
bundle,
|
||||
ty: _,
|
||||
} = self;
|
||||
bundle.write_trace(
|
||||
writer,
|
||||
ArgInType {
|
||||
source_var_type: "wire",
|
||||
sink_var_type: "wire",
|
||||
duplex_var_type: "wire",
|
||||
properties,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceWire {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody {} = arg.module_body();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
name: _,
|
||||
child,
|
||||
|
@ -425,14 +612,15 @@ impl WriteTrace for TraceWire {
|
|||
source_var_type: "wire",
|
||||
sink_var_type: "wire",
|
||||
duplex_var_type: "wire",
|
||||
properties,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceReg {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody {} = arg.module_body();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
name: _,
|
||||
child,
|
||||
|
@ -444,14 +632,15 @@ impl WriteTrace for TraceReg {
|
|||
source_var_type: "reg",
|
||||
sink_var_type: "reg",
|
||||
duplex_var_type: "reg",
|
||||
properties,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceModuleIO {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody {} = arg.module_body();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let ArgModuleBody { properties } = arg.module_body();
|
||||
let Self {
|
||||
name: _,
|
||||
child,
|
||||
|
@ -464,14 +653,15 @@ impl WriteTrace for TraceModuleIO {
|
|||
source_var_type: "wire",
|
||||
sink_var_type: "wire",
|
||||
duplex_var_type: "wire",
|
||||
properties,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl WriteTrace for TraceBundle {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let arg = arg.in_type();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let mut arg = arg.in_type();
|
||||
let Self {
|
||||
name,
|
||||
fields,
|
||||
|
@ -480,7 +670,7 @@ impl WriteTrace for TraceBundle {
|
|||
} = self;
|
||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||
for field in fields {
|
||||
field.write_trace(writer, arg)?;
|
||||
field.write_trace(writer, arg.reborrow())?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -488,8 +678,8 @@ impl WriteTrace for TraceBundle {
|
|||
}
|
||||
|
||||
impl WriteTrace for TraceArray {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let arg = arg.in_type();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let mut arg = arg.in_type();
|
||||
let Self {
|
||||
name,
|
||||
elements,
|
||||
|
@ -498,7 +688,7 @@ impl WriteTrace for TraceArray {
|
|||
} = self;
|
||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||
for element in elements {
|
||||
element.write_trace(writer, arg)?;
|
||||
element.write_trace(writer, arg.reborrow())?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -506,8 +696,8 @@ impl WriteTrace for TraceArray {
|
|||
}
|
||||
|
||||
impl WriteTrace for TraceEnumWithFields {
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, arg: A) -> io::Result<()> {
|
||||
let arg = arg.in_type();
|
||||
fn write_trace<W: io::Write, A: Arg>(self, writer: &mut W, mut arg: A) -> io::Result<()> {
|
||||
let mut arg = arg.in_type();
|
||||
let Self {
|
||||
name,
|
||||
discriminant,
|
||||
|
@ -516,9 +706,9 @@ impl WriteTrace for TraceEnumWithFields {
|
|||
flow: _,
|
||||
} = self;
|
||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||
discriminant.write_trace(writer, arg)?;
|
||||
discriminant.write_trace(writer, arg.reborrow())?;
|
||||
for field in non_empty_fields {
|
||||
field.write_trace(writer, arg)?;
|
||||
field.write_trace(writer, arg.reborrow())?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
|
@ -529,76 +719,184 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
|
|||
type Error = io::Error;
|
||||
type TraceWriter = VcdWriter<W>;
|
||||
|
||||
fn write_decls(self, module: TraceModule) -> Result<Self::TraceWriter, Self::Error> {
|
||||
fn write_decls(
|
||||
self,
|
||||
module: TraceModule,
|
||||
trace_scalar_id_count: usize,
|
||||
trace_memory_id_count: usize,
|
||||
) -> Result<Self::TraceWriter, Self::Error> {
|
||||
let Self {
|
||||
mut writer,
|
||||
timescale,
|
||||
} = self;
|
||||
writeln!(writer, "$timescale {} $end", vcd_timescale(timescale))?;
|
||||
module.write_trace(&mut writer, ArgModule {})?;
|
||||
let mut properties = VcdWriterProperties {
|
||||
next_scalar_id: trace_scalar_id_count,
|
||||
memory_properties: (0..trace_memory_id_count)
|
||||
.map(|_| MemoryProperties {
|
||||
element_parts: Vec::with_capacity(8),
|
||||
element_part_index: 0,
|
||||
element_index: 0,
|
||||
})
|
||||
.collect(),
|
||||
};
|
||||
module.write_trace(
|
||||
&mut writer,
|
||||
ArgModule {
|
||||
properties: &mut properties,
|
||||
},
|
||||
)?;
|
||||
writeln!(writer, "$enddefinitions $end")?;
|
||||
writeln!(writer, "$dumpvars")?;
|
||||
Ok(VcdWriter {
|
||||
writer,
|
||||
finished_init: false,
|
||||
timescale,
|
||||
properties,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
enum MemoryElementPartBody {
|
||||
Scalar,
|
||||
EnumDiscriminant { ty: Enum },
|
||||
}
|
||||
|
||||
struct MemoryElementPart {
|
||||
first_id: usize,
|
||||
start: usize,
|
||||
len: usize,
|
||||
body: MemoryElementPartBody,
|
||||
}
|
||||
|
||||
struct MemoryProperties {
|
||||
element_parts: Vec<MemoryElementPart>,
|
||||
element_part_index: usize,
|
||||
element_index: usize,
|
||||
}
|
||||
|
||||
struct VcdWriterProperties {
|
||||
next_scalar_id: usize,
|
||||
memory_properties: Box<[MemoryProperties]>,
|
||||
}
|
||||
|
||||
pub struct VcdWriter<W: io::Write + 'static> {
|
||||
writer: W,
|
||||
finished_init: bool,
|
||||
timescale: SimDuration,
|
||||
properties: VcdWriterProperties,
|
||||
}
|
||||
|
||||
impl<W: io::Write + 'static> VcdWriter<W> {
|
||||
pub fn timescale(&self) -> SimDuration {
|
||||
self.timescale
|
||||
}
|
||||
fn write_string_value_change(
|
||||
&mut self,
|
||||
value: impl Display,
|
||||
id: TraceScalarId,
|
||||
) -> io::Result<()> {
|
||||
self.writer.write_all(b"s")?;
|
||||
write_escaped(&mut self.writer, value)?;
|
||||
self.writer.write_all(b" ")?;
|
||||
write_scalar_id(&mut self.writer, id)?;
|
||||
self.writer.write_all(b"\n")
|
||||
}
|
||||
|
||||
fn write_string_value_change(
|
||||
writer: &mut impl io::Write,
|
||||
value: impl fmt::Display,
|
||||
id: usize,
|
||||
) -> io::Result<()> {
|
||||
writer.write_all(b"s")?;
|
||||
write_escaped(writer, value)?;
|
||||
writer.write_all(b" ")?;
|
||||
write_vcd_id(writer, id)?;
|
||||
writer.write_all(b"\n")
|
||||
}
|
||||
|
||||
fn write_bits_value_change(
|
||||
writer: &mut impl io::Write,
|
||||
value: &BitSlice,
|
||||
id: usize,
|
||||
) -> io::Result<()> {
|
||||
match value.len() {
|
||||
0 => writer.write_all(b"s0 ")?,
|
||||
1 => writer.write_all(if value[0] { b"1" } else { b"0" })?,
|
||||
_ => {
|
||||
writer.write_all(b"b")?;
|
||||
let mut any_ones = false;
|
||||
for bit in value.iter().rev() {
|
||||
if *bit {
|
||||
any_ones = true;
|
||||
writer.write_all(b"1")?;
|
||||
} else if any_ones {
|
||||
writer.write_all(b"0")?;
|
||||
}
|
||||
}
|
||||
if !any_ones {
|
||||
writer.write_all(b"0")?;
|
||||
}
|
||||
writer.write_all(b" ")?;
|
||||
}
|
||||
}
|
||||
write_vcd_id(writer, id)?;
|
||||
writer.write_all(b"\n")
|
||||
}
|
||||
|
||||
fn write_enum_discriminant_value_change(
|
||||
writer: &mut impl io::Write,
|
||||
variant_index: usize,
|
||||
ty: Enum,
|
||||
id: usize,
|
||||
) -> io::Result<()> {
|
||||
write_string_value_change(
|
||||
writer,
|
||||
format_args!(
|
||||
"{} ({variant_index})",
|
||||
ty.variants()
|
||||
.get(variant_index)
|
||||
.map(|v| &*v.name)
|
||||
.unwrap_or("<invalid>"),
|
||||
),
|
||||
id,
|
||||
)
|
||||
}
|
||||
|
||||
impl<W: io::Write> TraceWriter for VcdWriter<W> {
|
||||
type Error = io::Error;
|
||||
|
||||
fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
||||
match value.len() {
|
||||
0 => self.writer.write_all(b"s0 ")?,
|
||||
1 => self.writer.write_all(if value[0] { b"1" } else { b"0" })?,
|
||||
_ => {
|
||||
self.writer.write_all(b"b")?;
|
||||
let mut any_ones = false;
|
||||
for bit in value.iter().rev() {
|
||||
if *bit {
|
||||
any_ones = true;
|
||||
self.writer.write_all(b"1")?;
|
||||
} else if any_ones {
|
||||
self.writer.write_all(b"0")?;
|
||||
}
|
||||
fn set_memory_element(
|
||||
&mut self,
|
||||
memory: TraceMemoryId,
|
||||
element_index: usize,
|
||||
element_data: &BitSlice,
|
||||
) -> Result<(), Self::Error> {
|
||||
for &MemoryElementPart {
|
||||
first_id,
|
||||
start,
|
||||
len,
|
||||
ref body,
|
||||
} in &self.properties.memory_properties[memory.as_usize()].element_parts
|
||||
{
|
||||
match body {
|
||||
MemoryElementPartBody::Scalar => write_bits_value_change(
|
||||
&mut self.writer,
|
||||
&element_data[start..start + len],
|
||||
first_id + element_index,
|
||||
)?,
|
||||
MemoryElementPartBody::EnumDiscriminant { ty } => {
|
||||
let mut variant_index = 0;
|
||||
BitSlice::<usize, Lsb0>::from_element_mut(&mut variant_index)[..len]
|
||||
.clone_from_bitslice(&element_data[start..start + len]);
|
||||
write_enum_discriminant_value_change(
|
||||
&mut self.writer,
|
||||
variant_index,
|
||||
*ty,
|
||||
first_id + element_index,
|
||||
)?
|
||||
}
|
||||
if !any_ones {
|
||||
self.writer.write_all(b"0")?;
|
||||
}
|
||||
self.writer.write_all(b" ")?;
|
||||
}
|
||||
}
|
||||
write_scalar_id(&mut self.writer, id)?;
|
||||
self.writer.write_all(b"\n")
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
||||
write_bits_value_change(&mut self.writer, value, id.as_usize())
|
||||
}
|
||||
|
||||
fn set_signal_sint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
||||
self.set_signal_uint(id, value)
|
||||
write_bits_value_change(&mut self.writer, value, id.as_usize())
|
||||
}
|
||||
|
||||
fn finish_init(&mut self) -> Result<(), Self::Error> {
|
||||
|
@ -630,16 +928,7 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
|
|||
variant_index: usize,
|
||||
ty: Enum,
|
||||
) -> Result<(), Self::Error> {
|
||||
self.write_string_value_change(
|
||||
format_args!(
|
||||
"{} ({variant_index})",
|
||||
ty.variants()
|
||||
.get(variant_index)
|
||||
.map(|v| &*v.name)
|
||||
.unwrap_or("<invalid>"),
|
||||
),
|
||||
id,
|
||||
)
|
||||
write_enum_discriminant_value_change(&mut self.writer, variant_index, ty, id.as_usize())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -649,6 +938,7 @@ impl<W: io::Write> fmt::Debug for VcdWriter<W> {
|
|||
writer: _,
|
||||
finished_init,
|
||||
timescale,
|
||||
properties: _,
|
||||
} = self;
|
||||
f.debug_struct("VcdWriter")
|
||||
.field("finished_init", finished_init)
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||
// See Notices.txt for copyright information
|
||||
|
||||
use fayalite::{
|
||||
int::UIntValue,
|
||||
prelude::*,
|
||||
|
@ -7,6 +8,7 @@ use fayalite::{
|
|||
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
|
||||
util::RcWriter,
|
||||
};
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
#[hdl_module(outline_generated)]
|
||||
pub fn connect_const() {
|
||||
|
@ -492,4 +494,113 @@ fn test_enums() {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: add tests for memories
|
||||
#[hdl_module(outline_generated)]
|
||||
pub fn memories() {
|
||||
#[hdl]
|
||||
let r: fayalite::memory::ReadStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
|
||||
#[hdl]
|
||||
let w: fayalite::memory::WriteStruct<(UInt<8>, SInt<8>), ConstUsize<4>> = m.input();
|
||||
#[hdl]
|
||||
let mut mem = memory_with_init([(0x01u8, 0x23i8); 16]);
|
||||
mem.read_latency(0);
|
||||
mem.write_latency(NonZeroUsize::new(1).unwrap());
|
||||
mem.read_under_write(ReadUnderWrite::Old);
|
||||
connect_any(mem.new_read_port(), r);
|
||||
connect_any(mem.new_write_port(), w);
|
||||
}
|
||||
|
||||
#[cfg(todo)] // TODO: finish
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn test_memories() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let mut sim = Simulation::new(memories());
|
||||
let mut writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
sim.write_clock(sim.io().r.clk, false);
|
||||
sim.write_clock(sim.io().w.clk, false);
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
struct IO {
|
||||
r_addr: u8,
|
||||
r_en: bool,
|
||||
r_data: (u8, i8),
|
||||
w_addr: u8,
|
||||
w_en: bool,
|
||||
w_data: (u8, i8),
|
||||
w_mask: (bool, bool),
|
||||
}
|
||||
let io_cycles = [IO {
|
||||
r_addr: 0,
|
||||
r_en: false,
|
||||
r_data: (0, 0),
|
||||
w_addr: 0,
|
||||
w_en: false,
|
||||
w_data: (0, 0),
|
||||
w_mask: (false, false),
|
||||
}];
|
||||
for (
|
||||
cycle,
|
||||
expected @ IO {
|
||||
r_addr,
|
||||
r_en,
|
||||
r_data: _,
|
||||
w_addr,
|
||||
w_en,
|
||||
w_data,
|
||||
w_mask,
|
||||
},
|
||||
) in io_cycles.into_iter().enumerate()
|
||||
{
|
||||
sim.write_bool_or_int(sim.io().r.addr, r_addr.cast_to_static());
|
||||
sim.write_bool(sim.io().r.en, r_en);
|
||||
sim.write_bool_or_int(sim.io().w.addr, w_addr.cast_to_static());
|
||||
sim.write_bool(sim.io().w.en, w_en);
|
||||
sim.write_bool_or_int(sim.io().w.data.0, w_data.0);
|
||||
sim.write_bool_or_int(sim.io().w.data.1, w_data.1);
|
||||
sim.write_bool(sim.io().w.mask.0, w_mask.0);
|
||||
sim.write_bool(sim.io().w.mask.1, w_mask.1);
|
||||
let io = IO {
|
||||
r_addr,
|
||||
r_en,
|
||||
r_data: (
|
||||
sim.read_bool_or_int(sim.io().r.data.0)
|
||||
.to_bigint()
|
||||
.try_into()
|
||||
.expect("known to be in range"),
|
||||
sim.read_bool_or_int(sim.io().r.data.1)
|
||||
.to_bigint()
|
||||
.try_into()
|
||||
.expect("known to be in range"),
|
||||
),
|
||||
w_addr,
|
||||
w_en,
|
||||
w_data,
|
||||
w_mask,
|
||||
};
|
||||
assert_eq!(
|
||||
expected,
|
||||
io,
|
||||
"cycle: {cycle}\nvcd:\n{}",
|
||||
String::from_utf8(writer.take()).unwrap(),
|
||||
);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
sim.write_clock(sim.io().r.clk, true);
|
||||
sim.write_clock(sim.io().w.clk, true);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
sim.write_clock(sim.io().r.clk, false);
|
||||
sim.write_clock(sim.io().w.clk, false);
|
||||
}
|
||||
sim.flush_traces().unwrap();
|
||||
let vcd = String::from_utf8(writer.take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
if vcd != include_str!("sim/expected/memories.vcd") {
|
||||
panic!();
|
||||
}
|
||||
let sim_debug = format!("{sim:#?}");
|
||||
println!("#######\n{sim_debug}\n#######");
|
||||
if sim_debug != include_str!("sim/expected/memories.txt") {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: add more tests for memories
|
||||
|
|
|
@ -47,6 +47,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 2,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -112,7 +113,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "o",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "o",
|
||||
ty: UInt<8>,
|
||||
flow: Sink,
|
||||
|
@ -133,6 +134,7 @@ Simulation {
|
|||
last_state: 0x05,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [],
|
||||
instant: 0 s,
|
||||
clocks_triggered: [],
|
||||
|
|
|
@ -73,6 +73,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 5,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -175,7 +176,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "reset_out",
|
||||
child: TraceAsyncReset {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "reset_out",
|
||||
flow: Sink,
|
||||
},
|
||||
|
@ -185,7 +186,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "bit_out",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "bit_out",
|
||||
flow: Sink,
|
||||
},
|
||||
|
@ -212,6 +213,7 @@ Simulation {
|
|||
last_state: 0x1,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
|
@ -168,6 +168,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 18,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -417,12 +418,12 @@ Simulation {
|
|||
name: "cd",
|
||||
fields: [
|
||||
TraceClock {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "clk",
|
||||
flow: Source,
|
||||
},
|
||||
TraceAsyncReset {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "rst",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -446,7 +447,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "count",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(2),
|
||||
location: TraceScalarId(2),
|
||||
name: "count",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
|
@ -457,7 +458,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "count_reg",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(3),
|
||||
location: TraceScalarId(3),
|
||||
name: "count_reg",
|
||||
ty: UInt<4>,
|
||||
flow: Duplex,
|
||||
|
@ -502,6 +503,7 @@ Simulation {
|
|||
last_state: 0x3,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
|
@ -150,6 +150,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 15,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -398,12 +399,12 @@ Simulation {
|
|||
name: "cd",
|
||||
fields: [
|
||||
TraceClock {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "clk",
|
||||
flow: Source,
|
||||
},
|
||||
TraceSyncReset {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "rst",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -427,7 +428,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "count",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(2),
|
||||
location: TraceScalarId(2),
|
||||
name: "count",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
|
@ -438,7 +439,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "count_reg",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(3),
|
||||
location: TraceScalarId(3),
|
||||
name: "count_reg",
|
||||
ty: UInt<4>,
|
||||
flow: Duplex,
|
||||
|
@ -483,6 +484,7 @@ Simulation {
|
|||
last_state: 0x3,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
|
@ -875,6 +875,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 100,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -1333,12 +1334,12 @@ Simulation {
|
|||
name: "cd",
|
||||
fields: [
|
||||
TraceClock {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "clk",
|
||||
flow: Source,
|
||||
},
|
||||
TraceSyncReset {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "rst",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -1362,7 +1363,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "en",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(2),
|
||||
location: TraceScalarId(2),
|
||||
name: "en",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -1372,7 +1373,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "which_in",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(3),
|
||||
location: TraceScalarId(3),
|
||||
name: "which_in",
|
||||
ty: UInt<2>,
|
||||
flow: Source,
|
||||
|
@ -1383,7 +1384,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "data_in",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(4),
|
||||
location: TraceScalarId(4),
|
||||
name: "data_in",
|
||||
ty: UInt<4>,
|
||||
flow: Source,
|
||||
|
@ -1394,7 +1395,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "which_out",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(5),
|
||||
location: TraceScalarId(5),
|
||||
name: "which_out",
|
||||
ty: UInt<2>,
|
||||
flow: Sink,
|
||||
|
@ -1405,7 +1406,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "data_out",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(6),
|
||||
location: TraceScalarId(6),
|
||||
name: "data_out",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
|
@ -1418,7 +1419,7 @@ Simulation {
|
|||
child: TraceEnumWithFields {
|
||||
name: "the_reg",
|
||||
discriminant: TraceEnumDiscriminant {
|
||||
id: TraceScalarId(7),
|
||||
location: TraceScalarId(7),
|
||||
name: "$tag",
|
||||
ty: Enum {
|
||||
A,
|
||||
|
@ -1432,13 +1433,13 @@ Simulation {
|
|||
name: "B",
|
||||
fields: [
|
||||
TraceUInt {
|
||||
id: TraceScalarId(8),
|
||||
location: TraceScalarId(8),
|
||||
name: "0",
|
||||
ty: UInt<1>,
|
||||
flow: Source,
|
||||
},
|
||||
TraceBool {
|
||||
id: TraceScalarId(9),
|
||||
location: TraceScalarId(9),
|
||||
name: "1",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -1458,13 +1459,13 @@ Simulation {
|
|||
name: "a",
|
||||
elements: [
|
||||
TraceUInt {
|
||||
id: TraceScalarId(10),
|
||||
location: TraceScalarId(10),
|
||||
name: "[0]",
|
||||
ty: UInt<1>,
|
||||
flow: Source,
|
||||
},
|
||||
TraceUInt {
|
||||
id: TraceScalarId(11),
|
||||
location: TraceScalarId(11),
|
||||
name: "[1]",
|
||||
ty: UInt<1>,
|
||||
flow: Source,
|
||||
|
@ -1474,7 +1475,7 @@ Simulation {
|
|||
flow: Source,
|
||||
},
|
||||
TraceSInt {
|
||||
id: TraceScalarId(12),
|
||||
location: TraceScalarId(12),
|
||||
name: "b",
|
||||
ty: SInt<2>,
|
||||
flow: Source,
|
||||
|
@ -1623,6 +1624,7 @@ Simulation {
|
|||
last_state: 0x3,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
|
@ -180,6 +180,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 17,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -531,25 +532,25 @@ Simulation {
|
|||
name: "o",
|
||||
fields: [
|
||||
TraceUInt {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "i",
|
||||
ty: UInt<4>,
|
||||
flow: Source,
|
||||
},
|
||||
TraceSInt {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "o",
|
||||
ty: SInt<2>,
|
||||
flow: Sink,
|
||||
},
|
||||
TraceSInt {
|
||||
id: TraceScalarId(2),
|
||||
location: TraceScalarId(2),
|
||||
name: "i2",
|
||||
ty: SInt<2>,
|
||||
flow: Source,
|
||||
},
|
||||
TraceUInt {
|
||||
id: TraceScalarId(3),
|
||||
location: TraceScalarId(3),
|
||||
name: "o2",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
|
@ -585,25 +586,25 @@ Simulation {
|
|||
name: "child",
|
||||
fields: [
|
||||
TraceUInt {
|
||||
id: TraceScalarId(8),
|
||||
location: TraceScalarId(8),
|
||||
name: "i",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
},
|
||||
TraceSInt {
|
||||
id: TraceScalarId(9),
|
||||
location: TraceScalarId(9),
|
||||
name: "o",
|
||||
ty: SInt<2>,
|
||||
flow: Source,
|
||||
},
|
||||
TraceSInt {
|
||||
id: TraceScalarId(10),
|
||||
location: TraceScalarId(10),
|
||||
name: "i2",
|
||||
ty: SInt<2>,
|
||||
flow: Sink,
|
||||
},
|
||||
TraceUInt {
|
||||
id: TraceScalarId(11),
|
||||
location: TraceScalarId(11),
|
||||
name: "o2",
|
||||
ty: UInt<4>,
|
||||
flow: Source,
|
||||
|
@ -627,7 +628,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "i",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(4),
|
||||
location: TraceScalarId(4),
|
||||
name: "i",
|
||||
ty: UInt<4>,
|
||||
flow: Source,
|
||||
|
@ -638,7 +639,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "o",
|
||||
child: TraceSInt {
|
||||
id: TraceScalarId(5),
|
||||
location: TraceScalarId(5),
|
||||
name: "o",
|
||||
ty: SInt<2>,
|
||||
flow: Sink,
|
||||
|
@ -649,7 +650,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "i2",
|
||||
child: TraceSInt {
|
||||
id: TraceScalarId(6),
|
||||
location: TraceScalarId(6),
|
||||
name: "i2",
|
||||
ty: SInt<2>,
|
||||
flow: Source,
|
||||
|
@ -660,7 +661,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "o2",
|
||||
child: TraceUInt {
|
||||
id: TraceScalarId(7),
|
||||
location: TraceScalarId(7),
|
||||
name: "o2",
|
||||
ty: UInt<4>,
|
||||
flow: Sink,
|
||||
|
@ -793,6 +794,7 @@ Simulation {
|
|||
last_state: 0xe,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
|
@ -227,6 +227,7 @@ Simulation {
|
|||
..
|
||||
},
|
||||
pc: 30,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
|
@ -513,12 +514,12 @@ Simulation {
|
|||
name: "cd",
|
||||
fields: [
|
||||
TraceClock {
|
||||
id: TraceScalarId(0),
|
||||
location: TraceScalarId(0),
|
||||
name: "clk",
|
||||
flow: Source,
|
||||
},
|
||||
TraceSyncReset {
|
||||
id: TraceScalarId(1),
|
||||
location: TraceScalarId(1),
|
||||
name: "rst",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -542,7 +543,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "d",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(2),
|
||||
location: TraceScalarId(2),
|
||||
name: "d",
|
||||
flow: Source,
|
||||
},
|
||||
|
@ -552,7 +553,7 @@ Simulation {
|
|||
TraceModuleIO {
|
||||
name: "q",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(3),
|
||||
location: TraceScalarId(3),
|
||||
name: "q",
|
||||
flow: Sink,
|
||||
},
|
||||
|
@ -562,7 +563,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "reg0",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(4),
|
||||
location: TraceScalarId(4),
|
||||
name: "reg0",
|
||||
flow: Duplex,
|
||||
},
|
||||
|
@ -571,7 +572,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "reg1",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(5),
|
||||
location: TraceScalarId(5),
|
||||
name: "reg1",
|
||||
flow: Duplex,
|
||||
},
|
||||
|
@ -580,7 +581,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "reg2",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(6),
|
||||
location: TraceScalarId(6),
|
||||
name: "reg2",
|
||||
flow: Duplex,
|
||||
},
|
||||
|
@ -589,7 +590,7 @@ Simulation {
|
|||
TraceReg {
|
||||
name: "reg3",
|
||||
child: TraceBool {
|
||||
id: TraceScalarId(7),
|
||||
location: TraceScalarId(7),
|
||||
name: "reg3",
|
||||
flow: Duplex,
|
||||
},
|
||||
|
@ -663,6 +664,7 @@ Simulation {
|
|||
last_state: 0x0,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
|
|
Loading…
Reference in a new issue