WIP fixing bugs

This commit is contained in:
Jacob Lifshay 2025-12-16 02:32:19 -08:00
parent 5e1238b5c7
commit 59da0aec06
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
3 changed files with 38211 additions and 16198 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -771,7 +771,7 @@ impl FetchPipeQueueEntry {
.rotate_left(32)
.wrapping_mul(0x92B38C197608A6B) // random prime
.rotate_right(60);
(random % 8) as u8
if random % 32 == 0 { 30 } else { 3 }
}
}
@ -799,6 +799,12 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
async |mut sim| {
sim.write(from_fetch.fetch.ready, false).await;
sim.write(from_fetch.cancel.ready, false).await;
sim.write(
from_fetch.next_fetch_block_ids,
#[hdl(sim)]
(from_fetch.next_fetch_block_ids.ty()).HdlNone(),
)
.await;
sim.write(
to_post_decode.inner.data,
to_post_decode.ty().inner.data.HdlNone(),
@ -840,12 +846,21 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
let mut next_id = 0u32;
loop {
let mut sim_queue = queue_debug.ty().new_sim(FetchPipeQueueEntry.default_sim());
let mut next_fetch_block_ids =
from_fetch.next_fetch_block_ids.ty().HdlSome.new_sim(0u8);
for entry in &queue {
ArrayVec::try_push_sim(&mut sim_queue, entry)
.ok()
.expect("queue is known to be small enough");
let _ = ArrayVec::try_push_sim(&mut next_fetch_block_ids, &entry.fetch_block_id);
}
sim.write(queue_debug, sim_queue).await;
sim.write(
from_fetch.next_fetch_block_ids,
#[hdl(sim)]
(from_fetch.next_fetch_block_ids.ty()).HdlSome(next_fetch_block_ids),
)
.await;
if let Some(front) = queue.front().filter(|v| v.cycles_left.as_int() == 0) {
#[hdl(sim)]
let FetchPipeQueueEntry {
@ -874,6 +889,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
fetch_block_id,
id: next_id.cast_to_static::<UInt<_>>(),
pc,
predicted_next_pc: 0u64,
size_in_bytes: insn.byte_len().cast_to_static::<UInt<_>>(),
kind: insn.wip_decoded_insn_kind(),
};
@ -890,6 +906,7 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
fetch_block_id,
id: next_id.cast_to_static::<UInt<_>>(),
pc: start_pc,
predicted_next_pc: 0u64,
size_in_bytes: 0u8.cast_to_static::<UInt<_>>(),
kind: WipDecodedInsnKind.Interrupt(DEMO_ILLEGAL_INSN_TRAP),
},
@ -917,10 +934,27 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
.await;
sim.write(from_fetch.cancel.ready, true).await;
sim.wait_for_clock_edge(cd.clk).await;
println!(
"Dump mock fetch decode pipe queue: {:#?}",
Vec::from_iter(queue.iter().map(|v| {
DebugAsDisplay(format!(
"fid={:#x} pc={:#x}",
v.fetch_block_id.as_int(),
v.start_pc.as_int(),
))
}))
);
if sim.read_past_bool(to_post_decode.inner.ready, cd.clk).await {
#[hdl(sim)]
if let HdlSome(_) = sim.read_past(to_post_decode.inner.data, cd.clk).await {
queue.pop_front();
let Some(v) = queue.pop_front() else {
unreachable!();
};
println!(
"mock fetch decode pipe queue pop: fid={:#x} pc={:#x}",
v.fetch_block_id.as_int(),
v.start_pc.as_int(),
);
}
}
for entry in &mut queue {
@ -935,7 +969,14 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
{
// cancel in-progress fetches from newest to oldest
for _ in 0..*in_progress_fetches_to_cancel {
let _ = queue.pop_back();
let Some(v) = queue.pop_back() else {
unreachable!();
};
println!(
"mock fetch decode pipe queue cancel unpush: fid={:#x} pc={:#x}",
v.fetch_block_id.as_int(),
v.start_pc.as_int(),
);
}
}
if !sim.read_past_bool(from_fetch.fetch.ready, cd.clk).await {
@ -949,6 +990,11 @@ fn mock_fetch_pipe(config: PhantomConst<CpuConfig>, insns: MockInsns) {
start_pc,
fetch_block_id,
} = &inner;
println!(
"mock fetch decode pipe queue push: fid={:#x} pc={:#x}",
fetch_block_id.as_int(),
start_pc.as_int(),
);
queue.push_back(
#[hdl(sim)]
FetchPipeQueueEntry {
@ -979,7 +1025,8 @@ impl ExecuteRetirePipeQueueEntry {
WipDecodedInsn {
fetch_block_id: 0u8,
id: 0_hdl_u12,
pc: 0xEEEE_EEEE_EEEE_EEEEu64,
pc: 0u64,
predicted_next_pc: 0u64,
size_in_bytes: 0_hdl_u4,
kind: WipDecodedInsnKind.NonBranch(),
},
@ -996,7 +1043,13 @@ impl ExecuteRetirePipeQueueEntry {
.rotate_left(32)
.wrapping_mul(0x73161B54984B1C21) // random prime
.rotate_right(60);
(random % 16) as u8
const DELAYS: &[u8; 0x20] = &[
0, 0, 0, 0, 0, 0, 0, 0, //
1, 1, 1, 1, 1, 1, 1, 1, //
2, 2, 2, 2, 2, 2, 2, 2, //
3, 3, 3, 3, 4, 5, 6, 50, // 50 for simulating a cache miss or something
];
DELAYS[(random & 0x1F) as usize]
}
}
@ -1052,6 +1105,7 @@ impl MockExecuteState {
fetch_block_id: &insn.fetch_block_id,
id: &insn.id,
pc,
predicted_next_pc: &insn.predicted_next_pc,
size_in_bytes: mock_insn.byte_len().cast_to_static::<UInt<4>>(),
kind: mock_insn.wip_decoded_insn_kind(),
};
@ -1060,16 +1114,14 @@ impl MockExecuteState {
"insn doesn't match expected:\ninsn: {insn:?}\nexpected insn: {expected_insn:?}"
));
}
if let Some(next_insn) = self.queue.front() {
if next_pc != next_insn.insn.pc.as_int() {
self.canceling = true;
if !passive {
println!(
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={next_insn_pc}",
self.queue.len(),
next_insn_pc = next_insn.insn.pc
);
}
if next_pc != insn.predicted_next_pc.as_int() {
self.canceling = true;
if !passive {
println!(
"MockExecuteState: starting canceling {} instruction(s): next_pc={next_pc:#x}, mis-predicted next_pc={}",
self.queue.len(),
insn.predicted_next_pc
);
}
}
Ok(
@ -1130,6 +1182,10 @@ impl MockExecuteState {
if !self.used_ids.insert(insn.id.clone()) {
panic!("next_pc gave a duplicate insn id: {insn:?}");
}
println!(
"MockExecutionState::start fid={} id={} pc={}",
insn.fetch_block_id, insn.id, insn.pc
);
self.queue.push_back(
#[hdl(sim)]
ExecuteRetirePipeQueueEntry {
@ -1187,6 +1243,7 @@ fn mock_execute_retire_pipe(
cd,
async |mut sim| {
sim.write(from_post_decode.ready, 0usize).await;
sim.write(from_post_decode.cancel.ready, false).await;
sim.write(
retire_output.inner.data,
retire_output.ty().inner.data.HdlNone(),
@ -1310,6 +1367,8 @@ fn mock_execute_retire_pipe(
},
)
.await;
sim.write(from_post_decode.cancel.ready, state.canceling)
.await;
sim.wait_for_clock_edge(cd.clk).await;
println!(
"Dump mock execute retire pipe queue: {:#?}",
@ -1322,8 +1381,17 @@ fn mock_execute_retire_pipe(
))
}))
);
if state.canceling {
state.finish_cancel();
#[hdl(sim)]
if let HdlSome(v) = sim.read_past(from_post_decode.cancel.data, cd.clk).await {
#[hdl(sim)]
let () = v;
if sim
.read_past_bool(from_post_decode.cancel.ready, cd.clk)
.await
{
assert!(state.canceling);
state.finish_cancel();
}
}
if sim.read_past_bool(retire_output.inner.ready, cd.clk).await {
for _ in 0..**ArrayVec::len_sim(&retiring) {
@ -1339,7 +1407,7 @@ fn mock_execute_retire_pipe(
&mut new_insns,
*sim.read_past(from_post_decode.ready, cd.clk).await,
);
for insn in dbg!(ArrayVec::elements_sim_ref(&new_insns)) {
for insn in ArrayVec::elements_sim_ref(&new_insns) {
state.start(insn, delay_sequence_index);
}
}
@ -1430,9 +1498,9 @@ fn test_next_pc() {
};
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
for _cycle in 0..500 {
for cycle in 0..800 {
sim.advance_time(SimDuration::from_nanos(500));
println!("clock tick");
println!("clock tick: {cycle}");
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);