156 lines
4.9 KiB
Rust
156 lines
4.9 KiB
Rust
// SPDX-License-Identifier: LGPL-3.0-or-later
|
|
// See Notices.txt for copyright information
|
|
|
|
use cpu::{
|
|
config::{CpuConfig, UnitConfig},
|
|
instruction::{AddSubMOp, LogicalMOp, MOp, MOpDestReg, MOpRegNum, OutputIntegerMode},
|
|
reg_alloc::{reg_alloc, FetchedDecodedMOp},
|
|
register::{FlagsMode, PRegFlagsPowerISA},
|
|
unit::{GlobalState, UnitKind},
|
|
};
|
|
use fayalite::{
|
|
assert_export_firrtl,
|
|
firrtl::ExportOptions,
|
|
prelude::*,
|
|
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
|
|
util::RcWriter,
|
|
};
|
|
use std::num::NonZeroUsize;
|
|
|
|
#[hdl]
|
|
#[test]
|
|
fn test_reg_alloc() {
|
|
let _n = SourceLocation::normalize_files_for_tests();
|
|
let mut config = CpuConfig::new(
|
|
vec![
|
|
UnitConfig::new(UnitKind::AluBranch),
|
|
UnitConfig::new(UnitKind::AluBranch),
|
|
],
|
|
NonZeroUsize::new(20).unwrap(),
|
|
);
|
|
config.fetch_width = NonZeroUsize::new(2).unwrap();
|
|
let m = reg_alloc(&config);
|
|
let mut sim = Simulation::new(m);
|
|
let mut writer = RcWriter::default();
|
|
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
|
let fetch_decode_interface = sim.io().fetch_decode_interface;
|
|
sim.write_clock(sim.io().cd.clk, false);
|
|
sim.write_reset(sim.io().cd.rst, true);
|
|
sim.write_bool(fetch_decode_interface.fetch_decode_special_op.ready, true);
|
|
sim.write(
|
|
sim.io().global_state,
|
|
#[hdl]
|
|
GlobalState {
|
|
flags_mode: FlagsMode.PowerISA(
|
|
#[hdl]
|
|
PRegFlagsPowerISA {},
|
|
),
|
|
},
|
|
);
|
|
let insns_init: [Expr<MOp>; 4] = std::array::from_fn(|i| {
|
|
AddSubMOp::add_sub_i(
|
|
#[hdl]
|
|
MOpDestReg {
|
|
normal_regs: #[hdl]
|
|
[
|
|
#[hdl]
|
|
MOpRegNum { value: i as u8 + 1 },
|
|
MOpRegNum::const_zero(),
|
|
],
|
|
flag_regs: #[hdl]
|
|
[HdlSome(()), HdlNone()],
|
|
},
|
|
[0u8; 2],
|
|
0x12345678u32.cast_to_static(),
|
|
OutputIntegerMode.DupLow32(),
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
)
|
|
});
|
|
let insns_loop = [
|
|
AddSubMOp::add_sub(
|
|
#[hdl]
|
|
MOpDestReg {
|
|
normal_regs: #[hdl]
|
|
[
|
|
#[hdl]
|
|
MOpRegNum { value: 1u8 },
|
|
MOpRegNum::const_zero(),
|
|
],
|
|
flag_regs: #[hdl]
|
|
[HdlSome(()), HdlNone()],
|
|
},
|
|
[1u8, 0, 0],
|
|
1.cast_to_static(),
|
|
OutputIntegerMode.Full64(),
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
),
|
|
LogicalMOp::logical(
|
|
#[hdl]
|
|
MOpDestReg {
|
|
normal_regs: [
|
|
#[hdl]
|
|
MOpRegNum { value: 2u8 },
|
|
MOpRegNum::const_zero(),
|
|
],
|
|
flag_regs: [HdlNone(), HdlSome(())],
|
|
},
|
|
[2u8, 4u8],
|
|
0.cast_to_static(),
|
|
OutputIntegerMode.Full64(),
|
|
0b0110_hdl_u4,
|
|
),
|
|
];
|
|
let insns = insns_init.into_iter().chain(insns_loop.into_iter().cycle());
|
|
let mut insn_index = 0;
|
|
for cycle in 0..20 {
|
|
for fetch_index in 0..config.fetch_width.get() {
|
|
let mop = insns.clone().nth(insn_index).unwrap();
|
|
sim.write(
|
|
fetch_decode_interface.decoded_insns[fetch_index].data,
|
|
HdlSome(
|
|
#[hdl]
|
|
FetchedDecodedMOp {
|
|
mop,
|
|
is_unrelated_pc: insn_index == 0,
|
|
pc: 0x1000u64 + 4 * insn_index as u64,
|
|
},
|
|
),
|
|
);
|
|
insn_index += 1;
|
|
}
|
|
if cycle == 0 {
|
|
insn_index = 0;
|
|
}
|
|
sim.advance_time(SimDuration::from_nanos(500));
|
|
sim.write_clock(sim.io().cd.clk, true);
|
|
sim.advance_time(SimDuration::from_nanos(500));
|
|
sim.write_clock(sim.io().cd.clk, false);
|
|
sim.write_reset(sim.io().cd.rst, false);
|
|
}
|
|
// FIXME: vcd is just whatever reg_alloc does now, which isn't known to be correct
|
|
let vcd = String::from_utf8(writer.take()).unwrap();
|
|
println!("####### VCD:\n{vcd}\n#######");
|
|
if vcd != include_str!("expected/reg_alloc.vcd") {
|
|
panic!();
|
|
}
|
|
// #[rustfmt::skip] // work around https://github.com/rust-lang/rustfmt/issues/6161
|
|
// assert_export_firrtl! {
|
|
// m =>
|
|
// options: ExportOptions {
|
|
// simplify_enums: None,
|
|
// ..ExportOptions::default()
|
|
// },
|
|
// "/test/reg_alloc.fir": "",
|
|
// };
|
|
// let sim_debug = format!("{sim:#?}");
|
|
// println!("#######\n{sim_debug}\n#######");
|
|
// if sim_debug != include_str!("expected/reg_alloc.txt") {
|
|
// panic!();
|
|
// }
|
|
}
|