reg_alloc: add writes to rename table
All checks were successful
/ deps (push) Successful in 15s
/ test (push) Successful in 26m20s

This commit is contained in:
Jacob Lifshay 2025-02-11 19:19:06 -08:00
parent 64566f718f
commit 1084278f34
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
4 changed files with 10856 additions and 8375 deletions

View file

@ -2,7 +2,7 @@
// See Notices.txt for copyright information // See Notices.txt for copyright information
use crate::{unit::UnitMOp, util::range_u32_len}; use crate::{unit::UnitMOp, util::range_u32_len};
use fayalite::{expr::ops::ArrayLiteral, intern::Interned, prelude::*}; use fayalite::{expr::ops::ArrayLiteral, intern::Interned, prelude::*};
use std::{marker::PhantomData, ops::Range}; use std::{fmt, marker::PhantomData, ops::Range};
pub mod power_isa; pub mod power_isa;
@ -668,6 +668,29 @@ pub struct MOpDestReg {
pub flag_regs: Array<HdlOption<()>, { range_u32_len(&MOpRegNum::FLAG_REG_NUMS) }>, pub flag_regs: Array<HdlOption<()>, { range_u32_len(&MOpRegNum::FLAG_REG_NUMS) }>,
} }
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug)]
pub enum RenameTableName {
/// the large rename table for normal registers (has less read/write ports)
Normal,
/// a special small rename table (for flags and stuff, since it has more read/write ports)
Special,
}
impl RenameTableName {
pub const fn reg_range(self) -> std::ops::Range<u32> {
match self {
Self::Normal => MOpRegNum::NORMAL_REG_NUMS,
Self::Special => MOpRegNum::SPECIAL_REG_NUMS,
}
}
pub const fn as_str(self) -> &'static str {
match self {
Self::Normal => "rename_table_normal",
Self::Special => "rename_table_special",
}
}
}
#[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)] #[derive(Copy, Clone, Eq, PartialEq, Hash, Debug)]
pub enum MOpDestRegKind { pub enum MOpDestRegKind {
NormalReg { NormalReg {
@ -682,6 +705,69 @@ pub enum MOpDestRegKind {
}, },
} }
#[derive(Copy, Clone, Debug)]
pub struct MOpDestRegName {
base_name: &'static str,
index: usize,
reg_num: Option<u32>,
}
impl fmt::Display for MOpDestRegName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let Self {
base_name,
index,
reg_num,
} = self;
write!(f, "{base_name}{index}")?;
if let Some(reg_num) = reg_num {
write!(f, "_r{reg_num:02X}")?;
}
Ok(())
}
}
impl MOpDestRegKind {
pub const fn reg_range(self) -> std::ops::Range<u32> {
match self {
Self::NormalReg { .. } => MOpRegNum::NORMAL_REG_NUMS,
Self::FlagReg { .. } => MOpRegNum::FLAG_REG_NUMS,
}
}
pub const fn rename_table_names(self) -> &'static [RenameTableName] {
match self {
Self::NormalReg { .. } => &[RenameTableName::Normal, RenameTableName::Special],
Self::FlagReg { .. } => &[RenameTableName::Special],
}
}
pub fn fixed_reg_num(self) -> Option<u32> {
match self {
Self::NormalReg { dest_reg_index: _ } => None,
Self::FlagReg {
flag_reg_index: _,
reg_num,
} => Some(reg_num),
}
}
pub fn reg_name(self) -> MOpDestRegName {
match self {
Self::NormalReg { dest_reg_index } => MOpDestRegName {
base_name: "dest",
index: dest_reg_index,
reg_num: None,
},
Self::FlagReg {
flag_reg_index,
reg_num,
} => MOpDestRegName {
base_name: "flag",
index: flag_reg_index,
reg_num: Some(reg_num),
},
}
}
}
impl MOpDestReg { impl MOpDestReg {
pub const NORMAL_REG_COUNT: usize = 2; pub const NORMAL_REG_COUNT: usize = 2;
pub const REG_COUNT: usize = Self::NORMAL_REG_COUNT + range_u32_len(&MOpRegNum::FLAG_REG_NUMS); pub const REG_COUNT: usize = Self::NORMAL_REG_COUNT + range_u32_len(&MOpRegNum::FLAG_REG_NUMS);

View file

@ -3,17 +3,22 @@
use crate::{ use crate::{
config::CpuConfig, config::CpuConfig,
instruction::{ instruction::{
MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, UnitOutRegNum, COMMON_MOP_SRC_LEN, MOp, MOpDestReg, MOpRegNum, MOpTrait, PRegNum, RenameTableName, UnitOutRegNum,
COMMON_MOP_SRC_LEN,
}, },
unit::{TrapData, UnitTrait}, unit::{TrapData, UnitTrait},
util::tree_reduce::tree_reduce_with_state, util::tree_reduce::tree_reduce_with_state,
}; };
use fayalite::{ use fayalite::{
module::{instance_with_loc, wire_with_loc}, memory::{splat_mask, WriteStruct},
module::{instance_with_loc, memory_with_loc, wire_with_loc},
prelude::*, prelude::*,
util::ready_valid::ReadyValid, util::ready_valid::ReadyValid,
}; };
use std::num::NonZeroUsize; use std::{
collections::{BTreeMap, VecDeque},
num::NonZeroUsize,
};
pub mod unit_free_regs_tracker; pub mod unit_free_regs_tracker;
@ -55,15 +60,23 @@ pub fn reg_alloc(config: &CpuConfig) {
); );
// TODO: finish // TODO: finish
// the large rename table for normal registers (has less read/write ports) let mut rename_table_mems = BTreeMap::<RenameTableName, MemBuilder<_>>::new();
#[hdl]
let mut rename_table_normal_mem = memory(config.p_reg_num());
rename_table_normal_mem.depth(MOpRegNum::NORMAL_REG_NUMS.len());
// a special small rename table (for flags and stuff, since it has more read/write ports) for reg_kind in MOpDestReg::REG_KINDS {
#[hdl] for &rename_table_name in reg_kind.rename_table_names() {
let mut rename_table_special_mem = memory(config.p_reg_num()); rename_table_mems
rename_table_special_mem.depth(MOpRegNum::SPECIAL_REG_NUMS.len()); .entry(rename_table_name)
.or_insert_with(|| {
let mut mem = memory_with_loc(
&format!("{}_mem", rename_table_name.as_str()),
config.p_reg_num(),
SourceLocation::caller(),
);
mem.depth(rename_table_name.reg_range().len());
mem
});
}
}
#[hdl] #[hdl]
let available_units = let available_units =
@ -92,29 +105,28 @@ pub fn reg_alloc(config: &CpuConfig) {
struct RenameTableReadPort<T> { struct RenameTableReadPort<T> {
addr: MOpRegNum, addr: MOpRegNum,
#[hdl(flip)] #[hdl(flip)]
data: HdlOption<T>, data: T,
} }
let make_rename_table_read_port = let rename_table_read_ports: [_; COMMON_MOP_SRC_LEN] = std::array::from_fn(|src_index| {
|mem: &mut MemBuilder<_>, let wire = wire_with_loc(
reg_range: std::ops::Range<u32>, &format!("rename_{fetch_index}_src_{src_index}"),
src_index: usize, SourceLocation::caller(),
table_name: &str| { RenameTableReadPort[config.p_reg_num()],
);
connect(wire.addr, MOpRegNum::const_zero());
connect(wire.data, config.p_reg_num().const_zero());
for (&rename_table_name, mem) in &mut rename_table_mems {
let table_name = rename_table_name.as_str();
let read_port = mem.new_read_port(); let read_port = mem.new_read_port();
connect(read_port.clk, cd.clk); connect(read_port.clk, cd.clk);
connect_any(read_port.addr, 0u8); connect_any(read_port.addr, 0u8);
connect(read_port.en, false); connect(read_port.en, false);
let wire = wire_with_loc( let reg_range = rename_table_name.reg_range();
&format!("{table_name}_{fetch_index}_src_{src_index}"),
SourceLocation::caller(),
RenameTableReadPort[config.p_reg_num()],
);
connect(wire.addr, MOpRegNum::const_zero());
connect(wire.data, Expr::ty(wire.data).HdlNone());
#[hdl] #[hdl]
if wire.addr.value.cmp_ge(reg_range.start) & wire.addr.value.cmp_lt(reg_range.end) { if wire.addr.value.cmp_ge(reg_range.start) & wire.addr.value.cmp_lt(reg_range.end) {
connect_any(read_port.addr, wire.addr.value - reg_range.start); connect_any(read_port.addr, wire.addr.value - reg_range.start);
connect(read_port.en, true); connect(read_port.en, true);
connect(wire.data, HdlSome(read_port.data)); connect(wire.data, read_port.data);
for prev_fetch_index in 0..fetch_index { for prev_fetch_index in 0..fetch_index {
#[hdl] #[hdl]
if let HdlSome(decoded_insn) = if let HdlSome(decoded_insn) =
@ -125,36 +137,55 @@ pub fn reg_alloc(config: &CpuConfig) {
renamed_mops_out_reg[prev_fetch_index] renamed_mops_out_reg[prev_fetch_index]
{ {
let dest_reg = MOpTrait::dest_reg(decoded_insn.mop); let dest_reg = MOpTrait::dest_reg(decoded_insn.mop);
for dest_reg in MOpDestReg::regs(dest_reg) { for (dest_reg, reg_kind) in MOpDestReg::regs(dest_reg)
#[hdl] .into_iter()
if dest_reg.value.cmp_eq(wire.addr.value) { .zip(MOpDestReg::REG_KINDS)
connect(wire.data, HdlSome(renamed_mop_out_reg)); {
if reg_kind.rename_table_names().contains(&rename_table_name) {
#[hdl]
if dest_reg.value.cmp_eq(wire.addr.value) {
connect(wire.data, renamed_mop_out_reg);
}
} }
} }
} }
} }
} }
} }
wire }
}; wire
let rename_table_normal_read_ports: [_; COMMON_MOP_SRC_LEN] = });
std::array::from_fn(|src_index| { let mut rename_table_write_ports = BTreeMap::<RenameTableName, VecDeque<_>>::new();
make_rename_table_read_port( for reg_kind in MOpDestReg::REG_KINDS {
&mut rename_table_normal_mem, for &rename_table_name in reg_kind.rename_table_names() {
MOpRegNum::NORMAL_REG_NUMS, let mem = rename_table_mems
src_index, .get_mut(&rename_table_name)
"rename_table_normal", .expect("already added all RenameTableName values");
) let write_ports = rename_table_write_ports
}); .entry(rename_table_name)
let rename_table_special_read_ports: [_; COMMON_MOP_SRC_LEN] = .or_default();
std::array::from_fn(|src_index| { let write_port_ = mem.new_write_port();
make_rename_table_read_port( let table_name = rename_table_name.as_str();
&mut rename_table_special_mem, let write_port = wire_with_loc(
MOpRegNum::FLAG_REG_NUMS, &format!("{table_name}_{fetch_index}_{}", reg_kind.reg_name()),
src_index, SourceLocation::caller(),
"rename_table_special", Expr::ty(write_port_),
) );
}); connect(write_port_, write_port);
write_ports.push_back(write_port);
connect_any(
write_port,
#[hdl]
WriteStruct::<_, _> {
addr: 0_hdl_u0,
en: false,
clk: cd.clk,
data: Expr::ty(write_port.data).uninit(),
mask: splat_mask(config.p_reg_num(), true.to_expr()),
},
);
}
}
#[hdl] #[hdl]
if let HdlSome(decoded_insn) = fetch_decode_interface.decoded_insns[fetch_index].data { if let HdlSome(decoded_insn) = fetch_decode_interface.decoded_insns[fetch_index].data {
connect( connect(
@ -171,31 +202,41 @@ pub fn reg_alloc(config: &CpuConfig) {
renamed_mop_out_reg.unit_out_reg, renamed_mop_out_reg.unit_out_reg,
config.p_reg_num_width(), config.p_reg_num_width(),
&mut |src_reg, src_index| { &mut |src_reg, src_index| {
let src_reg = #[hdl] connect(
MOpRegNum { value: src_reg }; rename_table_read_ports[src_index].addr,
let renamed_src_reg = wire_with_loc( #[hdl]
&format!("renamed_src_reg_{fetch_index}_{src_index}"), MOpRegNum { value: src_reg },
SourceLocation::caller(),
config.p_reg_num(),
); );
connect(rename_table_normal_read_ports[src_index].addr, src_reg); rename_table_read_ports[src_index].data.cast_to_bits()
connect(rename_table_special_read_ports[src_index].addr, src_reg);
#[hdl]
if let HdlSome(v) = rename_table_normal_read_ports[src_index].data {
connect(renamed_src_reg, v);
} else if let HdlSome(v) =
rename_table_special_read_ports[src_index].data
{
connect(renamed_src_reg, v);
} else {
connect(renamed_src_reg, config.p_reg_num().const_zero());
}
renamed_src_reg.cast_to_bits()
}, },
)), )),
); );
// TODO: write dest_reg to rename table for (reg, reg_kind) in MOpDestReg::regs(dest_reg)
// rename_table_mem.new_write_port() .into_iter()
.zip(MOpDestReg::REG_KINDS)
{
for &rename_table_name in reg_kind.rename_table_names() {
let Some(write_ports) =
rename_table_write_ports.get_mut(&rename_table_name)
else {
unreachable!();
};
let Some(write_port) = write_ports.pop_front() else {
unreachable!();
};
let reg_range = rename_table_name.reg_range();
#[hdl]
if reg.value.cmp_ge(reg_range.start) & reg.value.cmp_lt(reg_range.end) {
connect(write_port.data, renamed_mop_out_reg);
if let Some(fixed_reg_num) = reg_kind.fixed_reg_num() {
connect_any(write_port.addr, fixed_reg_num - reg_range.start);
} else {
connect_any(write_port.addr, reg.value - reg_range.start);
}
connect(write_port.en, true);
}
}
}
} }
} }
connect( connect(

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff