simulator: allow external module generators to wait for value changes and/or clock edges
This commit is contained in:
parent
ab9ff4f2db
commit
a115585d5a
6 changed files with 969 additions and 182 deletions
|
|
@ -1485,3 +1485,50 @@ fn test_extern_module() {
|
|||
panic!();
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl_module(outline_generated, extern)]
|
||||
pub fn extern_module2() {
|
||||
#[hdl]
|
||||
let en: Bool = m.input();
|
||||
#[hdl]
|
||||
let clk: Clock = m.input();
|
||||
#[hdl]
|
||||
let o: UInt<8> = m.output();
|
||||
m.extern_module_simulation_fn((en, clk, o), |(en, clk, o), mut sim| async move {
|
||||
for b in "Hello, World!\n".bytes().cycle() {
|
||||
sim.write(o, b).await;
|
||||
loop {
|
||||
sim.wait_for_clock_edge(clk).await;
|
||||
if sim.read_bool(en).await {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_extern_module2() {
|
||||
let _n = SourceLocation::normalize_files_for_tests();
|
||||
let mut sim = Simulation::new(extern_module2());
|
||||
let mut writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
for i in 0..30 {
|
||||
sim.write(sim.io().en, i % 10 < 5);
|
||||
sim.write(sim.io().clk, false);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
sim.write(sim.io().clk, true);
|
||||
sim.advance_time(SimDuration::from_micros(1));
|
||||
}
|
||||
sim.flush_traces().unwrap();
|
||||
let vcd = String::from_utf8(writer.take()).unwrap();
|
||||
println!("####### VCD:\n{vcd}\n#######");
|
||||
if vcd != include_str!("sim/expected/extern_module2.vcd") {
|
||||
panic!();
|
||||
}
|
||||
let sim_debug = format!("{sim:#?}");
|
||||
println!("#######\n{sim_debug}\n#######");
|
||||
if sim_debug != include_str!("sim/expected/extern_module2.txt") {
|
||||
panic!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,11 +153,11 @@ Simulation {
|
|||
running_generator: Some(
|
||||
...,
|
||||
),
|
||||
wait_target: Some(
|
||||
wait_targets: {
|
||||
Instant(
|
||||
20.500000000000 μs,
|
||||
),
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
state_ready_to_run: false,
|
||||
|
|
|
|||
308
crates/fayalite/tests/sim/expected/extern_module2.txt
Normal file
308
crates/fayalite/tests/sim/expected/extern_module2.txt
Normal file
|
|
@ -0,0 +1,308 @@
|
|||
Simulation {
|
||||
state: State {
|
||||
insns: Insns {
|
||||
state_layout: StateLayout {
|
||||
ty: TypeLayout {
|
||||
small_slots: StatePartLayout<SmallSlots> {
|
||||
len: 0,
|
||||
debug_data: [],
|
||||
..
|
||||
},
|
||||
big_slots: StatePartLayout<BigSlots> {
|
||||
len: 3,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::en",
|
||||
ty: Bool,
|
||||
},
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::clk",
|
||||
ty: Clock,
|
||||
},
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::o",
|
||||
ty: UInt<8>,
|
||||
},
|
||||
],
|
||||
..
|
||||
},
|
||||
},
|
||||
memories: StatePartLayout<Memories> {
|
||||
len: 0,
|
||||
debug_data: [],
|
||||
layout_data: [],
|
||||
..
|
||||
},
|
||||
},
|
||||
insns: [
|
||||
// at: module-XXXXXXXXXX.rs:1:1
|
||||
0: Return,
|
||||
],
|
||||
..
|
||||
},
|
||||
pc: 0,
|
||||
memory_write_log: [],
|
||||
memories: StatePart {
|
||||
value: [],
|
||||
},
|
||||
small_slots: StatePart {
|
||||
value: [],
|
||||
},
|
||||
big_slots: StatePart {
|
||||
value: [
|
||||
0,
|
||||
1,
|
||||
101,
|
||||
],
|
||||
},
|
||||
},
|
||||
io: Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
},
|
||||
main_module: SimulationModuleState {
|
||||
base_targets: [
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.en,
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.clk,
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.o,
|
||||
],
|
||||
uninitialized_ios: {},
|
||||
io_targets: {
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.clk,
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.en,
|
||||
Instance {
|
||||
name: <simulator>::extern_module2,
|
||||
instantiated: Module {
|
||||
name: extern_module2,
|
||||
..
|
||||
},
|
||||
}.o,
|
||||
},
|
||||
did_initial_settle: true,
|
||||
},
|
||||
extern_modules: [
|
||||
SimulationExternModuleState {
|
||||
module_state: SimulationModuleState {
|
||||
base_targets: [
|
||||
ModuleIO {
|
||||
name: extern_module2::en,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::clk,
|
||||
is_input: true,
|
||||
ty: Clock,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::o,
|
||||
is_input: false,
|
||||
ty: UInt<8>,
|
||||
..
|
||||
},
|
||||
],
|
||||
uninitialized_ios: {},
|
||||
io_targets: {
|
||||
ModuleIO {
|
||||
name: extern_module2::clk,
|
||||
is_input: true,
|
||||
ty: Clock,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::en,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::o,
|
||||
is_input: false,
|
||||
ty: UInt<8>,
|
||||
..
|
||||
},
|
||||
},
|
||||
did_initial_settle: true,
|
||||
},
|
||||
sim: ExternModuleSimulation {
|
||||
generator: SimGeneratorFn {
|
||||
args: (
|
||||
ModuleIO {
|
||||
name: extern_module2::en,
|
||||
is_input: true,
|
||||
ty: Bool,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::clk,
|
||||
is_input: true,
|
||||
ty: Clock,
|
||||
..
|
||||
},
|
||||
ModuleIO {
|
||||
name: extern_module2::o,
|
||||
is_input: false,
|
||||
ty: UInt<8>,
|
||||
..
|
||||
},
|
||||
),
|
||||
f: ...,
|
||||
},
|
||||
source_location: SourceLocation(
|
||||
module-XXXXXXXXXX.rs:5:1,
|
||||
),
|
||||
},
|
||||
running_generator: Some(
|
||||
...,
|
||||
),
|
||||
wait_targets: {
|
||||
Change {
|
||||
key: CompiledValue {
|
||||
layout: CompiledTypeLayout {
|
||||
ty: Clock,
|
||||
layout: TypeLayout {
|
||||
small_slots: StatePartLayout<SmallSlots> {
|
||||
len: 0,
|
||||
debug_data: [],
|
||||
..
|
||||
},
|
||||
big_slots: StatePartLayout<BigSlots> {
|
||||
len: 1,
|
||||
debug_data: [
|
||||
SlotDebugData {
|
||||
name: "InstantiatedModule(extern_module2: extern_module2).extern_module2::clk",
|
||||
ty: Clock,
|
||||
},
|
||||
],
|
||||
..
|
||||
},
|
||||
},
|
||||
body: Scalar,
|
||||
},
|
||||
range: TypeIndexRange {
|
||||
small_slots: StatePartIndexRange<SmallSlots> { start: 0, len: 0 },
|
||||
big_slots: StatePartIndexRange<BigSlots> { start: 1, len: 1 },
|
||||
},
|
||||
write: None,
|
||||
},
|
||||
value: SimValue {
|
||||
ty: Clock,
|
||||
bits: 0x1,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
state_ready_to_run: false,
|
||||
trace_decls: TraceModule {
|
||||
name: "extern_module2",
|
||||
children: [
|
||||
TraceModuleIO {
|
||||
name: "en",
|
||||
child: TraceBool {
|
||||
location: TraceScalarId(0),
|
||||
name: "en",
|
||||
flow: Source,
|
||||
},
|
||||
ty: Bool,
|
||||
flow: Source,
|
||||
},
|
||||
TraceModuleIO {
|
||||
name: "clk",
|
||||
child: TraceClock {
|
||||
location: TraceScalarId(1),
|
||||
name: "clk",
|
||||
flow: Source,
|
||||
},
|
||||
ty: Clock,
|
||||
flow: Source,
|
||||
},
|
||||
TraceModuleIO {
|
||||
name: "o",
|
||||
child: TraceUInt {
|
||||
location: TraceScalarId(2),
|
||||
name: "o",
|
||||
ty: UInt<8>,
|
||||
flow: Sink,
|
||||
},
|
||||
ty: UInt<8>,
|
||||
flow: Sink,
|
||||
},
|
||||
],
|
||||
},
|
||||
traces: [
|
||||
SimTrace {
|
||||
id: TraceScalarId(0),
|
||||
kind: BigBool {
|
||||
index: StatePartIndex<BigSlots>(0),
|
||||
},
|
||||
state: 0x0,
|
||||
last_state: 0x0,
|
||||
},
|
||||
SimTrace {
|
||||
id: TraceScalarId(1),
|
||||
kind: BigClock {
|
||||
index: StatePartIndex<BigSlots>(1),
|
||||
},
|
||||
state: 0x1,
|
||||
last_state: 0x1,
|
||||
},
|
||||
SimTrace {
|
||||
id: TraceScalarId(2),
|
||||
kind: BigUInt {
|
||||
index: StatePartIndex<BigSlots>(2),
|
||||
ty: UInt<8>,
|
||||
},
|
||||
state: 0x65,
|
||||
last_state: 0x65,
|
||||
},
|
||||
],
|
||||
trace_memories: {},
|
||||
trace_writers: [
|
||||
Running(
|
||||
VcdWriter {
|
||||
finished_init: true,
|
||||
timescale: 1 ps,
|
||||
..
|
||||
},
|
||||
),
|
||||
],
|
||||
instant: 60 μs,
|
||||
clocks_triggered: [],
|
||||
..
|
||||
}
|
||||
150
crates/fayalite/tests/sim/expected/extern_module2.vcd
Normal file
150
crates/fayalite/tests/sim/expected/extern_module2.vcd
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
$timescale 1 ps $end
|
||||
$scope module extern_module2 $end
|
||||
$var wire 1 ! en $end
|
||||
$var wire 1 " clk $end
|
||||
$var wire 8 # o $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$dumpvars
|
||||
1!
|
||||
0"
|
||||
b1001000 #
|
||||
$end
|
||||
#1000000
|
||||
1"
|
||||
b1100101 #
|
||||
#2000000
|
||||
0"
|
||||
#3000000
|
||||
1"
|
||||
b1101100 #
|
||||
#4000000
|
||||
0"
|
||||
#5000000
|
||||
1"
|
||||
#6000000
|
||||
0"
|
||||
#7000000
|
||||
1"
|
||||
b1101111 #
|
||||
#8000000
|
||||
0"
|
||||
#9000000
|
||||
1"
|
||||
b101100 #
|
||||
#10000000
|
||||
0!
|
||||
0"
|
||||
#11000000
|
||||
1"
|
||||
#12000000
|
||||
0"
|
||||
#13000000
|
||||
1"
|
||||
#14000000
|
||||
0"
|
||||
#15000000
|
||||
1"
|
||||
#16000000
|
||||
0"
|
||||
#17000000
|
||||
1"
|
||||
#18000000
|
||||
0"
|
||||
#19000000
|
||||
1"
|
||||
#20000000
|
||||
1!
|
||||
0"
|
||||
#21000000
|
||||
1"
|
||||
b100000 #
|
||||
#22000000
|
||||
0"
|
||||
#23000000
|
||||
1"
|
||||
b1010111 #
|
||||
#24000000
|
||||
0"
|
||||
#25000000
|
||||
1"
|
||||
b1101111 #
|
||||
#26000000
|
||||
0"
|
||||
#27000000
|
||||
1"
|
||||
b1110010 #
|
||||
#28000000
|
||||
0"
|
||||
#29000000
|
||||
1"
|
||||
b1101100 #
|
||||
#30000000
|
||||
0!
|
||||
0"
|
||||
#31000000
|
||||
1"
|
||||
#32000000
|
||||
0"
|
||||
#33000000
|
||||
1"
|
||||
#34000000
|
||||
0"
|
||||
#35000000
|
||||
1"
|
||||
#36000000
|
||||
0"
|
||||
#37000000
|
||||
1"
|
||||
#38000000
|
||||
0"
|
||||
#39000000
|
||||
1"
|
||||
#40000000
|
||||
1!
|
||||
0"
|
||||
#41000000
|
||||
1"
|
||||
b1100100 #
|
||||
#42000000
|
||||
0"
|
||||
#43000000
|
||||
1"
|
||||
b100001 #
|
||||
#44000000
|
||||
0"
|
||||
#45000000
|
||||
1"
|
||||
b1010 #
|
||||
#46000000
|
||||
0"
|
||||
#47000000
|
||||
1"
|
||||
b1001000 #
|
||||
#48000000
|
||||
0"
|
||||
#49000000
|
||||
1"
|
||||
b1100101 #
|
||||
#50000000
|
||||
0!
|
||||
0"
|
||||
#51000000
|
||||
1"
|
||||
#52000000
|
||||
0"
|
||||
#53000000
|
||||
1"
|
||||
#54000000
|
||||
0"
|
||||
#55000000
|
||||
1"
|
||||
#56000000
|
||||
0"
|
||||
#57000000
|
||||
1"
|
||||
#58000000
|
||||
0"
|
||||
#59000000
|
||||
1"
|
||||
#60000000
|
||||
Loading…
Add table
Add a link
Reference in a new issue