reduce the number of wires to have one per form/field pair instead of one per insn/field pair
All checks were successful
/ test (pull_request) Successful in 30m9s

This commit is contained in:
Jacob Lifshay 2026-01-26 16:11:03 -08:00
parent 1db65ae753
commit faa8dde774
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
2 changed files with 73168 additions and 130361 deletions

View file

@ -20,14 +20,9 @@ use crate::{
array_vec::{ArrayVec, Length},
},
};
use fayalite::{
int::{BoolOrIntType, UIntInRange},
module::wire_with_loc,
prelude::*,
ty::StaticType,
};
use fayalite::{int::UIntInRange, module::wire_with_loc, prelude::*, ty::StaticType};
use std::{
collections::{BTreeMap, btree_map::Entry},
collections::{BTreeMap, HashMap, hash_map::Entry},
ops::RangeInclusive,
};
@ -136,7 +131,7 @@ const VSX_MNEMONICS: &[&str] = &[
];
#[derive(Debug)]
struct DecodeState {
struct DecodeState<'a> {
mnemonic: &'static str,
arguments: Option<&'static str>,
conditions: Option<&'static str>,
@ -147,6 +142,7 @@ struct DecodeState {
first_input: Expr<UInt<32>>,
second_input: Expr<HdlOption<UInt<32>>>,
second_input_used: Expr<Bool>,
field_wires: &'a mut HashMap<String, HashMap<Expr<UInt>, Expr<UInt>>>,
}
trait FieldSet {
@ -320,7 +316,7 @@ fn cr_bit_flag_index(
(MOpRegNum::power_isa_cr_reg(field_num), flag_index)
}
impl DecodeState {
impl DecodeState<'_> {
fn form(&self) -> &'static str {
let mut title_words = self
.header
@ -399,6 +395,26 @@ impl DecodeState {
(var.trim(), value.trim())
})
}
fn get_field_wire(&mut self, value: Expr<UInt>, name: &str) -> Expr<UInt> {
let form = self.form();
let width = value.ty().width();
let wire_name =
format!("{form}_{name}_{width}").replace(|c: char| !c.is_ascii_alphanumeric(), "_");
match self
.field_wires
.entry(wire_name.clone())
.or_default()
.entry(value)
{
Entry::Vacant(entry) => {
let wire = wire_with_loc(&wire_name, SourceLocation::caller(), value.ty());
connect(wire, value);
entry.insert(wire);
wire
}
Entry::Occupied(entry) => *entry.get(),
}
}
#[hdl]
fn decode_word(
&mut self,
@ -478,27 +494,19 @@ impl DecodeState {
};
field_pieces.filled_pieces.push(field);
if field_pieces.filled_pieces.len() == field_pieces.piece_count {
let wire = wire_with_loc(
&format!("{}_{name}", self.mnemonic)
.replace(|c: char| !c.is_ascii_alphanumeric(), "_"),
SourceLocation::caller(),
UInt[field_pieces
.filled_pieces
.iter()
.map(|v| v.ty().width())
.sum::<usize>()],
);
let filled_pieces = std::mem::take(&mut field_pieces.filled_pieces);
// filled_pieces are in lsb to msb order
let mut filled_pieces = field_pieces.filled_pieces.drain(..);
let mut filled_pieces = filled_pieces.into_iter();
let Some(mut value) = filled_pieces.next() else {
unreachable!();
};
let mut shift = value.ty().width();
let mut value_width = value.ty().width();
for next_value in filled_pieces {
value = value | (next_value << shift);
shift += next_value.ty().width();
value = value | (next_value << value_width);
value_width += next_value.ty().width();
}
connect(wire, value);
value = value.cast_to(UInt[value_width]);
let wire = self.get_field_wire(value, name);
fields.insert(name, wire);
}
} else {
@ -523,8 +531,8 @@ impl DecodeState {
let mut f = Some(f);
#[hdl]
#[track_caller]
fn run<FS: FieldSet, F: FnOnce(&mut DecodeState, FS)>(
this: &mut DecodeState,
fn run<'a, FS: FieldSet, F: FnOnce(&mut DecodeState<'a>, FS)>(
this: &mut DecodeState<'a>,
matches: Expr<Bool>,
fields: &mut BTreeMap<&str, Expr<UInt>>,
f: &mut Option<F>,
@ -2082,23 +2090,25 @@ impl DecodeState {
}
}
type DecodeFn = fn(&mut DecodeState);
type DecodeFn = fn(&mut DecodeState<'_>);
const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
(&["b", "ba", "bl", "bla"], DecodeState::decode_b_ba_bl_bla),
(&["b", "ba", "bl", "bla"], |state| {
DecodeState::decode_b_ba_bl_bla(state)
}),
(
&[
"bc", "bca", "bcl", "bcla", "bclr", "bclrl", "bcctr", "bcctrl", "bctar", "bctarl",
],
DecodeState::decode_bc_bclr_bcctr_bctar,
|state| DecodeState::decode_bc_bclr_bcctr_bctar(state),
),
(
&[
"crand", "crnand", "cror", "crxor", "crnor", "creqv", "crandc", "crorc",
],
DecodeState::decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc,
|state| DecodeState::decode_crand_crnand_cror_crxor_crnor_creqv_crandc_crorc(state),
),
(&["mcrf"], DecodeState::decode_mcrf),
(&["mcrf"], |state| DecodeState::decode_mcrf(state)),
(&["sc", "scv"], |_state| {
// TODO
}),
@ -2108,14 +2118,14 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
"plha", "lhax", "lhau", "lhaux", "lwz", "plwz", "lwzx", "lwzu", "lwzux", "lwa", "plwa",
"lwax", "lwaux", "ld", "pld", "ldx", "ldu", "ldux",
],
DecodeState::decode_load_8_16_32_64_bit,
|state| DecodeState::decode_load_8_16_32_64_bit(state),
),
(
&[
"stb", "pstb", "stbx", "stbu", "stbux", "sth", "psth", "sthx", "sthu", "sthux", "stw",
"pstw", "stwx", "stwu", "stwux", "std", "pstd", "stdx", "stdu", "stdux",
],
DecodeState::decode_store_8_16_32_64_bit,
|state| DecodeState::decode_store_8_16_32_64_bit(state),
),
(&["lq", "plq", "stq", "pstq"], |_state| {
// TODO
@ -2132,43 +2142,46 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
(&["lswi", "lswx", "stswi", "stswx"], |_state| {
// load/store string are intentionally not implemented
}),
(&["addi", "paddi"], DecodeState::decode_addi_paddi),
(&["addis"], DecodeState::decode_addis),
(&["addpcis"], DecodeState::decode_addpcis),
(&["add", "add.", "addo", "addo."], DecodeState::decode_add),
(&["addic", "addic."], DecodeState::decode_addic),
(
&["subf", "subf.", "subfo", "subfo."],
DecodeState::decode_subf_subfc,
),
(&["subfic"], DecodeState::decode_subfic),
(
&["addc", "addc.", "addco", "addco."],
DecodeState::decode_addc,
),
(
&["subfc", "subfc.", "subfco", "subfco."],
DecodeState::decode_subf_subfc,
),
(
&["adde", "adde.", "addeo", "addeo."],
DecodeState::decode_adde,
),
(
&["subfe", "subfe.", "subfeo", "subfeo."],
DecodeState::decode_subfe,
),
(&["addi", "paddi"], |state| {
DecodeState::decode_addi_paddi(state)
}),
(&["addis"], |state| DecodeState::decode_addis(state)),
(&["addpcis"], |state| DecodeState::decode_addpcis(state)),
(&["add", "add.", "addo", "addo."], |state| {
DecodeState::decode_add(state)
}),
(&["addic", "addic."], |state| {
DecodeState::decode_addic(state)
}),
(&["subf", "subf.", "subfo", "subfo."], |state| {
DecodeState::decode_subf_subfc(state)
}),
(&["subfic"], |state| DecodeState::decode_subfic(state)),
(&["addc", "addc.", "addco", "addco."], |state| {
DecodeState::decode_addc(state)
}),
(&["subfc", "subfc.", "subfco", "subfco."], |state| {
DecodeState::decode_subf_subfc(state)
}),
(&["adde", "adde.", "addeo", "addeo."], |state| {
DecodeState::decode_adde(state)
}),
(&["subfe", "subfe.", "subfeo", "subfeo."], |state| {
DecodeState::decode_subfe(state)
}),
(
&[
"addme", "addme.", "addmeo", "addmeo.", "addze", "addze.", "addzeo", "addzeo.",
"subfme", "subfme.", "subfmeo", "subfmeo.", "subfze", "subfze.", "subfzeo", "subfzeo.",
],
DecodeState::decode_addme_subfme_addze_subfze,
|state| DecodeState::decode_addme_subfme_addze_subfze(state),
),
(&["addex"], |_state| {
// TODO
}),
(&["neg", "neg.", "nego", "nego."], DecodeState::decode_neg),
(&["neg", "neg.", "nego", "nego."], |state| {
DecodeState::decode_neg(state)
}),
(
&[
"mulli", "mullw", "mullw.", "mullwo", "mullwo.", "mulhw", "mulhw.", "mulhwu", "mulhwu.",
@ -2209,12 +2222,12 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
// TODO
},
),
(&["cmpi"], DecodeState::decode_cmpi),
(&["cmp"], DecodeState::decode_cmp),
(&["cmpli"], DecodeState::decode_cmpli),
(&["cmpl"], DecodeState::decode_cmpl),
(&["cmprb"], DecodeState::decode_cmprb),
(&["cmpeqb"], DecodeState::decode_cmpeqb),
(&["cmpi"], |state| DecodeState::decode_cmpi(state)),
(&["cmp"], |state| DecodeState::decode_cmp(state)),
(&["cmpli"], |state| DecodeState::decode_cmpli(state)),
(&["cmpl"], |state| DecodeState::decode_cmpl(state)),
(&["cmprb"], |state| DecodeState::decode_cmprb(state)),
(&["cmpeqb"], |state| DecodeState::decode_cmpeqb(state)),
(&["twi", "tw", "tdi", "td"], |_state| {
// TODO
}),
@ -2223,18 +2236,18 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
}),
(
&["andi.", "andis.", "ori", "oris", "xori", "xoris"],
DecodeState::decode_andis_oris_xoris,
|state| DecodeState::decode_andis_oris_xoris(state),
),
(
&[
"and", "and.", "xor", "xor.", "nand", "nand.", "or", "or.", "orc", "orc.", "nor",
"nor.", "eqv", "eqv.", "andc", "andc.",
],
DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc,
|state| DecodeState::decode_and_xor_nand_or_orc_nor_eqv_andc(state),
),
(
&["extsb", "extsb.", "extsh", "extsh.", "extsw", "extsw."],
DecodeState::decode_extsb_extsh_extsw,
|state| DecodeState::decode_extsb_extsh_extsw(state),
),
(&["cmpb"], |_state| {
// TODO
@ -2264,7 +2277,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
"slw", "slw.", "srw", "srw.", "srawi", "srawi.", "sraw", "sraw.", "sld", "sld.",
"sradi", "sradi.", "srd", "srd.", "srad", "srad.",
],
DecodeState::decode_shift,
|state| DecodeState::decode_shift(state),
),
(&["extswsli", "extswsli."], |_state| {
// TODO
@ -2292,7 +2305,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
// TODO
},
),
(&["mcrxrx"], DecodeState::decode_mcrxrx),
(&["mcrxrx"], |state| DecodeState::decode_mcrxrx(state)),
(
&[
"mtocrf", "mtcrf", "mfocrf", "mfcr", "setb", "setbc", "setbcr", "setnbc", "setnbcr",
@ -2301,7 +2314,7 @@ const DECODE_FNS: &[(&[&str], DecodeFn)] = &[
// TODO
},
),
(&["pnop"], DecodeState::decode_pnop),
(&["pnop"], |state| DecodeState::decode_pnop(state)),
(FP_MNEMONICS, |_state| {
// TODO(FP)
}),
@ -2395,6 +2408,7 @@ pub fn decode_one_insn() {
assert!(!duplicate, "duplicate mnemonic in DECODE_FNS: {mnemonic:?}");
}
}
let mut field_wires = Default::default();
for insn in Instructions::get().instructions() {
for header in insn.header() {
for mnemonic_line in header.mnemonics().lines() {
@ -2438,6 +2452,7 @@ pub fn decode_one_insn() {
first_input,
second_input,
second_input_used,
field_wires: &mut field_wires,
});
}
}

File diff suppressed because it is too large Load diff