sim: add WIP memory test
This commit is contained in:
		
							parent
							
								
									8616ee4737
								
							
						
					
					
						commit
						393f78a14d
					
				
					 11 changed files with 1155 additions and 304 deletions
				
			
		
										
											
												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…
	
	Add table
		Add a link
		
	
		Reference in a new issue