forked from libre-chip/cpu
WIP fixing bugs
This commit is contained in:
parent
5e1238b5c7
commit
59da0aec06
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
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue