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
use crate::{unit::UnitMOp, util::range_u32_len};
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;
@ -668,6 +668,29 @@ pub struct MOpDestReg {
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)]
pub enum MOpDestRegKind {
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 {
pub const NORMAL_REG_COUNT: usize = 2;
pub const REG_COUNT: usize = Self::NORMAL_REG_COUNT + range_u32_len(&MOpRegNum::FLAG_REG_NUMS);

View file

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff