runs instructions that read other instructions' outputs
All checks were successful
/ deps (push) Successful in 16s
/ test (push) Successful in 25m49s

This commit is contained in:
Jacob Lifshay 2025-02-23 19:51:45 -08:00
parent 3bd5c77a3f
commit 5b15f4a6b4
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
4 changed files with 29247 additions and 18604 deletions

View file

@ -415,6 +415,16 @@ pub fn reg_alloc(config: &CpuConfig) {
.element() .element()
.HdlNone(), .HdlNone(),
); );
connect(
unit_forwarding_info.unit_reg_frees[unit_index],
HdlOption::map(
ReadyValid::firing_data(unit_free_regs_tracker.free_in[0]),
|value| {
#[hdl]
UnitOutRegNum::<_> { value }
},
),
);
#[hdl] #[hdl]
if let HdlSome(output) = unit_to_reg_alloc.output { if let HdlSome(output) = unit_to_reg_alloc.output {
#[hdl] #[hdl]

View file

@ -20,6 +20,7 @@ use std::marker::PhantomData;
#[hdl] #[hdl]
pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> { pub struct UnitForwardingInfo<UnitNumWidth: Size, OutRegNumWidth: Size, UnitCount: Size> {
pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>, pub unit_output_writes: ArrayType<HdlOption<UnitOutputWrite<OutRegNumWidth>>, UnitCount>,
pub unit_reg_frees: ArrayType<HdlOption<UnitOutRegNum<OutRegNumWidth>>, UnitCount>,
pub _phantom: PhantomData<UnitNumWidth>, pub _phantom: PhantomData<UnitNumWidth>,
} }
@ -277,7 +278,12 @@ pub fn unit_base<
HdlOption::is_some(in_flight_ops_summary.empty_op_index), HdlOption::is_some(in_flight_ops_summary.empty_op_index),
); );
let unit_output_writes = unit_to_reg_alloc.unit_forwarding_info.unit_output_writes; #[hdl]
let UnitForwardingInfo::<_, _, _> {
unit_output_writes,
unit_reg_frees,
_phantom: _,
} = unit_to_reg_alloc.unit_forwarding_info;
#[hdl] #[hdl]
let read_src_regs = wire(mop_ty.src_regs_ty()); let read_src_regs = wire(mop_ty.src_regs_ty());
connect( connect(
@ -287,6 +293,26 @@ pub fn unit_base<
#[hdl] #[hdl]
let read_src_values = wire(); let read_src_values = wire();
connect(read_src_values, [PRegValue::zeroed(); COMMON_MOP_SRC_LEN]); connect(read_src_values, [PRegValue::zeroed(); COMMON_MOP_SRC_LEN]);
#[hdl]
let input_src_regs = wire(mop_ty.src_regs_ty());
connect(
input_src_regs,
repeat(config.p_reg_num().const_zero().cast_to_bits(), ConstUsize),
);
#[hdl]
let input_src_regs_valid = wire();
connect(input_src_regs_valid, [true; COMMON_MOP_SRC_LEN]);
let mut unit_output_regs_valid: Vec<MemBuilder<Bool>> = (0..Expr::ty(unit_output_writes).len())
.map(|unit_index| {
let mut mem = memory_with_loc(
&format!("unit_{unit_index}_output_regs_valid"),
Bool,
SourceLocation::caller(),
);
mem.depth(1 << config.out_reg_num_width);
mem
})
.collect();
for unit_index in 0..Expr::ty(unit_output_writes).len() { for unit_index in 0..Expr::ty(unit_output_writes).len() {
let mut unit_output_regs = memory_with_loc( let mut unit_output_regs = memory_with_loc(
&format!("unit_{unit_index}_output_regs"), &format!("unit_{unit_index}_output_regs"),
@ -308,17 +334,60 @@ pub fn unit_base<
} }
} }
for src_index in 0..COMMON_MOP_SRC_LEN {
let read_port = unit_output_regs_valid[unit_index].new_read_port();
let p_reg_num = input_src_regs[src_index].cast_bits_to(config.p_reg_num());
connect_any(read_port.addr, p_reg_num.unit_out_reg.value);
connect(read_port.en, false);
connect(read_port.clk, cd.clk);
#[hdl]
if UnitNum::is_index(p_reg_num.unit_num, unit_index) {
connect(read_port.en, true);
connect(input_src_regs_valid[src_index], read_port.data);
}
}
let write_port = unit_output_regs.new_write_port(); let write_port = unit_output_regs.new_write_port();
connect_any(write_port.addr, 0u8); connect_any(write_port.addr, 0u8);
connect(write_port.en, false); connect(write_port.en, false);
connect(write_port.clk, cd.clk); connect(write_port.clk, cd.clk);
connect(write_port.data, PRegValue::zeroed()); connect(write_port.data, PRegValue::zeroed());
connect(write_port.mask, splat_mask(PRegValue, true.to_expr())); connect(write_port.mask, splat_mask(PRegValue, true.to_expr()));
let ready_write_port = unit_output_regs_valid[unit_index].new_write_port();
connect_any(ready_write_port.addr, 0u8);
connect(ready_write_port.en, false);
connect(ready_write_port.clk, cd.clk);
connect(ready_write_port.data, true);
connect(ready_write_port.mask, true);
#[hdl] #[hdl]
if let HdlSome(unit_output_write) = unit_output_writes[unit_index] { if let HdlSome(unit_output_write) = unit_output_writes[unit_index] {
connect_any(write_port.addr, unit_output_write.which.value); connect_any(write_port.addr, unit_output_write.which.value);
connect(write_port.data, unit_output_write.value); connect(write_port.data, unit_output_write.value);
connect(write_port.en, true); connect(write_port.en, true);
connect_any(ready_write_port.addr, unit_output_write.which.value);
connect(ready_write_port.en, true);
let p_reg_num = #[hdl]
PRegNum::<_, _> {
unit_num: config.unit_num().from_index(unit_index),
unit_out_reg: unit_output_write.which,
};
for src_index in 0..COMMON_MOP_SRC_LEN {
#[hdl]
if input_src_regs[src_index].cmp_eq(p_reg_num.cast_to_bits()) {
connect(input_src_regs_valid[src_index], true);
}
}
}
let free_write_port = unit_output_regs_valid[unit_index].new_write_port();
connect_any(free_write_port.addr, 0u8);
connect(free_write_port.en, false);
connect(free_write_port.clk, cd.clk);
connect(free_write_port.data, false);
connect(free_write_port.mask, true);
#[hdl]
if let HdlSome(unit_reg_free) = unit_reg_frees[unit_index] {
connect_any(free_write_port.addr, unit_reg_free.value);
connect(free_write_port.en, true);
} }
} }
@ -364,16 +433,8 @@ pub fn unit_base<
SourceLocation::caller(), SourceLocation::caller(),
StaticType::TYPE, StaticType::TYPE,
); );
for src_index in 0..COMMON_MOP_SRC_LEN { connect(src_ready_flags, input_src_regs_valid);
connect( connect(input_src_regs, input_mop_src_regs);
src_ready_flags[src_index],
config
.p_reg_num()
.const_zero()
.cast_to_bits()
.cmp_eq(input_mop_src_regs[src_index]),
);
}
#[hdl] #[hdl]
if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome( if unit_to_reg_alloc.cancel_input.cmp_ne(HdlSome(
#[hdl] #[hdl]
@ -494,8 +555,11 @@ pub fn unit_base<
#[hdl] #[hdl]
if !in_flight_op_canceling[in_flight_op_index] { if !in_flight_op_canceling[in_flight_op_index] {
#[hdl] #[hdl]
if let InFlightOpState::Running = state { match state {
connect(unit_to_reg_alloc.output, HdlSome(unit_output)); InFlightOpState::Running | InFlightOpState::Ready => {
connect(unit_to_reg_alloc.output, HdlSome(unit_output))
}
InFlightOpState::CanceledAndRunning => {}
} }
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -47,12 +47,41 @@ fn test_reg_alloc() {
), ),
}, },
); );
sim.write( let insns = std::array::from_fn::<_, 4, _>(|i| {
fetch_decode_interface.decoded_insns[0].data, MOp.AluBranch(MOp.AluBranch.AddSubI(
HdlSome(
#[hdl] #[hdl]
FetchedDecodedMOp { AddSubMOp {
mop: MOp.AluBranch(MOp.AluBranch.AddSub( alu_common: #[hdl]
AluCommonMOp {
common: CommonMOp::new(
0_hdl_u0,
#[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(SInt[COMMON_MOP_2_IMM_WIDTH]),
),
output_integer_mode: OutputIntegerMode.DupLow32(),
},
invert_src0: false,
src1_is_carry_in: false,
invert_carry_in: false,
add_pc: false,
},
))
})
.into_iter()
.chain(
[
MOp.AluBranch(MOp.AluBranch.AddSub(
#[hdl] #[hdl]
AddSubMOp { AddSubMOp {
alu_common: #[hdl] alu_common: #[hdl]
@ -70,28 +99,18 @@ fn test_reg_alloc() {
flag_regs: #[hdl] flag_regs: #[hdl]
[HdlSome(()), HdlNone()], [HdlSome(()), HdlNone()],
}, },
[2u8, 3u8, 4u8], [1u8, 0, 0],
0x1234.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]), 1.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]),
), ),
output_integer_mode: OutputIntegerMode.Full64(), output_integer_mode: OutputIntegerMode.Full64(),
}, },
invert_src0: true, invert_src0: false,
src1_is_carry_in: true, src1_is_carry_in: false,
invert_carry_in: true, invert_carry_in: false,
add_pc: true, add_pc: false,
}, },
)), )),
is_unrelated_pc: true, MOp.AluBranch(MOp.AluBranch.Logical(
pc: 0x1000_hdl_u64,
},
),
);
sim.write(
fetch_decode_interface.decoded_insns[1].data,
HdlSome(
#[hdl]
FetchedDecodedMOp {
mop: MOp.AluBranch(MOp.AluBranch.Logical(
#[hdl] #[hdl]
LogicalMOp { LogicalMOp {
alu_common: #[hdl] alu_common: #[hdl]
@ -107,7 +126,7 @@ fn test_reg_alloc() {
], ],
flag_regs: [HdlNone(), HdlSome(())], flag_regs: [HdlNone(), HdlSome(())],
}, },
[3u8, 4u8], [2u8, 4u8],
SInt[COMMON_MOP_2_IMM_WIDTH].zero(), SInt[COMMON_MOP_2_IMM_WIDTH].zero(),
), ),
output_integer_mode: OutputIntegerMode.Full64(), output_integer_mode: OutputIntegerMode.Full64(),
@ -115,12 +134,30 @@ fn test_reg_alloc() {
lut: 0b0110_hdl_u4, lut: 0b0110_hdl_u4,
}, },
)), )),
is_unrelated_pc: false, ]
pc: 0x1004_hdl_u64, .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,
}, },
), ),
); );
for cycle in 0..20 { insn_index += 1;
}
if cycle == 0 {
insn_index = 0;
}
sim.advance_time(SimDuration::from_nanos(500)); sim.advance_time(SimDuration::from_nanos(500));
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));