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) struct State {
|
||||||
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
pub(crate) insns: Interned<Insns<InsnsBuildingDone>>,
|
||||||
pub(crate) pc: usize,
|
pub(crate) pc: usize,
|
||||||
|
pub(crate) memory_write_log: Vec<(StatePartIndex<StatePartKindMemories>, usize)>,
|
||||||
$(pub(crate) $state_field: StatePart<$StateKind>,)*
|
$(pub(crate) $state_field: StatePart<$StateKind>,)*
|
||||||
$(pub(crate) $type_field: StatePart<$TypeKind>,)*
|
$(pub(crate) $type_field: StatePart<$TypeKind>,)*
|
||||||
}
|
}
|
||||||
|
@ -999,6 +1000,7 @@ macro_rules! make_state_part_kinds {
|
||||||
Self {
|
Self {
|
||||||
insns,
|
insns,
|
||||||
pc: 0,
|
pc: 0,
|
||||||
|
memory_write_log: Vec::with_capacity(32),
|
||||||
$($state_field: StatePart::new(&insns.state_layout.$state_field.layout_data),)*
|
$($state_field: StatePart::new(&insns.state_layout.$state_field.layout_data),)*
|
||||||
$($type_field: StatePart::new(&insns.state_layout.ty.$type_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,
|
insns: &self.insns.insns,
|
||||||
pc: self.pc,
|
pc: self.pc,
|
||||||
orig_pc: &mut self.pc,
|
orig_pc: &mut self.pc,
|
||||||
|
memory_write_log: &mut self.memory_write_log,
|
||||||
$($state_field: self.$state_field.borrow(),)*
|
$($state_field: self.$state_field.borrow(),)*
|
||||||
$($type_field: self.$type_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) insns: &'a [Insn],
|
||||||
pub(crate) orig_pc: &'a mut usize,
|
pub(crate) orig_pc: &'a mut usize,
|
||||||
pub(crate) pc: 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) $state_field: BorrowedStatePart<'a, $StateKind>,)*
|
||||||
$(pub(crate) $type_field: BorrowedStatePart<'a, $TypeKind>,)*
|
$(pub(crate) $type_field: BorrowedStatePart<'a, $TypeKind>,)*
|
||||||
}
|
}
|
||||||
|
@ -2146,6 +2150,7 @@ impl State {
|
||||||
let Self {
|
let Self {
|
||||||
insns: _,
|
insns: _,
|
||||||
pc,
|
pc,
|
||||||
|
memory_write_log: _,
|
||||||
memories: _,
|
memories: _,
|
||||||
small_slots: _,
|
small_slots: _,
|
||||||
big_slots: _,
|
big_slots: _,
|
||||||
|
@ -2172,6 +2177,18 @@ impl BorrowedState<'_> {
|
||||||
}
|
}
|
||||||
Some(retval)
|
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 {
|
impl TypeIndexRange {
|
||||||
|
@ -2898,6 +2915,7 @@ impl_insns! {
|
||||||
} => {
|
} => {
|
||||||
let addr = state.small_slots[addr];
|
let addr = state.small_slots[addr];
|
||||||
memory_write_big::<UInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
memory_write_big::<UInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
||||||
|
state.log_memory_write(memory, addr);
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
MemoryWriteSInt {
|
MemoryWriteSInt {
|
||||||
|
@ -2916,6 +2934,7 @@ impl_insns! {
|
||||||
} => {
|
} => {
|
||||||
let addr = state.small_slots[addr];
|
let addr = state.small_slots[addr];
|
||||||
memory_write_big::<SInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
memory_write_big::<SInt>(&mut state.memories[memory], addr, stride, start, width, &mut state.big_slots[value]);
|
||||||
|
state.log_memory_write(memory, addr);
|
||||||
next!();
|
next!();
|
||||||
}
|
}
|
||||||
Return => {
|
Return => {
|
||||||
|
|
|
@ -9,13 +9,14 @@ use crate::{
|
||||||
time::{SimDuration, SimInstant},
|
time::{SimDuration, SimInstant},
|
||||||
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
TraceArray, TraceAsyncReset, TraceBool, TraceBundle, TraceClock, TraceDecl,
|
||||||
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
TraceEnumDiscriminant, TraceEnumWithFields, TraceFieldlessEnum, TraceInstance,
|
||||||
TraceMemPort, TraceModule, TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId,
|
TraceLocation, TraceMem, TraceMemPort, TraceMemoryId, TraceMemoryLocation, TraceModule,
|
||||||
TraceScope, TraceSyncReset, TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
TraceModuleIO, TraceReg, TraceSInt, TraceScalar, TraceScalarId, TraceScope, TraceSyncReset,
|
||||||
|
TraceUInt, TraceWire, TraceWriter, TraceWriterDecls,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use bitvec::slice::BitSlice;
|
use bitvec::{order::Lsb0, slice::BitSlice};
|
||||||
use std::{
|
use std::{
|
||||||
fmt::{self, Display},
|
fmt,
|
||||||
io::{self, Write},
|
io::{self, Write},
|
||||||
mem,
|
mem,
|
||||||
};
|
};
|
||||||
|
@ -112,20 +113,20 @@ macro_rules! trait_arg {
|
||||||
(
|
(
|
||||||
trait $Arg:ident {
|
trait $Arg:ident {
|
||||||
$(
|
$(
|
||||||
fn $fn:ident(self) -> $ty:ty;
|
fn $fn:ident(&mut self) -> $ty:ty;
|
||||||
)*
|
)*
|
||||||
}
|
}
|
||||||
) => {
|
) => {
|
||||||
trait $Arg: Sized {
|
trait $Arg: Sized {
|
||||||
$(fn $fn(self) -> $ty {
|
$(fn $fn(&mut self) -> $ty {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
})*
|
})*
|
||||||
}
|
}
|
||||||
|
|
||||||
$(
|
$(
|
||||||
impl $Arg for $ty {
|
impl $Arg for $ty {
|
||||||
fn $fn(self) -> $ty {
|
fn $fn(&mut self) -> $ty {
|
||||||
self
|
self.reborrow()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
|
@ -134,21 +135,52 @@ macro_rules! trait_arg {
|
||||||
|
|
||||||
trait_arg! {
|
trait_arg! {
|
||||||
trait Arg {
|
trait Arg {
|
||||||
fn module(self) -> ArgModule;
|
fn module(&mut self) -> ArgModule<'_>;
|
||||||
fn module_body(self) -> ArgModuleBody;
|
fn module_body(&mut self) -> ArgModuleBody<'_>;
|
||||||
fn in_type(self) -> ArgInType;
|
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 ArgModuleBody<'a> {
|
||||||
struct ArgInType {
|
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,
|
source_var_type: &'static str,
|
||||||
sink_var_type: &'static str,
|
sink_var_type: &'static str,
|
||||||
duplex_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 {
|
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 min_char = b'!';
|
||||||
let max_char = b'~';
|
let max_char = b'~';
|
||||||
let base = (max_char - min_char + 1) as usize;
|
let base = (max_char - min_char + 1) as usize;
|
||||||
let mut id = id.as_usize();
|
|
||||||
loop {
|
loop {
|
||||||
let digit = (id % base) as u8 + min_char;
|
let digit = (id % base) as u8 + min_char;
|
||||||
id /= base;
|
id /= base;
|
||||||
|
@ -195,7 +226,7 @@ fn write_scalar_id<W: io::Write>(writer: &mut W, id: TraceScalarId) -> io::Resul
|
||||||
Ok(())
|
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:
|
// escaping rules from function GTKWave uses to decode VCD strings:
|
||||||
// https://github.com/gtkwave/gtkwave/blob/491f24d7e8619cfc1fcc65704ee5c967d1083c18/lib/libfst/fstapi.c#L7090
|
// https://github.com/gtkwave/gtkwave/blob/491f24d7e8619cfc1fcc65704ee5c967d1083c18/lib/libfst/fstapi.c#L7090
|
||||||
struct Wrapper<W>(W);
|
struct Wrapper<W>(W);
|
||||||
|
@ -247,14 +278,47 @@ fn is_unescaped_verilog_identifier(ident: &str) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn write_vcd_var<W: io::Write>(
|
fn write_vcd_var<W: io::Write>(
|
||||||
|
properties: &mut VcdWriterProperties,
|
||||||
|
memory_element_part_body: MemoryElementPartBody,
|
||||||
writer: &mut W,
|
writer: &mut W,
|
||||||
var_type: &str,
|
var_type: &str,
|
||||||
size: usize,
|
size: usize,
|
||||||
id: TraceScalarId,
|
location: TraceLocation,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> io::Result<()> {
|
) -> 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!(writer, "$var {var_type} {size} ")?;
|
||||||
write_scalar_id(writer, id)?;
|
write_vcd_id(writer, id)?;
|
||||||
writer.write_all(b" ")?;
|
writer.write_all(b" ")?;
|
||||||
if !is_unescaped_verilog_identifier(name) {
|
if !is_unescaped_verilog_identifier(name) {
|
||||||
writer.write_all(b"\\")?;
|
writer.write_all(b"\\")?;
|
||||||
|
@ -264,31 +328,49 @@ fn write_vcd_var<W: io::Write>(
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceUInt {
|
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 {
|
let ArgInType {
|
||||||
source_var_type,
|
source_var_type,
|
||||||
sink_var_type,
|
sink_var_type,
|
||||||
duplex_var_type,
|
duplex_var_type,
|
||||||
|
properties,
|
||||||
} = arg.in_type();
|
} = arg.in_type();
|
||||||
let Self { id, name, ty, flow } = self;
|
let Self {
|
||||||
let var_type = match flow {
|
location,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
|
let mut var_type = match flow {
|
||||||
Flow::Source => source_var_type,
|
Flow::Source => source_var_type,
|
||||||
Flow::Sink => sink_var_type,
|
Flow::Sink => sink_var_type,
|
||||||
Flow::Duplex => duplex_var_type,
|
Flow::Duplex => duplex_var_type,
|
||||||
};
|
};
|
||||||
if ty.width() == 0 {
|
if ty.width() == 0 {
|
||||||
write_vcd_var(writer, "string", ty.width(), id, &name)
|
var_type = "string";
|
||||||
} else {
|
|
||||||
write_vcd_var(writer, var_type, ty.width(), id, &name)
|
|
||||||
}
|
}
|
||||||
|
write_vcd_var(
|
||||||
|
properties,
|
||||||
|
MemoryElementPartBody::Scalar,
|
||||||
|
writer,
|
||||||
|
var_type,
|
||||||
|
ty.width(),
|
||||||
|
location,
|
||||||
|
&name,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceSInt {
|
impl WriteTrace for TraceSInt {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, ty, flow } = self;
|
let Self {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id,
|
location,
|
||||||
name,
|
name,
|
||||||
ty: UInt::new_dyn(ty.width()),
|
ty: UInt::new_dyn(ty.width()),
|
||||||
flow,
|
flow,
|
||||||
|
@ -299,9 +381,13 @@ impl WriteTrace for TraceSInt {
|
||||||
|
|
||||||
impl WriteTrace for TraceBool {
|
impl WriteTrace for TraceBool {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, flow } = self;
|
let Self {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id,
|
location,
|
||||||
name,
|
name,
|
||||||
flow,
|
flow,
|
||||||
ty: UInt::new_dyn(1),
|
ty: UInt::new_dyn(1),
|
||||||
|
@ -312,46 +398,93 @@ impl WriteTrace for TraceBool {
|
||||||
|
|
||||||
impl WriteTrace for TraceFieldlessEnum {
|
impl WriteTrace for TraceFieldlessEnum {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, ty, flow } = self;
|
let Self {
|
||||||
TraceEnumDiscriminant { id, name, ty, flow }.write_trace(writer, arg)
|
location,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
|
TraceEnumDiscriminant {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
ty,
|
||||||
|
flow,
|
||||||
|
}
|
||||||
|
.write_trace(writer, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceEnumDiscriminant {
|
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 {
|
let ArgInType {
|
||||||
source_var_type: _,
|
source_var_type: _,
|
||||||
sink_var_type: _,
|
sink_var_type: _,
|
||||||
duplex_var_type: _,
|
duplex_var_type: _,
|
||||||
|
properties,
|
||||||
} = arg.in_type();
|
} = arg.in_type();
|
||||||
let Self {
|
let Self {
|
||||||
id,
|
location,
|
||||||
name,
|
name,
|
||||||
ty: _,
|
ty,
|
||||||
flow: _,
|
flow: _,
|
||||||
} = self;
|
} = 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 {
|
impl WriteTrace for TraceClock {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, flow } = self;
|
let Self {
|
||||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
|
TraceBool {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
}
|
||||||
|
.write_trace(writer, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceSyncReset {
|
impl WriteTrace for TraceSyncReset {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, flow } = self;
|
let Self {
|
||||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
|
TraceBool {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
}
|
||||||
|
.write_trace(writer, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceAsyncReset {
|
impl WriteTrace for TraceAsyncReset {
|
||||||
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, arg: A) -> io::Result<()> {
|
||||||
let Self { id, name, flow } = self;
|
let Self {
|
||||||
TraceBool { id, name, flow }.write_trace(writer, arg)
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
} = self;
|
||||||
|
TraceBool {
|
||||||
|
location,
|
||||||
|
name,
|
||||||
|
flow,
|
||||||
|
}
|
||||||
|
.write_trace(writer, arg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -360,6 +493,7 @@ impl WriteTrace for TraceScope {
|
||||||
match self {
|
match self {
|
||||||
Self::Module(v) => v.write_trace(writer, arg),
|
Self::Module(v) => v.write_trace(writer, arg),
|
||||||
Self::Instance(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::MemPort(v) => v.write_trace(writer, arg),
|
||||||
Self::Wire(v) => v.write_trace(writer, arg),
|
Self::Wire(v) => v.write_trace(writer, arg),
|
||||||
Self::Reg(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 {
|
impl WriteTrace for TraceModule {
|
||||||
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 ArgModule {} = arg.module();
|
let ArgModule { properties } = arg.module();
|
||||||
let Self { name, children } = self;
|
let Self { name, children } = self;
|
||||||
write_vcd_scope(writer, "module", &name, |writer| {
|
write_vcd_scope(writer, "module", &name, |writer| {
|
||||||
for child in children {
|
for child in children {
|
||||||
child.write_trace(writer, ArgModuleBody {})?;
|
child.write_trace(writer, ArgModuleBody { properties })?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -385,8 +519,8 @@ impl WriteTrace for TraceModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceInstance {
|
impl WriteTrace for TraceInstance {
|
||||||
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 ArgModuleBody {} = arg.module_body();
|
let ArgModuleBody { properties } = arg.module_body();
|
||||||
let Self {
|
let Self {
|
||||||
name: _,
|
name: _,
|
||||||
instance_io,
|
instance_io,
|
||||||
|
@ -399,21 +533,74 @@ impl WriteTrace for TraceInstance {
|
||||||
source_var_type: "wire",
|
source_var_type: "wire",
|
||||||
sink_var_type: "wire",
|
sink_var_type: "wire",
|
||||||
duplex_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 {
|
impl WriteTrace for TraceMemPort {
|
||||||
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<()> {
|
||||||
todo!()
|
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 {
|
impl WriteTrace for TraceWire {
|
||||||
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 ArgModuleBody {} = arg.module_body();
|
let ArgModuleBody { properties } = arg.module_body();
|
||||||
let Self {
|
let Self {
|
||||||
name: _,
|
name: _,
|
||||||
child,
|
child,
|
||||||
|
@ -425,14 +612,15 @@ impl WriteTrace for TraceWire {
|
||||||
source_var_type: "wire",
|
source_var_type: "wire",
|
||||||
sink_var_type: "wire",
|
sink_var_type: "wire",
|
||||||
duplex_var_type: "wire",
|
duplex_var_type: "wire",
|
||||||
|
properties,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceReg {
|
impl WriteTrace for TraceReg {
|
||||||
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 ArgModuleBody {} = arg.module_body();
|
let ArgModuleBody { properties } = arg.module_body();
|
||||||
let Self {
|
let Self {
|
||||||
name: _,
|
name: _,
|
||||||
child,
|
child,
|
||||||
|
@ -444,14 +632,15 @@ impl WriteTrace for TraceReg {
|
||||||
source_var_type: "reg",
|
source_var_type: "reg",
|
||||||
sink_var_type: "reg",
|
sink_var_type: "reg",
|
||||||
duplex_var_type: "reg",
|
duplex_var_type: "reg",
|
||||||
|
properties,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceModuleIO {
|
impl WriteTrace for TraceModuleIO {
|
||||||
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 ArgModuleBody {} = arg.module_body();
|
let ArgModuleBody { properties } = arg.module_body();
|
||||||
let Self {
|
let Self {
|
||||||
name: _,
|
name: _,
|
||||||
child,
|
child,
|
||||||
|
@ -464,14 +653,15 @@ impl WriteTrace for TraceModuleIO {
|
||||||
source_var_type: "wire",
|
source_var_type: "wire",
|
||||||
sink_var_type: "wire",
|
sink_var_type: "wire",
|
||||||
duplex_var_type: "wire",
|
duplex_var_type: "wire",
|
||||||
|
properties,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceBundle {
|
impl WriteTrace for TraceBundle {
|
||||||
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 arg = arg.in_type();
|
let mut arg = arg.in_type();
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
fields,
|
fields,
|
||||||
|
@ -480,7 +670,7 @@ impl WriteTrace for TraceBundle {
|
||||||
} = self;
|
} = self;
|
||||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||||
for field in fields {
|
for field in fields {
|
||||||
field.write_trace(writer, arg)?;
|
field.write_trace(writer, arg.reborrow())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -488,8 +678,8 @@ impl WriteTrace for TraceBundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceArray {
|
impl WriteTrace for TraceArray {
|
||||||
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 arg = arg.in_type();
|
let mut arg = arg.in_type();
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
elements,
|
elements,
|
||||||
|
@ -498,7 +688,7 @@ impl WriteTrace for TraceArray {
|
||||||
} = self;
|
} = self;
|
||||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||||
for element in elements {
|
for element in elements {
|
||||||
element.write_trace(writer, arg)?;
|
element.write_trace(writer, arg.reborrow())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -506,8 +696,8 @@ impl WriteTrace for TraceArray {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WriteTrace for TraceEnumWithFields {
|
impl WriteTrace for TraceEnumWithFields {
|
||||||
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 arg = arg.in_type();
|
let mut arg = arg.in_type();
|
||||||
let Self {
|
let Self {
|
||||||
name,
|
name,
|
||||||
discriminant,
|
discriminant,
|
||||||
|
@ -516,9 +706,9 @@ impl WriteTrace for TraceEnumWithFields {
|
||||||
flow: _,
|
flow: _,
|
||||||
} = self;
|
} = self;
|
||||||
write_vcd_scope(writer, "struct", &name, |writer| {
|
write_vcd_scope(writer, "struct", &name, |writer| {
|
||||||
discriminant.write_trace(writer, arg)?;
|
discriminant.write_trace(writer, arg.reborrow())?;
|
||||||
for field in non_empty_fields {
|
for field in non_empty_fields {
|
||||||
field.write_trace(writer, arg)?;
|
field.write_trace(writer, arg.reborrow())?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
|
@ -529,76 +719,184 @@ impl<W: io::Write> TraceWriterDecls for VcdWriterDecls<W> {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
type TraceWriter = VcdWriter<W>;
|
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 {
|
let Self {
|
||||||
mut writer,
|
mut writer,
|
||||||
timescale,
|
timescale,
|
||||||
} = self;
|
} = self;
|
||||||
writeln!(writer, "$timescale {} $end", vcd_timescale(timescale))?;
|
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, "$enddefinitions $end")?;
|
||||||
writeln!(writer, "$dumpvars")?;
|
writeln!(writer, "$dumpvars")?;
|
||||||
Ok(VcdWriter {
|
Ok(VcdWriter {
|
||||||
writer,
|
writer,
|
||||||
finished_init: false,
|
finished_init: false,
|
||||||
timescale,
|
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> {
|
pub struct VcdWriter<W: io::Write + 'static> {
|
||||||
writer: W,
|
writer: W,
|
||||||
finished_init: bool,
|
finished_init: bool,
|
||||||
timescale: SimDuration,
|
timescale: SimDuration,
|
||||||
|
properties: VcdWriterProperties,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<W: io::Write + 'static> VcdWriter<W> {
|
impl<W: io::Write + 'static> VcdWriter<W> {
|
||||||
pub fn timescale(&self) -> SimDuration {
|
pub fn timescale(&self) -> SimDuration {
|
||||||
self.timescale
|
self.timescale
|
||||||
}
|
}
|
||||||
fn write_string_value_change(
|
}
|
||||||
&mut self,
|
|
||||||
value: impl Display,
|
fn write_string_value_change(
|
||||||
id: TraceScalarId,
|
writer: &mut impl io::Write,
|
||||||
) -> io::Result<()> {
|
value: impl fmt::Display,
|
||||||
self.writer.write_all(b"s")?;
|
id: usize,
|
||||||
write_escaped(&mut self.writer, value)?;
|
) -> io::Result<()> {
|
||||||
self.writer.write_all(b" ")?;
|
writer.write_all(b"s")?;
|
||||||
write_scalar_id(&mut self.writer, id)?;
|
write_escaped(writer, value)?;
|
||||||
self.writer.write_all(b"\n")
|
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> {
|
impl<W: io::Write> TraceWriter for VcdWriter<W> {
|
||||||
type Error = io::Error;
|
type Error = io::Error;
|
||||||
|
|
||||||
|
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,
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
fn set_signal_uint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
||||||
match value.len() {
|
write_bits_value_change(&mut self.writer, value, id.as_usize())
|
||||||
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")?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_signal_sint(&mut self, id: TraceScalarId, value: &BitSlice) -> Result<(), Self::Error> {
|
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> {
|
fn finish_init(&mut self) -> Result<(), Self::Error> {
|
||||||
|
@ -630,16 +928,7 @@ impl<W: io::Write> TraceWriter for VcdWriter<W> {
|
||||||
variant_index: usize,
|
variant_index: usize,
|
||||||
ty: Enum,
|
ty: Enum,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
self.write_string_value_change(
|
write_enum_discriminant_value_change(&mut self.writer, variant_index, ty, id.as_usize())
|
||||||
format_args!(
|
|
||||||
"{} ({variant_index})",
|
|
||||||
ty.variants()
|
|
||||||
.get(variant_index)
|
|
||||||
.map(|v| &*v.name)
|
|
||||||
.unwrap_or("<invalid>"),
|
|
||||||
),
|
|
||||||
id,
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -649,6 +938,7 @@ impl<W: io::Write> fmt::Debug for VcdWriter<W> {
|
||||||
writer: _,
|
writer: _,
|
||||||
finished_init,
|
finished_init,
|
||||||
timescale,
|
timescale,
|
||||||
|
properties: _,
|
||||||
} = self;
|
} = self;
|
||||||
f.debug_struct("VcdWriter")
|
f.debug_struct("VcdWriter")
|
||||||
.field("finished_init", finished_init)
|
.field("finished_init", finished_init)
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// SPDX-License-Identifier: LGPL-3.0-or-later
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
// See Notices.txt for copyright information
|
// See Notices.txt for copyright information
|
||||||
|
|
||||||
use fayalite::{
|
use fayalite::{
|
||||||
int::UIntValue,
|
int::UIntValue,
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
@ -7,6 +8,7 @@ use fayalite::{
|
||||||
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
|
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
|
||||||
util::RcWriter,
|
util::RcWriter,
|
||||||
};
|
};
|
||||||
|
use std::num::NonZeroUsize;
|
||||||
|
|
||||||
#[hdl_module(outline_generated)]
|
#[hdl_module(outline_generated)]
|
||||||
pub fn connect_const() {
|
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,
|
pc: 2,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -112,7 +113,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "o",
|
name: "o",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "o",
|
name: "o",
|
||||||
ty: UInt<8>,
|
ty: UInt<8>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -133,6 +134,7 @@ Simulation {
|
||||||
last_state: 0x05,
|
last_state: 0x05,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [],
|
trace_writers: [],
|
||||||
instant: 0 s,
|
instant: 0 s,
|
||||||
clocks_triggered: [],
|
clocks_triggered: [],
|
||||||
|
|
|
@ -73,6 +73,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 5,
|
pc: 5,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -175,7 +176,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "reset_out",
|
name: "reset_out",
|
||||||
child: TraceAsyncReset {
|
child: TraceAsyncReset {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "reset_out",
|
name: "reset_out",
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
|
@ -185,7 +186,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "bit_out",
|
name: "bit_out",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "bit_out",
|
name: "bit_out",
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
|
@ -212,6 +213,7 @@ Simulation {
|
||||||
last_state: 0x1,
|
last_state: 0x1,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
|
@ -168,6 +168,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 18,
|
pc: 18,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -417,12 +418,12 @@ Simulation {
|
||||||
name: "cd",
|
name: "cd",
|
||||||
fields: [
|
fields: [
|
||||||
TraceClock {
|
TraceClock {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "clk",
|
name: "clk",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceAsyncReset {
|
TraceAsyncReset {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "rst",
|
name: "rst",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -446,7 +447,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "count",
|
name: "count",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(2),
|
location: TraceScalarId(2),
|
||||||
name: "count",
|
name: "count",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -457,7 +458,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "count_reg",
|
name: "count_reg",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(3),
|
location: TraceScalarId(3),
|
||||||
name: "count_reg",
|
name: "count_reg",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
|
@ -502,6 +503,7 @@ Simulation {
|
||||||
last_state: 0x3,
|
last_state: 0x3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
|
@ -150,6 +150,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 15,
|
pc: 15,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -398,12 +399,12 @@ Simulation {
|
||||||
name: "cd",
|
name: "cd",
|
||||||
fields: [
|
fields: [
|
||||||
TraceClock {
|
TraceClock {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "clk",
|
name: "clk",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSyncReset {
|
TraceSyncReset {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "rst",
|
name: "rst",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -427,7 +428,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "count",
|
name: "count",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(2),
|
location: TraceScalarId(2),
|
||||||
name: "count",
|
name: "count",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -438,7 +439,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "count_reg",
|
name: "count_reg",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(3),
|
location: TraceScalarId(3),
|
||||||
name: "count_reg",
|
name: "count_reg",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
|
@ -483,6 +484,7 @@ Simulation {
|
||||||
last_state: 0x3,
|
last_state: 0x3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
|
@ -875,6 +875,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 100,
|
pc: 100,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -1333,12 +1334,12 @@ Simulation {
|
||||||
name: "cd",
|
name: "cd",
|
||||||
fields: [
|
fields: [
|
||||||
TraceClock {
|
TraceClock {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "clk",
|
name: "clk",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSyncReset {
|
TraceSyncReset {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "rst",
|
name: "rst",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -1362,7 +1363,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "en",
|
name: "en",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(2),
|
location: TraceScalarId(2),
|
||||||
name: "en",
|
name: "en",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -1372,7 +1373,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "which_in",
|
name: "which_in",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(3),
|
location: TraceScalarId(3),
|
||||||
name: "which_in",
|
name: "which_in",
|
||||||
ty: UInt<2>,
|
ty: UInt<2>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -1383,7 +1384,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "data_in",
|
name: "data_in",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(4),
|
location: TraceScalarId(4),
|
||||||
name: "data_in",
|
name: "data_in",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -1394,7 +1395,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "which_out",
|
name: "which_out",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(5),
|
location: TraceScalarId(5),
|
||||||
name: "which_out",
|
name: "which_out",
|
||||||
ty: UInt<2>,
|
ty: UInt<2>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -1405,7 +1406,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "data_out",
|
name: "data_out",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(6),
|
location: TraceScalarId(6),
|
||||||
name: "data_out",
|
name: "data_out",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -1418,7 +1419,7 @@ Simulation {
|
||||||
child: TraceEnumWithFields {
|
child: TraceEnumWithFields {
|
||||||
name: "the_reg",
|
name: "the_reg",
|
||||||
discriminant: TraceEnumDiscriminant {
|
discriminant: TraceEnumDiscriminant {
|
||||||
id: TraceScalarId(7),
|
location: TraceScalarId(7),
|
||||||
name: "$tag",
|
name: "$tag",
|
||||||
ty: Enum {
|
ty: Enum {
|
||||||
A,
|
A,
|
||||||
|
@ -1432,13 +1433,13 @@ Simulation {
|
||||||
name: "B",
|
name: "B",
|
||||||
fields: [
|
fields: [
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(8),
|
location: TraceScalarId(8),
|
||||||
name: "0",
|
name: "0",
|
||||||
ty: UInt<1>,
|
ty: UInt<1>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceBool {
|
TraceBool {
|
||||||
id: TraceScalarId(9),
|
location: TraceScalarId(9),
|
||||||
name: "1",
|
name: "1",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -1458,13 +1459,13 @@ Simulation {
|
||||||
name: "a",
|
name: "a",
|
||||||
elements: [
|
elements: [
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(10),
|
location: TraceScalarId(10),
|
||||||
name: "[0]",
|
name: "[0]",
|
||||||
ty: UInt<1>,
|
ty: UInt<1>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(11),
|
location: TraceScalarId(11),
|
||||||
name: "[1]",
|
name: "[1]",
|
||||||
ty: UInt<1>,
|
ty: UInt<1>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -1474,7 +1475,7 @@ Simulation {
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSInt {
|
TraceSInt {
|
||||||
id: TraceScalarId(12),
|
location: TraceScalarId(12),
|
||||||
name: "b",
|
name: "b",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -1623,6 +1624,7 @@ Simulation {
|
||||||
last_state: 0x3,
|
last_state: 0x3,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
|
@ -180,6 +180,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 17,
|
pc: 17,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -531,25 +532,25 @@ Simulation {
|
||||||
name: "o",
|
name: "o",
|
||||||
fields: [
|
fields: [
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "i",
|
name: "i",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSInt {
|
TraceSInt {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "o",
|
name: "o",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
TraceSInt {
|
TraceSInt {
|
||||||
id: TraceScalarId(2),
|
location: TraceScalarId(2),
|
||||||
name: "i2",
|
name: "i2",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(3),
|
location: TraceScalarId(3),
|
||||||
name: "o2",
|
name: "o2",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -585,25 +586,25 @@ Simulation {
|
||||||
name: "child",
|
name: "child",
|
||||||
fields: [
|
fields: [
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(8),
|
location: TraceScalarId(8),
|
||||||
name: "i",
|
name: "i",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
TraceSInt {
|
TraceSInt {
|
||||||
id: TraceScalarId(9),
|
location: TraceScalarId(9),
|
||||||
name: "o",
|
name: "o",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSInt {
|
TraceSInt {
|
||||||
id: TraceScalarId(10),
|
location: TraceScalarId(10),
|
||||||
name: "i2",
|
name: "i2",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
TraceUInt {
|
TraceUInt {
|
||||||
id: TraceScalarId(11),
|
location: TraceScalarId(11),
|
||||||
name: "o2",
|
name: "o2",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -627,7 +628,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "i",
|
name: "i",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(4),
|
location: TraceScalarId(4),
|
||||||
name: "i",
|
name: "i",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -638,7 +639,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "o",
|
name: "o",
|
||||||
child: TraceSInt {
|
child: TraceSInt {
|
||||||
id: TraceScalarId(5),
|
location: TraceScalarId(5),
|
||||||
name: "o",
|
name: "o",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -649,7 +650,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "i2",
|
name: "i2",
|
||||||
child: TraceSInt {
|
child: TraceSInt {
|
||||||
id: TraceScalarId(6),
|
location: TraceScalarId(6),
|
||||||
name: "i2",
|
name: "i2",
|
||||||
ty: SInt<2>,
|
ty: SInt<2>,
|
||||||
flow: Source,
|
flow: Source,
|
||||||
|
@ -660,7 +661,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "o2",
|
name: "o2",
|
||||||
child: TraceUInt {
|
child: TraceUInt {
|
||||||
id: TraceScalarId(7),
|
location: TraceScalarId(7),
|
||||||
name: "o2",
|
name: "o2",
|
||||||
ty: UInt<4>,
|
ty: UInt<4>,
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
|
@ -793,6 +794,7 @@ Simulation {
|
||||||
last_state: 0xe,
|
last_state: 0xe,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
|
@ -227,6 +227,7 @@ Simulation {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
pc: 30,
|
pc: 30,
|
||||||
|
memory_write_log: [],
|
||||||
memories: StatePart {
|
memories: StatePart {
|
||||||
value: [],
|
value: [],
|
||||||
},
|
},
|
||||||
|
@ -513,12 +514,12 @@ Simulation {
|
||||||
name: "cd",
|
name: "cd",
|
||||||
fields: [
|
fields: [
|
||||||
TraceClock {
|
TraceClock {
|
||||||
id: TraceScalarId(0),
|
location: TraceScalarId(0),
|
||||||
name: "clk",
|
name: "clk",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
TraceSyncReset {
|
TraceSyncReset {
|
||||||
id: TraceScalarId(1),
|
location: TraceScalarId(1),
|
||||||
name: "rst",
|
name: "rst",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -542,7 +543,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "d",
|
name: "d",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(2),
|
location: TraceScalarId(2),
|
||||||
name: "d",
|
name: "d",
|
||||||
flow: Source,
|
flow: Source,
|
||||||
},
|
},
|
||||||
|
@ -552,7 +553,7 @@ Simulation {
|
||||||
TraceModuleIO {
|
TraceModuleIO {
|
||||||
name: "q",
|
name: "q",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(3),
|
location: TraceScalarId(3),
|
||||||
name: "q",
|
name: "q",
|
||||||
flow: Sink,
|
flow: Sink,
|
||||||
},
|
},
|
||||||
|
@ -562,7 +563,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "reg0",
|
name: "reg0",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(4),
|
location: TraceScalarId(4),
|
||||||
name: "reg0",
|
name: "reg0",
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
},
|
},
|
||||||
|
@ -571,7 +572,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "reg1",
|
name: "reg1",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(5),
|
location: TraceScalarId(5),
|
||||||
name: "reg1",
|
name: "reg1",
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
},
|
},
|
||||||
|
@ -580,7 +581,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "reg2",
|
name: "reg2",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(6),
|
location: TraceScalarId(6),
|
||||||
name: "reg2",
|
name: "reg2",
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
},
|
},
|
||||||
|
@ -589,7 +590,7 @@ Simulation {
|
||||||
TraceReg {
|
TraceReg {
|
||||||
name: "reg3",
|
name: "reg3",
|
||||||
child: TraceBool {
|
child: TraceBool {
|
||||||
id: TraceScalarId(7),
|
location: TraceScalarId(7),
|
||||||
name: "reg3",
|
name: "reg3",
|
||||||
flow: Duplex,
|
flow: Duplex,
|
||||||
},
|
},
|
||||||
|
@ -663,6 +664,7 @@ Simulation {
|
||||||
last_state: 0x0,
|
last_state: 0x0,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
trace_memories: {},
|
||||||
trace_writers: [
|
trace_writers: [
|
||||||
Running(
|
Running(
|
||||||
VcdWriter {
|
VcdWriter {
|
||||||
|
|
Loading…
Reference in a new issue