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