forked from libre-chip/cpu
Compare commits
3 commits
ebd69089c5
...
af87d52bf7
| Author | SHA1 | Date | |
|---|---|---|---|
| af87d52bf7 | |||
| d38bc786a7 | |||
| 6ee0d4265c |
12 changed files with 554048 additions and 20719 deletions
|
|
@ -87,8 +87,11 @@ fn add_sub<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
|||
connect(src1, src_values[1].int_fp);
|
||||
}
|
||||
#[hdl]
|
||||
let carry_in = wire();
|
||||
connect(carry_in, carry_in_before_inversion ^ invert_carry_in);
|
||||
let carry_in: UInt<1> = wire();
|
||||
connect(
|
||||
carry_in,
|
||||
(carry_in_before_inversion ^ invert_carry_in).cast_to_static::<UInt<1>>(),
|
||||
);
|
||||
#[hdl]
|
||||
let src0 = wire();
|
||||
connect(src0, src_values[0].int_fp);
|
||||
|
|
@ -104,7 +107,12 @@ fn add_sub<C: Type + PhantomConstCpuConfig, SrcCount: KnownSize>(config: C) {
|
|||
connect(pc_or_zero, pc);
|
||||
}
|
||||
let sum_of_sliced = |slice: RangeTo<usize>| {
|
||||
src0[slice] + src1[slice] + src_values[2].int_fp[slice] + pc_or_zero[slice] + imm[slice]
|
||||
src0[slice]
|
||||
+ src1[slice]
|
||||
+ src_values[2].int_fp[slice]
|
||||
+ pc_or_zero[slice]
|
||||
+ imm[slice]
|
||||
+ carry_in
|
||||
};
|
||||
#[hdl]
|
||||
let sum: UInt<64> = wire();
|
||||
|
|
|
|||
|
|
@ -317,152 +317,3 @@ impl LFSR31 {
|
|||
state
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CheckedVcdOutput {
|
||||
writer: Option<RcWriter>,
|
||||
expected_path: PathBuf,
|
||||
expected_contents: Result<String, (Option<PathBuf>, std::io::Error)>,
|
||||
location: &'static Location<'static>,
|
||||
}
|
||||
|
||||
impl CheckedVcdOutput {
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
pub fn new<T: BundleType>(sim: &mut Simulation<T>, expected_path: PathBuf) -> Self {
|
||||
let writer = RcWriter::default();
|
||||
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
|
||||
Self {
|
||||
writer: Some(writer),
|
||||
expected_contents: std::fs::read_to_string(&expected_path).map_err(|e| {
|
||||
eprintln!(
|
||||
"error: failed to read expected VCD from: {}",
|
||||
expected_path.display(),
|
||||
);
|
||||
(std::env::current_dir().ok(), e)
|
||||
}),
|
||||
expected_path,
|
||||
location: Location::caller(),
|
||||
}
|
||||
}
|
||||
#[must_use]
|
||||
#[track_caller]
|
||||
#[doc(hidden)]
|
||||
pub fn __checked_vcd_output_macro_helper<T: BundleType>(
|
||||
sim: &mut Simulation<T>,
|
||||
cargo_manifest_dir: &'static str,
|
||||
path: &'static str,
|
||||
) -> Self {
|
||||
Self::new(sim, Path::new(cargo_manifest_dir).join(path))
|
||||
}
|
||||
pub fn with_vcd_output<R>(&self, f: impl FnOnce(&str) -> R) -> R {
|
||||
let Some(writer) = &self.writer else {
|
||||
unreachable!();
|
||||
};
|
||||
writer.clone().borrow(|output| {
|
||||
let Ok(output) = str::from_utf8(output) else {
|
||||
unreachable!("VcdWriter writes valid UTF-8");
|
||||
};
|
||||
f(output)
|
||||
})
|
||||
}
|
||||
#[track_caller]
|
||||
pub fn finish(mut self) {
|
||||
let Ok(()) = self.finish_impl(|msg| panic!("{msg}"));
|
||||
}
|
||||
fn finish_impl<E>(
|
||||
&mut self,
|
||||
error: impl FnOnce(std::fmt::Arguments<'_>) -> E,
|
||||
) -> Result<(), E> {
|
||||
let Self {
|
||||
writer: Some(writer),
|
||||
expected_path,
|
||||
expected_contents,
|
||||
location,
|
||||
} = self
|
||||
else {
|
||||
// already finished
|
||||
return Ok(());
|
||||
};
|
||||
let Ok(vcd) = String::from_utf8(writer.take()) else {
|
||||
unreachable!("VcdWriter writes valid UTF-8");
|
||||
};
|
||||
let expected_path_d = expected_path.display();
|
||||
if expected_contents
|
||||
.as_ref()
|
||||
.is_ok_and(|expected_contents| *expected_contents == vcd)
|
||||
{
|
||||
// avoid written output from being split from threads interleaving writes to stdout
|
||||
let _stdout = std::io::stderr().lock();
|
||||
// use println to get output captured by tests
|
||||
println!("\n{location}: generated VCD matches the expected VCD in {expected_path_d}");
|
||||
return Ok(());
|
||||
}
|
||||
// avoid written output from being split from threads interleaving writes to stderr
|
||||
let _stderr = std::io::stderr().lock();
|
||||
let error = |msg: std::fmt::Arguments<'_>| {
|
||||
// print msg at both beginning and end so it's easier to find when the vcd is huge
|
||||
Err(error(format_args!(
|
||||
"\n{msg}####### VCD:\n{vcd}\n#######\n{msg}"
|
||||
)))
|
||||
};
|
||||
let error = |msg: std::fmt::Arguments<'_>| match &*expected_contents {
|
||||
Ok(_) => error(format_args!(
|
||||
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||
{msg}",
|
||||
)),
|
||||
Err((Some(current_dir), e)) => error(format_args!(
|
||||
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||
error: failed to read: {e}\n\
|
||||
current dir: {current_dir}\n\
|
||||
{msg}",
|
||||
current_dir = current_dir.display(),
|
||||
)),
|
||||
Err((None, e)) => error(format_args!(
|
||||
"{location}: generated VCD doesn't match the expected VCD in {expected_path_d}\n\
|
||||
error: failed to read: {e}\n\
|
||||
{msg}",
|
||||
)),
|
||||
};
|
||||
const OVERWRITE_VAR_NAME: &str = "OVERWRITE_EXPECTED_VCD";
|
||||
const OVERWRITE_VAR_VALUE: &str = "overwrite";
|
||||
match std::env::var_os(OVERWRITE_VAR_NAME) {
|
||||
Some(v) if v == OVERWRITE_VAR_VALUE => match std::fs::write(&expected_path, &vcd) {
|
||||
Ok(()) => error(format_args!(
|
||||
"warning: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- writing the generated VCD to {expected_path_d}\n"
|
||||
)),
|
||||
Err(e) => error(format_args!(
|
||||
"error: since `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}` is set -- tried to write the generated VCD to {expected_path_d}\n\
|
||||
error: failed to write: {e}"
|
||||
)),
|
||||
},
|
||||
_ => error(format_args!(
|
||||
"note: rerun the test with the environment variable `{OVERWRITE_VAR_NAME}={OVERWRITE_VAR_VALUE}`\n\
|
||||
to update the expected output to match the generated output.\n"
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for CheckedVcdOutput {
|
||||
#[track_caller]
|
||||
fn drop(&mut self) {
|
||||
let _ = self.finish_impl(|msg| {
|
||||
if std::thread::panicking() {
|
||||
eprintln!("{msg}"); // use eprintln to get output captured by tests
|
||||
} else {
|
||||
panic!("{msg}");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! checked_vcd_output {
|
||||
($sim:expr, $path_relative_to_manifest_dir:expr $(,)?) => {
|
||||
$crate::util::CheckedVcdOutput::__checked_vcd_output_macro_helper(
|
||||
$sim,
|
||||
::std::env!("CARGO_MANIFEST_DIR"),
|
||||
::std::concat!($path_relative_to_manifest_dir),
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1363,6 +1363,13 @@ $var wire 5 '=~,@ MLS_D_RT_5 $end
|
|||
$scope struct power_isa_gpr_or_zero_reg_2 $end
|
||||
$var wire 8 ?rD:V" value $end
|
||||
$upscope $end
|
||||
$scope struct power_isa_gpr_or_zero_reg_3 $end
|
||||
$var wire 8 ?rD:V# value $end
|
||||
$upscope $end
|
||||
$var wire 1 {!]++ DX_d2_1 $end
|
||||
$var wire 10 bj=V` DX_d0_10 $end
|
||||
$var wire 5 ^98rl DX_d1_5 $end
|
||||
$var wire 5 dmHRS DX_RT_5 $end
|
||||
$var wire 5 VT+LS XO_RB_5 $end
|
||||
$var wire 5 n'8X< XO_RA_5 $end
|
||||
$var wire 5 /')9{ XO_RT_5 $end
|
||||
|
|
@ -1406,33 +1413,48 @@ $var string 1 k^+pu$ \$tag $end
|
|||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_5 $end
|
||||
$var string 1 #a]5!% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_5 $end
|
||||
$var string 1 k^+pu% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_6 $end
|
||||
$var string 1 #a]5!& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_6 $end
|
||||
$var string 1 k^+pu& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_7 $end
|
||||
$var string 1 k^+pu' \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_5 $end
|
||||
$var string 1 #a]5!% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_8 $end
|
||||
$var string 1 k^+pu( \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_6 $end
|
||||
$var string 1 #a]5!& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_9 $end
|
||||
$var string 1 k^+pu) \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_7 $end
|
||||
$var string 1 #a]5!' \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_7 $end
|
||||
$var string 1 k^+pu' \$tag $end
|
||||
$scope struct flag_reg_1_10 $end
|
||||
$var string 1 k^+pu* \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
|
|
@ -1441,8 +1463,8 @@ $var string 1 #a]5!( \$tag $end
|
|||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_8 $end
|
||||
$var string 1 k^+pu( \$tag $end
|
||||
$scope struct flag_reg_1_11 $end
|
||||
$var string 1 k^+pu+ \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
|
|
@ -15214,6 +15236,8 @@ $var wire 1 O9nl\ matched_any_case $end
|
|||
$var wire 1 2J><` matched_case_addi $end
|
||||
$var wire 1 F[XQ_ matched_case_paddi $end
|
||||
$var wire 1 F[XQ_" matched_case_paddi_2 $end
|
||||
$var wire 1 zYEiT matched_case_addis $end
|
||||
$var wire 1 -="Wg matched_case_addpcis $end
|
||||
$var wire 1 f](?M matched_case_add $end
|
||||
$var wire 1 6@6XS \matched_case_add. $end
|
||||
$var wire 1 KbSE, matched_case_addo $end
|
||||
|
|
@ -15222,6 +15246,9 @@ $var wire 1 >{-\6 matched_case_addc $end
|
|||
$var wire 1 dL::r \matched_case_addc. $end
|
||||
$var wire 1 [Cj%o matched_case_addco $end
|
||||
$var wire 1 Bo#P' \matched_case_addco. $end
|
||||
$var wire 1 ;UoIk matched_case_addic $end
|
||||
$var wire 1 g:;Z_ \matched_case_addic. $end
|
||||
$var wire 1 pAfEx matched_case_subfic $end
|
||||
$var wire 64 <$d:7 input_r3 $end
|
||||
$var wire 64 h<mmR input_r4 $end
|
||||
$scope struct output_reg $end
|
||||
|
|
@ -15536,6 +15563,11 @@ $upscope $end
|
|||
$var wire 16 Hd*94 addi_imm $end
|
||||
$var wire 34 5bo?w paddi_imm $end
|
||||
$var wire 34 5bo?w" paddi_imm_2 $end
|
||||
$var wire 16 ~W%v& addis_imm $end
|
||||
$var wire 10 ei=V2 addpcis_d0 $end
|
||||
$var wire 5 09o]U addpcis_d1 $end
|
||||
$var wire 1 3E]&t addpcis_d2 $end
|
||||
$var wire 16 N<`^[ addpcis_d $end
|
||||
$var string 1 <gfVf add_expected_out $end
|
||||
$var string 1 <gfVf" add_expected_out_2 $end
|
||||
$var string 1 <gfVf# add_expected_out_3 $end
|
||||
|
|
@ -15544,6 +15576,15 @@ $var string 1 <gfVf% add_expected_out_5 $end
|
|||
$var string 1 <gfVf& add_expected_out_6 $end
|
||||
$var string 1 <gfVf' add_expected_out_7 $end
|
||||
$var string 1 <gfVf( add_expected_out_8 $end
|
||||
$var wire 16 .-Zk( addic_subfic_imm $end
|
||||
$var wire 64 $a0'K addic_subfic_in $end
|
||||
$var string 1 4CV)U addic_subfic_expected_out $end
|
||||
$var wire 16 .-Zk(" addic_subfic_imm_2 $end
|
||||
$var wire 64 $a0'K" addic_subfic_in_2 $end
|
||||
$var string 1 4CV)U" addic_subfic_expected_out_2 $end
|
||||
$var wire 16 .-Zk(# addic_subfic_imm_3 $end
|
||||
$var wire 64 $a0'K# addic_subfic_in_3 $end
|
||||
$var string 1 4CV)U# addic_subfic_expected_out_3 $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$dumpvars
|
||||
|
|
@ -16720,6 +16761,11 @@ b0 5]QZg
|
|||
b0 pQ'}$
|
||||
b0 '=~,@
|
||||
b0 ?rD:V"
|
||||
b0 ?rD:V#
|
||||
0{!]++
|
||||
b0 bj=V`
|
||||
b0 ^98rl
|
||||
b0 dmHRS
|
||||
b0 VT+LS
|
||||
b0 n'8X<
|
||||
b0 /')9{
|
||||
|
|
@ -16731,14 +16777,17 @@ sHdlSome\x20(1) #a]5!#
|
|||
sHdlNone\x20(0) k^+pu#
|
||||
sHdlSome\x20(1) #a]5!$
|
||||
sHdlSome\x20(1) k^+pu$
|
||||
sHdlNone\x20(0) #a]5!%
|
||||
sHdlNone\x20(0) k^+pu%
|
||||
sHdlNone\x20(0) #a]5!&
|
||||
sHdlSome\x20(1) k^+pu&
|
||||
sHdlSome\x20(1) #a]5!'
|
||||
sHdlNone\x20(0) k^+pu'
|
||||
sHdlNone\x20(0) #a]5!%
|
||||
sHdlNone\x20(0) k^+pu(
|
||||
sHdlNone\x20(0) #a]5!&
|
||||
sHdlSome\x20(1) k^+pu)
|
||||
sHdlSome\x20(1) #a]5!'
|
||||
sHdlNone\x20(0) k^+pu*
|
||||
sHdlSome\x20(1) #a]5!(
|
||||
sHdlSome\x20(1) k^+pu(
|
||||
sHdlSome\x20(1) k^+pu+
|
||||
b0 x,~Jt
|
||||
sHdlNone\x20(0) \L:8?
|
||||
b0 sD<$[
|
||||
|
|
@ -23137,6 +23186,8 @@ b1000000000100 @$@j=%
|
|||
02J><`
|
||||
0F[XQ_
|
||||
0F[XQ_"
|
||||
0zYEiT
|
||||
0-="Wg
|
||||
1f](?M
|
||||
06@6XS
|
||||
0KbSE,
|
||||
|
|
@ -23145,6 +23196,9 @@ b1000000000100 @$@j=%
|
|||
0dL::r
|
||||
0[Cj%o
|
||||
0Bo#P'
|
||||
0;UoIk
|
||||
0g:;Z_
|
||||
0pAfEx
|
||||
b1001000110100 <$d:7
|
||||
b1001000110100 @$@j=&
|
||||
b1001000110100 h<mmR
|
||||
|
|
@ -23429,6 +23483,11 @@ sPhantomConst({\"units\":[{\"kind\":\"AluBranch\",\"max_in_flight\":null}],\"out
|
|||
b10001000010100 Hd*94
|
||||
b1100100010000101000000000000000000 5bo?w
|
||||
b1100100010000101000000000000000000 5bo?w"
|
||||
b10001000010100 ~W%v&
|
||||
b10001000 ei=V2
|
||||
b11 09o]U
|
||||
03E]&t
|
||||
b10001000000110 N<`^[
|
||||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf
|
||||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf"
|
||||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf#
|
||||
|
|
@ -23437,6 +23496,15 @@ sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20tru
|
|||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf&
|
||||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf'
|
||||
sPRegValue\x20{\x20int_fp:\x200x2468_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} <gfVf(
|
||||
b10001000010100 .-Zk(
|
||||
b1001000110100 $a0'K
|
||||
sPRegValue\x20{\x20int_fp:\x200x3448_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} 4CV)U
|
||||
b10001000010100 .-Zk("
|
||||
b1001000110100 $a0'K"
|
||||
sPRegValue\x20{\x20int_fp:\x200x3448_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} 4CV)U"
|
||||
b10001000010100 .-Zk(#
|
||||
b1001000110100 $a0'K#
|
||||
sPRegValue\x20{\x20int_fp:\x200x3448_u64,\x20flags:\x20Pwr\x20{\x20cr_gt:\x20true,\x20..\x20}\x20} 4CV)U#
|
||||
$end
|
||||
#500000
|
||||
1mAPf1
|
||||
|
|
@ -23458,6 +23526,10 @@ b11 p'{1C
|
|||
b11 XQ7U4
|
||||
b100011 ?rD:V
|
||||
b110010001000010100 lX!]F
|
||||
b100011 ?rD:V#
|
||||
b10001000 bj=V`
|
||||
b11 ^98rl
|
||||
b11 dmHRS
|
||||
b100 VT+LS
|
||||
b11 n'8X<
|
||||
b11 /')9{
|
||||
|
|
@ -23789,6 +23861,10 @@ b0 p'{1C
|
|||
b0 XQ7U4
|
||||
b0 ?rD:V
|
||||
b0 lX!]F
|
||||
b0 ?rD:V#
|
||||
b0 bj=V`
|
||||
b0 ^98rl
|
||||
b0 dmHRS
|
||||
b0 VT+LS
|
||||
b0 n'8X<
|
||||
b0 /')9{
|
||||
|
|
|
|||
536192
crates/cpu/tests/expected/units_formal_power_isa_add_sub_sim.vcd
generated
Normal file
536192
crates/cpu/tests/expected/units_formal_power_isa_add_sub_sim.vcd
generated
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -1363,6 +1363,13 @@ $var wire 5 '=~,@ MLS_D_RT_5 $end
|
|||
$scope struct power_isa_gpr_or_zero_reg_2 $end
|
||||
$var wire 8 ?rD:V" value $end
|
||||
$upscope $end
|
||||
$scope struct power_isa_gpr_or_zero_reg_3 $end
|
||||
$var wire 8 ?rD:V# value $end
|
||||
$upscope $end
|
||||
$var wire 1 {!]++ DX_d2_1 $end
|
||||
$var wire 10 bj=V` DX_d0_10 $end
|
||||
$var wire 5 ^98rl DX_d1_5 $end
|
||||
$var wire 5 dmHRS DX_RT_5 $end
|
||||
$var wire 5 VT+LS XO_RB_5 $end
|
||||
$var wire 5 n'8X< XO_RA_5 $end
|
||||
$var wire 5 /')9{ XO_RT_5 $end
|
||||
|
|
@ -1406,33 +1413,48 @@ $var string 1 k^+pu$ \$tag $end
|
|||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_5 $end
|
||||
$var string 1 #a]5!% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_5 $end
|
||||
$var string 1 k^+pu% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_6 $end
|
||||
$var string 1 #a]5!& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_6 $end
|
||||
$var string 1 k^+pu& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_7 $end
|
||||
$var string 1 k^+pu' \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_5 $end
|
||||
$var string 1 #a]5!% \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_8 $end
|
||||
$var string 1 k^+pu( \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_6 $end
|
||||
$var string 1 #a]5!& \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_9 $end
|
||||
$var string 1 k^+pu) \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_0_7 $end
|
||||
$var string 1 #a]5!' \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_7 $end
|
||||
$var string 1 k^+pu' \$tag $end
|
||||
$scope struct flag_reg_1_10 $end
|
||||
$var string 1 k^+pu* \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
|
|
@ -1441,8 +1463,8 @@ $var string 1 #a]5!( \$tag $end
|
|||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
$scope struct flag_reg_1_8 $end
|
||||
$var string 1 k^+pu( \$tag $end
|
||||
$scope struct flag_reg_1_11 $end
|
||||
$var string 1 k^+pu+ \$tag $end
|
||||
$scope struct HdlSome $end
|
||||
$upscope $end
|
||||
$upscope $end
|
||||
|
|
@ -15214,6 +15236,8 @@ $var wire 1 O9nl\ matched_any_case $end
|
|||
$var wire 1 2J><` matched_case_addi $end
|
||||
$var wire 1 F[XQ_ matched_case_paddi $end
|
||||
$var wire 1 F[XQ_" matched_case_paddi_2 $end
|
||||
$var wire 1 zYEiT matched_case_addis $end
|
||||
$var wire 1 -="Wg matched_case_addpcis $end
|
||||
$var wire 1 f](?M matched_case_add $end
|
||||
$var wire 1 6@6XS \matched_case_add. $end
|
||||
$var wire 1 KbSE, matched_case_addo $end
|
||||
|
|
@ -15222,6 +15246,9 @@ $var wire 1 >{-\6 matched_case_addc $end
|
|||
$var wire 1 dL::r \matched_case_addc. $end
|
||||
$var wire 1 [Cj%o matched_case_addco $end
|
||||
$var wire 1 Bo#P' \matched_case_addco. $end
|
||||
$var wire 1 ;UoIk matched_case_addic $end
|
||||
$var wire 1 g:;Z_ \matched_case_addic. $end
|
||||
$var wire 1 pAfEx matched_case_subfic $end
|
||||
$var wire 64 <$d:7 input_r3 $end
|
||||
$var wire 64 h<mmR input_r4 $end
|
||||
$scope struct output_reg $end
|
||||
|
|
@ -15536,6 +15563,11 @@ $upscope $end
|
|||
$var wire 16 Hd*94 addi_imm $end
|
||||
$var wire 34 5bo?w paddi_imm $end
|
||||
$var wire 34 5bo?w" paddi_imm_2 $end
|
||||
$var wire 16 ~W%v& addis_imm $end
|
||||
$var wire 10 ei=V2 addpcis_d0 $end
|
||||
$var wire 5 09o]U addpcis_d1 $end
|
||||
$var wire 1 3E]&t addpcis_d2 $end
|
||||
$var wire 16 N<`^[ addpcis_d $end
|
||||
$var string 1 <gfVf add_expected_out $end
|
||||
$var string 1 <gfVf" add_expected_out_2 $end
|
||||
$var string 1 <gfVf# add_expected_out_3 $end
|
||||
|
|
@ -15544,6 +15576,15 @@ $var string 1 <gfVf% add_expected_out_5 $end
|
|||
$var string 1 <gfVf& add_expected_out_6 $end
|
||||
$var string 1 <gfVf' add_expected_out_7 $end
|
||||
$var string 1 <gfVf( add_expected_out_8 $end
|
||||
$var wire 16 .-Zk( addic_subfic_imm $end
|
||||
$var wire 64 $a0'K addic_subfic_in $end
|
||||
$var string 1 4CV)U addic_subfic_expected_out $end
|
||||
$var wire 16 .-Zk(" addic_subfic_imm_2 $end
|
||||
$var wire 64 $a0'K" addic_subfic_in_2 $end
|
||||
$var string 1 4CV)U" addic_subfic_expected_out_2 $end
|
||||
$var wire 16 .-Zk(# addic_subfic_imm_3 $end
|
||||
$var wire 64 $a0'K# addic_subfic_in_3 $end
|
||||
$var string 1 4CV)U# addic_subfic_expected_out_3 $end
|
||||
$upscope $end
|
||||
$enddefinitions $end
|
||||
$dumpvars
|
||||
|
|
@ -16720,6 +16761,11 @@ b0 5]QZg
|
|||
b0 pQ'}$
|
||||
b0 '=~,@
|
||||
b0 ?rD:V"
|
||||
b0 ?rD:V#
|
||||
0{!]++
|
||||
b0 bj=V`
|
||||
b0 ^98rl
|
||||
b0 dmHRS
|
||||
b0 VT+LS
|
||||
b0 n'8X<
|
||||
b0 /')9{
|
||||
|
|
@ -16731,14 +16777,17 @@ sHdlSome\x20(1) #a]5!#
|
|||
sHdlNone\x20(0) k^+pu#
|
||||
sHdlSome\x20(1) #a]5!$
|
||||
sHdlSome\x20(1) k^+pu$
|
||||
sHdlNone\x20(0) #a]5!%
|
||||
sHdlNone\x20(0) k^+pu%
|
||||
sHdlNone\x20(0) #a]5!&
|
||||
sHdlSome\x20(1) k^+pu&
|
||||
sHdlSome\x20(1) #a]5!'
|
||||
sHdlNone\x20(0) k^+pu'
|
||||
sHdlNone\x20(0) #a]5!%
|
||||
sHdlNone\x20(0) k^+pu(
|
||||
sHdlNone\x20(0) #a]5!&
|
||||
sHdlSome\x20(1) k^+pu)
|
||||
sHdlSome\x20(1) #a]5!'
|
||||
sHdlNone\x20(0) k^+pu*
|
||||
sHdlSome\x20(1) #a]5!(
|
||||
sHdlSome\x20(1) k^+pu(
|
||||
sHdlSome\x20(1) k^+pu+
|
||||
b0 x,~Jt
|
||||
sHdlNone\x20(0) \L:8?
|
||||
b0 sD<$[
|
||||
|
|
@ -23137,6 +23186,8 @@ b1000000001000 @$@j=%
|
|||
02J><`
|
||||
1F[XQ_
|
||||
0F[XQ_"
|
||||
0zYEiT
|
||||
0-="Wg
|
||||
0f](?M
|
||||
06@6XS
|
||||
0KbSE,
|
||||
|
|
@ -23145,6 +23196,9 @@ b1000000001000 @$@j=%
|
|||
0dL::r
|
||||
0[Cj%o
|
||||
0Bo#P'
|
||||
0;UoIk
|
||||
0g:;Z_
|
||||
0pAfEx
|
||||
b1001100100000111010011110010011000000000000000000000000000000010 <$d:7
|
||||
b1001100100000111010011110010011000000000000000000000000000000010 @$@j=&
|
||||
b110000000000000000001000010010000010111110111111111111011111101 h<mmR
|
||||
|
|
@ -23429,6 +23483,11 @@ sPhantomConst({\"units\":[{\"kind\":\"AluBranch\",\"max_in_flight\":null}],\"out
|
|||
b0 Hd*94
|
||||
b1000000000000 5bo?w
|
||||
b1000000000000 5bo?w"
|
||||
b0 ~W%v&
|
||||
b0 ei=V2
|
||||
b0 09o]U
|
||||
03E]&t
|
||||
b0 N<`^[
|
||||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf
|
||||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf"
|
||||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf#
|
||||
|
|
@ -23437,6 +23496,15 @@ sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20c
|
|||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf&
|
||||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf'
|
||||
sPRegValue\x20{\x20int_fp:\x200xF907534A17DFFEFF_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} <gfVf(
|
||||
b0 .-Zk(
|
||||
b1001111111111111111110111101101111101000001000000000000100000010 $a0'K
|
||||
sPRegValue\x20{\x20int_fp:\x200x9FFFFBDBE8200103_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} 4CV)U
|
||||
b0 .-Zk("
|
||||
b1001111111111111111110111101101111101000001000000000000100000010 $a0'K"
|
||||
sPRegValue\x20{\x20int_fp:\x200x9FFFFBDBE8200103_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} 4CV)U"
|
||||
b0 .-Zk(#
|
||||
b1001111111111111111110111101101111101000001000000000000100000010 $a0'K#
|
||||
sPRegValue\x20{\x20int_fp:\x200x9FFFFBDBE8200103_u64,\x20flags:\x20Pwr\x20{\x20cr_lt:\x20true,\x20..\x20}\x20} 4CV)U#
|
||||
$end
|
||||
#500000
|
||||
1mAPf1
|
||||
|
|
@ -23465,6 +23533,7 @@ b1000000000000 5]QZg
|
|||
b100 pQ'}$
|
||||
b11 '=~,@
|
||||
b100100 ?rD:V"
|
||||
b10000 dmHRS
|
||||
b10000 /')9{
|
||||
b110000000000000000000000000 x,~Jt
|
||||
sHdlSome\x20(1) \L:8?
|
||||
|
|
@ -23738,6 +23807,7 @@ b0 5]QZg
|
|||
b0 pQ'}$
|
||||
b0 '=~,@
|
||||
b0 ?rD:V"
|
||||
b0 dmHRS
|
||||
b0 /')9{
|
||||
b0 x,~Jt
|
||||
sHdlNone\x20(0) \L:8?
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
// See Notices.txt for copyright information
|
||||
|
||||
use cpu::{
|
||||
checked_vcd_output,
|
||||
config::{
|
||||
CpuConfig, CpuConfigFetchWidth, CpuConfigMaxUnitMaxInFlight, PhantomConstCpuConfig,
|
||||
UnitConfig,
|
||||
|
|
@ -29,6 +28,7 @@ use cpu::{
|
|||
};
|
||||
use fayalite::{
|
||||
bundle::BundleType,
|
||||
checked_vcd_output,
|
||||
module::instance_with_loc,
|
||||
prelude::*,
|
||||
ty::{OpaqueSimValue, StaticType},
|
||||
|
|
|
|||
|
|
@ -3,10 +3,9 @@
|
|||
|
||||
use crate::test_cases::TestCase;
|
||||
use cpu::{
|
||||
checked_vcd_output, decoder::simple_power_isa::decode_one_insn, instruction::MOp,
|
||||
util::array_vec::ArrayVec,
|
||||
decoder::simple_power_isa::decode_one_insn, instruction::MOp, util::array_vec::ArrayVec,
|
||||
};
|
||||
use fayalite::prelude::*;
|
||||
use fayalite::{checked_vcd_output, prelude::*};
|
||||
use std::{fmt::Write as _, io::Write, process::Command};
|
||||
|
||||
mod test_cases;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use cpu::{
|
|||
util::array_vec::ArrayVec,
|
||||
};
|
||||
use fayalite::{
|
||||
checked_vcd_output,
|
||||
firrtl::ExportOptions,
|
||||
module::{instance_with_loc, transform::simplify_enums::SimplifyEnumsKind, wire_with_loc},
|
||||
prelude::*,
|
||||
|
|
@ -412,6 +413,69 @@ fn case_check_paddi(cases: &mut Cases) {
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn case_check_addis(cases: &mut Cases) {
|
||||
cases.add("addis 3, 4, imm", 0x3C64_0000, 0xFFFF, check_addis);
|
||||
#[hdl]
|
||||
fn check_addis(clk: Expr<Clock>, input: Expr<CheckInput>, output: &mut CaseOutput) {
|
||||
#[hdl]
|
||||
let addis_imm = wire();
|
||||
connect(
|
||||
addis_imm,
|
||||
input.decoder_input.0.cast_to_static::<SInt<16>>(),
|
||||
);
|
||||
let r4_in = input.regs.regs[MOpRegNum::power_isa_gpr_reg_imm(4).value].int_fp;
|
||||
let r3_out = output.reg(MOpRegNum::power_isa_gpr_reg_num(3)).int_fp;
|
||||
hdl_assert(
|
||||
clk,
|
||||
(r4_in + (addis_imm << 16).cast_to_static::<UInt<64>>())
|
||||
.cast_to_static::<UInt<64>>()
|
||||
.cmp_eq(r3_out),
|
||||
"",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn case_check_addpcis(cases: &mut Cases) {
|
||||
cases.add("addpcis 3, imm", 0x4C60_0004, 0x1F_FFC1, check_addpcis);
|
||||
#[hdl]
|
||||
fn check_addpcis(clk: Expr<Clock>, input: Expr<CheckInput>, output: &mut CaseOutput) {
|
||||
#[hdl]
|
||||
let addpcis_d0 = wire();
|
||||
connect(
|
||||
addpcis_d0,
|
||||
input.decoder_input.0[6..].cast_to_static::<UInt<10>>(),
|
||||
);
|
||||
#[hdl]
|
||||
let addpcis_d1 = wire();
|
||||
connect(
|
||||
addpcis_d1,
|
||||
input.decoder_input.0[16..].cast_to_static::<UInt<5>>(),
|
||||
);
|
||||
#[hdl]
|
||||
let addpcis_d2 = wire();
|
||||
connect(
|
||||
addpcis_d2,
|
||||
input.decoder_input.0.cast_to_static::<UInt<1>>(),
|
||||
);
|
||||
#[hdl]
|
||||
let addpcis_d = wire();
|
||||
connect(
|
||||
addpcis_d,
|
||||
(addpcis_d2 + (addpcis_d1 << 1) + (addpcis_d0 << 6)).cast_to_static::<SInt<16>>(),
|
||||
);
|
||||
let r3_out = output.reg(MOpRegNum::power_isa_gpr_reg_num(3)).int_fp;
|
||||
hdl_assert(
|
||||
clk,
|
||||
(input.pc + 4u64 + (addpcis_d << 16).cast_to_static::<UInt<64>>())
|
||||
.cast_to_static::<UInt<64>>()
|
||||
.cmp_eq(r3_out),
|
||||
"",
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn case_check_add_addc(cases: &mut Cases) {
|
||||
cases.add("add 3, 3, 4", 0x7C63_2214, 0, check_add);
|
||||
|
|
@ -493,20 +557,98 @@ fn case_check_add_addc(cases: &mut Cases) {
|
|||
}
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn case_check_addic_subfic(cases: &mut Cases) {
|
||||
cases.add("addic 3, 4, imm", 0x3064_0000, 0xFFFF, check_addic_subfic);
|
||||
cases.add("addic. 3, 4, imm", 0x3464_0000, 0xFFFF, check_addic_subfic);
|
||||
cases.add("subfic 3, 4, imm", 0x2064_0000, 0xFFFF, check_addic_subfic);
|
||||
#[hdl]
|
||||
fn check_addic_subfic(clk: Expr<Clock>, input: Expr<CheckInput>, output: &mut CaseOutput) {
|
||||
let rc = (input.decoder_input.0 & 0x400_0000u32).cmp_ne(0u32);
|
||||
let is_sub = (input.decoder_input.0 & 0x1000_0000u32).cmp_eq(0u32);
|
||||
let r4_in = input.regs.regs[MOpRegNum::power_isa_gpr_reg_imm(4).value].int_fp;
|
||||
let cr0_in = input.regs.regs[MOpRegNum::power_isa_cr_0_reg().value];
|
||||
let r3_out = output.reg(MOpRegNum::power_isa_gpr_reg_num(3));
|
||||
let ca_out = output.reg(MOpRegNum::POWER_ISA_XER_CA_CA32_REG_NUM);
|
||||
let cr0_out = output.reg(MOpRegNum::POWER_ISA_CR_0_REG_NUM);
|
||||
#[hdl]
|
||||
let addic_subfic_imm = wire();
|
||||
connect(
|
||||
addic_subfic_imm,
|
||||
input.decoder_input.0.cast_to_static::<SInt<16>>(),
|
||||
);
|
||||
#[hdl]
|
||||
let addic_subfic_in = wire();
|
||||
connect(addic_subfic_in, r4_in);
|
||||
#[hdl]
|
||||
if is_sub {
|
||||
connect(addic_subfic_in, !r4_in);
|
||||
}
|
||||
#[hdl]
|
||||
let addic_subfic_expected_out = wire(r3_out.ty());
|
||||
connect_any(
|
||||
addic_subfic_expected_out.int_fp,
|
||||
addic_subfic_in + addic_subfic_imm.cast_to(UInt[64]) + is_sub.cast_to(UInt[1]),
|
||||
);
|
||||
let PRegFlagsPowerISAView {
|
||||
unused: _,
|
||||
xer_ca,
|
||||
xer_ca32,
|
||||
xer_ov,
|
||||
xer_ov32,
|
||||
cr_lt,
|
||||
cr_gt,
|
||||
cr_eq,
|
||||
so,
|
||||
..
|
||||
} = PRegFlags::view::<PRegFlagsPowerISA>(addic_subfic_expected_out.flags);
|
||||
let addic_subfic_in_s = addic_subfic_in.cast_to_static::<SInt<64>>();
|
||||
let u64_sum =
|
||||
addic_subfic_in + addic_subfic_imm.cast_to(UInt[64]) + is_sub.cast_to(UInt[1]);
|
||||
let s64_sum =
|
||||
addic_subfic_in_s + addic_subfic_imm + is_sub.cast_to(UInt[1]).cast_to(SInt[64]);
|
||||
let u32_sum = addic_subfic_in.cast_to(UInt[32])
|
||||
+ addic_subfic_imm.cast_to(UInt[32])
|
||||
+ is_sub.cast_to(UInt[1]);
|
||||
let s32_sum = addic_subfic_in.cast_to(SInt[32])
|
||||
+ addic_subfic_imm.cast_to(SInt[32])
|
||||
+ is_sub.cast_to(UInt[1]).cast_to(SInt[32]);
|
||||
let sum_as_s64 = u64_sum.cast_to(SInt[64]);
|
||||
connect(xer_ca, u64_sum[64]);
|
||||
connect(xer_ca32, u32_sum[32]);
|
||||
connect(xer_ov, s64_sum.cmp_lt(i64::MIN) | s64_sum.cmp_gt(i64::MAX));
|
||||
connect(
|
||||
xer_ov32,
|
||||
s32_sum.cmp_lt(i32::MIN) | s32_sum.cmp_gt(i32::MAX),
|
||||
);
|
||||
connect(cr_gt, sum_as_s64.cmp_gt(0i64));
|
||||
connect(cr_lt, sum_as_s64.cmp_lt(0i64));
|
||||
connect(cr_eq, sum_as_s64.cmp_eq(0i64));
|
||||
connect(so, xer_ov); // TODO: also propagate from input SO
|
||||
|
||||
hdl_assert(clk, addic_subfic_expected_out.cmp_eq(ca_out), "");
|
||||
|
||||
#[hdl]
|
||||
if rc {
|
||||
hdl_assert(clk, addic_subfic_expected_out.cmp_eq(cr0_out), "");
|
||||
} else {
|
||||
hdl_assert(clk, cr0_in.cmp_eq(cr0_out), "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn cases_add_sub() -> Cases {
|
||||
let mut cases = Cases::default();
|
||||
case_check_addi(&mut cases);
|
||||
case_check_paddi(&mut cases);
|
||||
// TODO: "addis"
|
||||
// TODO: "addpcis"
|
||||
case_check_addis(&mut cases);
|
||||
case_check_addpcis(&mut cases);
|
||||
case_check_add_addc(&mut cases);
|
||||
// TODO: "addic"
|
||||
// TODO: "addic."
|
||||
case_check_addic_subfic(&mut cases);
|
||||
// TODO: "subf"
|
||||
// TODO: "subf."
|
||||
// TODO: "subfo"
|
||||
// TODO: "subfo."
|
||||
// TODO: "subfic"
|
||||
// TODO: "subfc"
|
||||
// TODO: "subfc."
|
||||
// TODO: "subfco"
|
||||
|
|
@ -572,7 +714,7 @@ impl AnyConsts {
|
|||
#[hdl_module]
|
||||
fn check_power_isa_alu_formal(
|
||||
config: PhantomConst<CpuConfig>,
|
||||
cases: Cases,
|
||||
cases: &Cases,
|
||||
any_consts: Option<AnyConsts>,
|
||||
) {
|
||||
#[hdl]
|
||||
|
|
@ -778,7 +920,7 @@ fn test_power_isa_add_sub_formal() {
|
|||
vec![UnitConfig::new(UnitKind::AluBranch)],
|
||||
NonZero::new(20).unwrap(),
|
||||
));
|
||||
let m = check_power_isa_alu_formal(config, cases_add_sub(), None);
|
||||
let m = check_power_isa_alu_formal(config, &cases_add_sub(), None);
|
||||
assert_formal(
|
||||
"test_power_isa_add_sub_formal",
|
||||
m,
|
||||
|
|
@ -792,6 +934,138 @@ fn test_power_isa_add_sub_formal() {
|
|||
);
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
fn test_power_isa_alu_sim(
|
||||
cases: Cases,
|
||||
checked_vcd_output: impl FnOnce(
|
||||
&mut Simulation<check_power_isa_alu_formal>,
|
||||
) -> fayalite::testing::CheckedVcdOutput,
|
||||
) {
|
||||
let config = PhantomConst::new_sized(CpuConfig::new(
|
||||
vec![UnitConfig::new(UnitKind::AluBranch)],
|
||||
NonZero::new(20).unwrap(),
|
||||
));
|
||||
let any_consts = AnyConsts::new();
|
||||
let m = check_power_isa_alu_formal(config, &cases, Some(any_consts));
|
||||
let mut sim = Simulation::new(m);
|
||||
let _checked_vcd_output = checked_vcd_output(&mut sim);
|
||||
let AnyConsts {
|
||||
decoder_first_word_any_const,
|
||||
decoder_has_second_word_any_const,
|
||||
decoder_second_word_any_const,
|
||||
r3_any_const,
|
||||
r4_any_const,
|
||||
pc_any_const,
|
||||
predicted_next_pc_any_const,
|
||||
} = any_consts;
|
||||
const REG_VALUES: &[u64] = &[0x0, 0xAAAA_AAAA_AAAA_AAAA, 0xFFFF_FFFF_FFFF_FFFF];
|
||||
const IMM_S16_VALUES: &[i16] = &[0, 1, -1, i16::MAX, i16::MIN, 0x100];
|
||||
const S34_MAX: i64 = (1 << 33) - 1;
|
||||
const S34_MIN: i64 = -1 << 33;
|
||||
const IMM_S34_VALUES: &[i64] = &[0, 1, -1, S34_MAX, S34_MIN];
|
||||
const PC: u64 = 0x1000;
|
||||
for case in &cases.cases {
|
||||
for &r3 in REG_VALUES {
|
||||
for &r4 in REG_VALUES {
|
||||
let mut imm_index = 0;
|
||||
loop {
|
||||
let asm = case.asm();
|
||||
let source_location = case.source_location();
|
||||
println!(
|
||||
"case: {asm}\n\
|
||||
r3={r3:#x} r4={r4:#x}\n\
|
||||
at: {source_location}"
|
||||
);
|
||||
sim.write(r3_any_const, r3);
|
||||
sim.write(r4_any_const, r4);
|
||||
sim.write(pc_any_const, PC);
|
||||
let imm_count;
|
||||
match *case {
|
||||
Case::Unprefixed {
|
||||
asm: _,
|
||||
encoded,
|
||||
imm_mask,
|
||||
check: _,
|
||||
source_location: _,
|
||||
} => {
|
||||
sim.write(predicted_next_pc_any_const, PC + 4);
|
||||
let imm = IMM_S16_VALUES[imm_index] as i64;
|
||||
if imm_mask == 0 {
|
||||
imm_count = 1;
|
||||
} else {
|
||||
imm_count = IMM_S16_VALUES.len();
|
||||
println!("imm = {imm:#x}");
|
||||
}
|
||||
let mut imm = imm as u32;
|
||||
if case.mnemonic() == "addpcis" {
|
||||
let d2 = imm & 1;
|
||||
let d1 = (imm >> 1) & 0x1F;
|
||||
let d0 = (imm >> 6) & 0x3FF;
|
||||
imm = d2 | (d1 << 16) | (d0 << 6);
|
||||
}
|
||||
sim.write(decoder_first_word_any_const, encoded | (imm_mask & imm));
|
||||
sim.write(decoder_has_second_word_any_const, false);
|
||||
sim.write(decoder_second_word_any_const, 0u32);
|
||||
}
|
||||
Case::Prefixed {
|
||||
asm: _,
|
||||
encoded: (encoded_prefix, encoded_suffix),
|
||||
imm_mask: (imm_mask_prefix, imm_mask_suffix),
|
||||
check: _,
|
||||
source_location: _,
|
||||
} => {
|
||||
sim.write(predicted_next_pc_any_const, PC + 8);
|
||||
let imm = IMM_S34_VALUES[imm_index];
|
||||
if imm_mask_prefix == 0 && imm_mask_suffix == 0 {
|
||||
imm_count = 1;
|
||||
} else {
|
||||
imm_count = IMM_S34_VALUES.len();
|
||||
println!("imm = {imm:#x}");
|
||||
}
|
||||
sim.write(
|
||||
decoder_first_word_any_const,
|
||||
encoded_prefix | (imm_mask_prefix & (imm >> 16) as u32),
|
||||
);
|
||||
sim.write(decoder_has_second_word_any_const, true);
|
||||
sim.write(
|
||||
decoder_second_word_any_const,
|
||||
encoded_suffix | (imm_mask_suffix & (imm & 0xFFFF) as u32),
|
||||
);
|
||||
}
|
||||
}
|
||||
let clk = formal_global_clock();
|
||||
let rst = formal_reset();
|
||||
sim.write_clock(clk, false);
|
||||
sim.write_reset(rst, true);
|
||||
for cycle in 0..10 {
|
||||
sim.advance_time(SimDuration::from_nanos(500));
|
||||
println!("clock tick: {cycle}");
|
||||
sim.write_clock(clk, true);
|
||||
sim.advance_time(SimDuration::from_nanos(500));
|
||||
sim.write_clock(clk, false);
|
||||
sim.write_reset(rst, false);
|
||||
if sim.read_bool(sim.io().ran) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert!(sim.read_bool(sim.io().ran));
|
||||
imm_index += 1;
|
||||
if imm_index >= imm_count {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_power_isa_add_sub_sim() {
|
||||
test_power_isa_alu_sim(cases_add_sub(), |sim| {
|
||||
checked_vcd_output!(sim, "tests/expected/units_formal_power_isa_add_sub_sim.vcd")
|
||||
});
|
||||
}
|
||||
|
||||
#[hdl]
|
||||
#[test]
|
||||
fn test_power_isa_add_sim() {
|
||||
|
|
@ -800,9 +1074,9 @@ fn test_power_isa_add_sim() {
|
|||
NonZero::new(20).unwrap(),
|
||||
));
|
||||
let any_consts = AnyConsts::new();
|
||||
let m = check_power_isa_alu_formal(config, cases_add_sub(), Some(any_consts));
|
||||
let m = check_power_isa_alu_formal(config, &cases_add_sub(), Some(any_consts));
|
||||
let mut sim = Simulation::new(m);
|
||||
let _checked_vcd_output = cpu::checked_vcd_output!(
|
||||
let _checked_vcd_output = checked_vcd_output!(
|
||||
&mut sim,
|
||||
"tests/expected/units_formal_power_isa_add_sim.vcd",
|
||||
);
|
||||
|
|
@ -845,9 +1119,9 @@ fn test_power_isa_paddi_sim() {
|
|||
NonZero::new(20).unwrap(),
|
||||
));
|
||||
let any_consts = AnyConsts::new();
|
||||
let m = check_power_isa_alu_formal(config, cases_add_sub(), Some(any_consts));
|
||||
let m = check_power_isa_alu_formal(config, &cases_add_sub(), Some(any_consts));
|
||||
let mut sim = Simulation::new(m);
|
||||
let _checked_vcd_output = cpu::checked_vcd_output!(
|
||||
let _checked_vcd_output = checked_vcd_output!(
|
||||
&mut sim,
|
||||
"tests/expected/units_formal_power_isa_paddi_sim.vcd",
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue