add test_many_memories so we catch if memories are iterated in an inconsistent order like in 838bd469ce
All checks were successful
/ test (pull_request) Successful in 4m44s
/ test (push) Successful in 5m22s

This commit is contained in:
Jacob Lifshay 2025-10-24 01:39:02 -07:00
parent 838bd469ce
commit 7dc4417874
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
3 changed files with 10683 additions and 1 deletions

View file

@ -3,7 +3,7 @@
use fayalite::{
memory::{ReadStruct, ReadWriteStruct, WriteStruct},
module::{instance_with_loc, reg_builder_with_loc},
module::{instance_with_loc, memory_with_init_and_loc, reg_builder_with_loc},
prelude::*,
reset::ResetType,
sim::vcd::VcdWriterDecls,
@ -1261,6 +1261,310 @@ fn test_memories3() {
}
}
#[hdl_module(outline_generated)]
pub fn many_memories() {
#[hdl]
let r: Array<ReadStruct<Bool, ConstUsize<4>>, 8> = m.input();
#[hdl]
let w: Array<WriteStruct<Bool, ConstUsize<4>>, 8> = m.input();
for (mem_index, (r, w)) in r.into_iter().zip(w).enumerate() {
let mut mem = memory_with_init_and_loc(
&format!("mem_{mem_index}"),
(0..16)
.map(|bit_index| mem_index.pow(5).to_expr()[bit_index])
.collect::<Vec<_>>(),
SourceLocation::caller(),
);
connect_any(mem.new_read_port(), r);
connect_any(mem.new_write_port(), w);
}
}
#[hdl]
#[test]
fn test_many_memories() {
let _n = SourceLocation::normalize_files_for_tests();
let mut sim = Simulation::new(many_memories());
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
for r in sim.io().r {
sim.write_clock(r.clk, false);
}
for w in sim.io().w {
sim.write_clock(w.clk, false);
}
#[hdl(cmp_eq)]
struct IO {
r_addr: UInt<4>,
r_en: Bool,
r_data: Array<Bool, 8>,
w_addr: UInt<4>,
w_en: Bool,
w_data: Array<Bool, 8>,
w_mask: Array<Bool, 8>,
}
let io_cycles = [
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: false,
r_data: [false; 8],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [false; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [false, true, false, true, false, true, false, true],
w_addr: 0_hdl_u4,
w_en: true,
w_data: [true; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [true; 8],
w_addr: 0_hdl_u4,
w_en: true,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0_hdl_u4,
r_en: true,
r_data: [false; 8],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 1_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 2_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, true, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 3_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 4_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, true, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 5_hdl_u4,
r_en: true,
r_data: [false, false, true, true, false, true, true, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 6_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 7_hdl_u4,
r_en: true,
r_data: [false, false, false, true, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 8_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 9_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xA_hdl_u4,
r_en: true,
r_data: [false, false, false, false, true, true, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xB_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, true, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xC_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, true, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xD_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xE_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, true],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
#[hdl(sim)]
IO {
r_addr: 0xF_hdl_u4,
r_en: true,
r_data: [false, false, false, false, false, false, false, false],
w_addr: 0_hdl_u4,
w_en: false,
w_data: [false; 8],
w_mask: [true; 8],
},
];
for (cycle, expected) in io_cycles.into_iter().enumerate() {
#[hdl(sim)]
let IO {
r_addr,
r_en,
r_data: _,
w_addr,
w_en,
w_data,
w_mask,
} = expected;
for (((r, w), w_data), w_mask) in sim
.io()
.r
.into_iter()
.zip(sim.io().w)
.zip(w_data.iter())
.zip(w_mask.iter())
{
sim.write(r.addr, &r_addr);
sim.write(r.en, &r_en);
sim.write(w.addr, &w_addr);
sim.write(w.en, &w_en);
sim.write(w.data, w_data);
sim.write(w.mask, w_mask);
}
let io = #[hdl(sim)]
IO {
r_addr,
r_en,
r_data: std::array::from_fn(|i| sim.read(sim.io().r[i].data)),
w_addr,
w_en,
w_data,
w_mask,
};
assert_eq!(
expected,
io,
"vcd:\n{}\ncycle: {cycle}",
String::from_utf8(writer.take()).unwrap(),
);
sim.advance_time(SimDuration::from_micros(1));
for r in sim.io().r {
sim.write_clock(r.clk, true);
}
for w in sim.io().w {
sim.write_clock(w.clk, true);
}
sim.advance_time(SimDuration::from_micros(1));
for r in sim.io().r {
sim.write_clock(r.clk, false);
}
for w in sim.io().w {
sim.write_clock(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/many_memories.vcd") {
panic!();
}
let sim_debug = format!("{sim:#?}");
println!("#######\n{sim_debug}\n#######");
if sim_debug != include_str!("sim/expected/many_memories.txt") {
panic!();
}
}
#[hdl_module(outline_generated)]
pub fn duplicate_names() {
#[hdl]

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff