reduce the number of wires to have one per form/field pair instead of one per insn/field pair

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

File diff suppressed because it is too large Load diff