forked from libre-chip/cpu
reduce the number of wires to have one per form/field pair instead of one per insn/field pair
This commit is contained in:
parent
1db65ae753
commit
faa8dde774
2 changed files with 73168 additions and 130361 deletions
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue