forked from libre-chip/cpu
fix & clean up MOp definitions and ensure_reg_fields_are_in_the_same_place
This commit is contained in:
parent
9b8d99e9af
commit
e6f876f9af
3 changed files with 4561 additions and 5933 deletions
|
|
@ -1919,7 +1919,7 @@ common_mop_struct! {
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct ReadL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<0>>,
|
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<0>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1928,7 +1928,7 @@ common_mop_struct! {
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct WriteL2RegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1946,7 +1946,7 @@ common_mop_struct! {
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
pub struct LoadStoreCommonMOp<DestReg: Type, SrcRegWidth: Size, SrcCount: KnownSize> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<1>, DestReg, SrcRegWidth, SrcCount>,
|
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, SrcCount>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1972,8 +1972,8 @@ mop_enum! {
|
||||||
#[impl_mop_into = true]
|
#[impl_mop_into = true]
|
||||||
#[hdl]
|
#[hdl]
|
||||||
pub enum LoadStoreMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub enum LoadStoreMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
Load(CommonMOp<ConstUsize<2>, DestReg, SrcRegWidth, ConstUsize<0>>),
|
Load(LoadMOp<DestReg, SrcRegWidth>),
|
||||||
Store(CommonMOp<ConstUsize<2>, DestReg, SrcRegWidth, ConstUsize<1>>),
|
Store(StoreMOp<DestReg, SrcRegWidth>),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1982,7 +1982,7 @@ common_mop_struct! {
|
||||||
#[hdl(cmp_eq)]
|
#[hdl(cmp_eq)]
|
||||||
pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> {
|
pub struct MoveRegMOp<DestReg: Type, SrcRegWidth: Size> {
|
||||||
#[common]
|
#[common]
|
||||||
pub common: CommonMOp<ConstUsize<3>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
pub common: CommonMOp<ConstUsize<4>, DestReg, SrcRegWidth, ConstUsize<1>>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2440,16 +2440,23 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn ensure_reg_fields_are_in_the_same_place() {
|
fn ensure_reg_fields_are_in_the_same_place() {
|
||||||
|
struct Error {
|
||||||
|
dest_reg_offset: usize,
|
||||||
|
prefix_pad: usize,
|
||||||
|
path: Vec<&'static str>,
|
||||||
|
loc: SourceLocation,
|
||||||
|
variant: String,
|
||||||
|
}
|
||||||
struct Visitor {
|
struct Visitor {
|
||||||
dest_reg_offset: Option<(usize, String)>,
|
dest_reg_offset: Option<(usize, String)>,
|
||||||
max_dest_reg_offset: usize,
|
max_dest_reg_offset: usize,
|
||||||
min_prefix_pad: usize,
|
min_prefix_pad: usize,
|
||||||
errors: Option<String>,
|
errors: Vec<Error>,
|
||||||
}
|
}
|
||||||
impl MOpVariantVisitor<MOp> for Visitor {
|
impl<T: MOpTrait> MOpVariantVisitor<T> for Visitor {
|
||||||
type Break = Infallible;
|
type Break = Infallible;
|
||||||
fn visit_variant<
|
fn visit_variant<
|
||||||
VisitOps: ?Sized + MOpVariantVisitOps<Target = MOp, MOp: CommonMOpTrait>,
|
VisitOps: ?Sized + MOpVariantVisitOps<Target = T, MOp: CommonMOpTrait>,
|
||||||
>(
|
>(
|
||||||
&mut self,
|
&mut self,
|
||||||
visit_ops: &VisitOps,
|
visit_ops: &VisitOps,
|
||||||
|
|
@ -2497,15 +2504,13 @@ mod tests {
|
||||||
self.max_dest_reg_offset = self.max_dest_reg_offset.max(dest_reg_offset);
|
self.max_dest_reg_offset = self.max_dest_reg_offset.max(dest_reg_offset);
|
||||||
if let Some((first_dest_reg_offset, _)) = self.dest_reg_offset {
|
if let Some((first_dest_reg_offset, _)) = self.dest_reg_offset {
|
||||||
if first_dest_reg_offset != dest_reg_offset {
|
if first_dest_reg_offset != dest_reg_offset {
|
||||||
writeln!(
|
self.errors.push(Error {
|
||||||
self.errors.get_or_insert_default(),
|
dest_reg_offset,
|
||||||
"dest_reg_offset {dest_reg_offset} doesn't match first \
|
prefix_pad: <VisitOps::MOp as CommonMOpTrait>::PrefixPad::VALUE,
|
||||||
variant's dest_reg_offset {first_dest_reg_offset}\n\
|
path: VisitOps::path(),
|
||||||
variant's path: {:?}\n\
|
loc: VisitOps::MOp::source_location(),
|
||||||
variant: {variant:#?}\n",
|
variant: format!("{variant:#?}"),
|
||||||
VisitOps::path(),
|
});
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.dest_reg_offset = Some((
|
self.dest_reg_offset = Some((
|
||||||
|
|
@ -2519,28 +2524,54 @@ mod tests {
|
||||||
ControlFlow::Continue(())
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let mut visitor = Visitor {
|
#[track_caller]
|
||||||
dest_reg_offset: None,
|
fn check<T: MOpVisitVariants>(mop: T) {
|
||||||
max_dest_reg_offset: 0,
|
let mut visitor = Visitor {
|
||||||
min_prefix_pad: usize::MAX,
|
dest_reg_offset: None,
|
||||||
errors: None,
|
max_dest_reg_offset: 0,
|
||||||
};
|
min_prefix_pad: usize::MAX,
|
||||||
let ControlFlow::Continue(()) = MOp::visit_variants(&mut visitor, &MOp);
|
errors: Vec::new(),
|
||||||
let Visitor {
|
};
|
||||||
dest_reg_offset: Some((_, first_variant)),
|
let ControlFlow::Continue(()) = T::visit_variants(&mut visitor, &mop);
|
||||||
max_dest_reg_offset,
|
let Visitor {
|
||||||
min_prefix_pad,
|
dest_reg_offset: Some((_, first_variant)),
|
||||||
errors,
|
max_dest_reg_offset,
|
||||||
} = visitor
|
min_prefix_pad,
|
||||||
else {
|
errors,
|
||||||
panic!("no variants");
|
} = visitor
|
||||||
};
|
else {
|
||||||
println!("max_dest_reg_offset: {max_dest_reg_offset}");
|
panic!("no variants");
|
||||||
println!("min_prefix_pad: {min_prefix_pad}");
|
};
|
||||||
println!("{first_variant}");
|
println!("max_dest_reg_offset: {max_dest_reg_offset}");
|
||||||
if let Some(errors) = errors {
|
println!("min_prefix_pad: {min_prefix_pad}");
|
||||||
panic!("{errors}");
|
println!("{first_variant}");
|
||||||
|
if !errors.is_empty() {
|
||||||
|
let mut text = String::new();
|
||||||
|
for Error {
|
||||||
|
dest_reg_offset,
|
||||||
|
prefix_pad,
|
||||||
|
path,
|
||||||
|
loc,
|
||||||
|
variant,
|
||||||
|
} in errors
|
||||||
|
{
|
||||||
|
let expected_dest_reg_offset = max_dest_reg_offset - min_prefix_pad;
|
||||||
|
let fixed_prefix_pad = expected_dest_reg_offset + prefix_pad - dest_reg_offset;
|
||||||
|
writeln!(
|
||||||
|
text,
|
||||||
|
"at: {loc}\n\
|
||||||
|
dest_reg_offset {dest_reg_offset} doesn't match expected {expected_dest_reg_offset}\n\
|
||||||
|
change the prefix pad to: {fixed_prefix_pad}\n\
|
||||||
|
variant's path: {path:?}\n\
|
||||||
|
variant: {variant}\n",
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
panic!("{text}");
|
||||||
|
}
|
||||||
|
assert_eq!(min_prefix_pad, 0);
|
||||||
}
|
}
|
||||||
assert_eq!(min_prefix_pad, 0);
|
check(MOp);
|
||||||
|
check(RenamedMOp[UInt[8]][8]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7948
crates/cpu/tests/expected/decode_one_insn.vcd
generated
7948
crates/cpu/tests/expected/decode_one_insn.vcd
generated
File diff suppressed because it is too large
Load diff
2435
crates/cpu/tests/expected/reg_alloc.vcd
generated
2435
crates/cpu/tests/expected/reg_alloc.vcd
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue