Skip to content

Commit 222e26c

Browse files
committed
fix(pipeline): send flw/fsw through the LSU in parallel-FU mode
In FunctionalUnits mode, flw and fsw went to the FPU unit because their class is FloatingPoint. Results from that unit go straight to WB, so the load never read memory and the store never wrote it. Any value that went through memory into or out of the float registers was lost; rv32uf passed 4 of 11 in this mode. Dispatch them to the LSU and count them as memory operations for the ordering check. rv32uf now passes 11/11 in all four pipeline modes. The other modes do not use these paths, and their cycle counts on the riscv-tests ELFs are unchanged.
1 parent 8cb4aa2 commit 222e26c

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

‎crates/raven-engine/src/architectures/riscv32/falcon/pipeline/sim.rs‎

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2854,8 +2854,19 @@ fn apply_just_committed_visibility_to_mem(slot: &mut PipeSlot, committed: &PipeS
28542854
}
28552855
}
28562856

2857+
/// `flw` and `fsw` are FloatingPoint by class but access memory: they must go
2858+
/// through the LSU and MEM, not straight from the FPU to WB.
2859+
fn is_float_memory_slot(slot: &PipeSlot) -> bool {
2860+
matches!(
2861+
slot.instr
2862+
.or_else(|| crate::falcon::decoder::decode(slot.word).ok()),
2863+
Some(Instruction::Flw { .. } | Instruction::Fsw { .. })
2864+
)
2865+
}
2866+
28572867
fn parallel_fu_kind_for_slot(slot: &PipeSlot) -> Option<FuKind> {
28582868
match slot.class {
2869+
InstrClass::FloatingPoint if is_float_memory_slot(slot) => Some(FuKind::Lsu),
28592870
InstrClass::Alu | InstrClass::Multiply | InstrClass::Divide | InstrClass::FloatingPoint => {
28602871
FuKind::from_class(slot.class)
28612872
}
@@ -2885,7 +2896,9 @@ fn parallel_fu_occupancy(state: &PipelineSimState, kind: FuKind) -> usize {
28852896
}
28862897

28872898
fn is_memory_slot(slot: &PipeSlot) -> bool {
2888-
!slot.is_bubble && matches!(slot.class, InstrClass::Load | InstrClass::Store)
2899+
!slot.is_bubble
2900+
&& (matches!(slot.class, InstrClass::Load | InstrClass::Store)
2901+
|| is_float_memory_slot(slot))
28892902
}
28902903

28912904
fn lsu_dispatch_blocked_by_older_memory(state: &PipelineSimState) -> bool {

‎tests/support/ui_pipeline_sim.rs‎

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1667,6 +1667,61 @@ fn f0_result_is_forwarded_like_any_float_register() {
16671667
assert_eq!(cpu_pipe.read(10), 0x12345678);
16681668
}
16691669

1670+
#[test]
1671+
fn parallel_fu_mode_sends_float_loads_and_stores_through_mem() {
1672+
// flw/fsw are FloatingPoint by class; they used to go from the FPU
1673+
// straight to WB, so the load read nothing and the store wrote nothing.
1674+
let asm = r#"
1675+
.data
1676+
tdat:
1677+
.word 0xbf800000
1678+
.word 0x40000000
1679+
.word 0
1680+
.word 0
1681+
.word 0
1682+
.word 0
1683+
.text
1684+
la a1, tdat
1685+
flw f1, 4(a1)
1686+
fsw f1, 20(a1)
1687+
lw a0, 20(a1)
1688+
flw f2, 0(a1)
1689+
fadd.s f3, f1, f2
1690+
fmv.x.w a2, f3
1691+
halt
1692+
"#;
1693+
let (_, cpu_seq, _) = run_sequential(asm);
1694+
let mut cpu = Cpu::default();
1695+
let mut mem = CacheController::new(
1696+
CacheConfig::default(),
1697+
CacheConfig::default(),
1698+
vec![],
1699+
0x4000,
1700+
);
1701+
let mut console = Console::default();
1702+
let cpi = CpiConfig::default();
1703+
let mut state = PipelineSimState::new();
1704+
state.mode = crate::falcon::pipeline::PipelineMode::FunctionalUnits;
1705+
mem.bypass = true;
1706+
load_program_into_mem(asm, &mut cpu, &mut mem);
1707+
state.reset_stages(0);
1708+
for _ in 0..1024 {
1709+
pipeline_tick(&mut state, &mut cpu, &mut mem, &cpi, &mut console);
1710+
if state.halted || state.faulted {
1711+
break;
1712+
}
1713+
}
1714+
// 2.0 stored and reloaded; 2.0 + (-1.0) = 1.0.
1715+
assert_eq!(
1716+
[cpu_seq.read(10), cpu_seq.read(12)],
1717+
[0x4000_0000, 0x3F80_0000]
1718+
);
1719+
assert_eq!(
1720+
[cpu.read(10), cpu.read(12)],
1721+
[cpu_seq.read(10), cpu_seq.read(12)]
1722+
);
1723+
}
1724+
16701725
#[test]
16711726
fn branch_after_two_loads_matches_sequential_behavior() {
16721727
let asm = r#"

0 commit comments

Comments
 (0)