start debugging reg_alloc with simulator
All checks were successful
/ deps (push) Successful in 14s
/ test (push) Successful in 25m15s

This commit is contained in:
Jacob Lifshay 2024-12-20 00:26:16 -08:00
parent bf34dee043
commit 12481cfab3
Signed by: programmerjake
SSH key fingerprint: SHA256:HnFTLGpSm4Q4Fj502oCFisjZSoakwEuTsJJMSke63RQ
8 changed files with 1211 additions and 37 deletions

View file

@ -16,8 +16,25 @@ pub struct CpuConfig {
}
impl CpuConfig {
pub const DEFAULT_OUT_REG_NUM_WIDTH: usize = 4;
pub const DEFAULT_FETCH_WIDTH: NonZeroUsize = {
let Some(v) = NonZeroUsize::new(1) else {
unreachable!();
};
v
};
pub fn new(unit_kinds: Vec<UnitKind>) -> Self {
Self {
unit_kinds,
out_reg_num_width: Self::DEFAULT_OUT_REG_NUM_WIDTH,
fetch_width: Self::DEFAULT_FETCH_WIDTH,
}
}
pub fn non_const_unit_nums(&self) -> std::ops::Range<usize> {
(CONST_ZERO_UNIT_NUM + 1)..(self.unit_kinds.len() + 1)
}
pub fn unit_num_width(&self) -> usize {
UInt::range((CONST_ZERO_UNIT_NUM + 1)..self.unit_kinds.len()).width()
UInt::range(self.non_const_unit_nums()).width()
}
pub fn unit_num(&self) -> UnitNum<DynSize> {
UnitNum[self.unit_num_width()]

View file

@ -1,7 +1,7 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::unit::UnitMOp;
use fayalite::prelude::*;
use fayalite::{expr::ops::ArrayLiteral, intern::Interned, prelude::*};
use std::marker::PhantomData;
pub mod power_isa;
@ -20,58 +20,138 @@ pub enum OutputIntegerMode {
pub const MOP_IMM_WIDTH: usize = 34;
pub const MOP_MIN_REG_WIDTH: usize = 8;
pub const COMMON_MOP_OTHER_WIDTH: usize =
MOP_IMM_WIDTH - (COMMON_MOP_SRC_REG_COUNT - COMMON_MOP_IMM_SRC_REG_COUNT) * MOP_MIN_REG_WIDTH;
pub const COMMON_MOP_SRC_REG_COUNT: usize = 3;
pub const COMMON_MOP_IMM_SRC_REG_COUNT: usize = 2;
pub const COMMON_MOP_SRC_LEN: usize = 3;
pub const COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM: usize = 2;
pub const COMMON_MOP_IMM_LOW_WIDTH: usize = CommonMOpWithMaxSrcCount::IMM_WIDTH - 1;
#[hdl]
pub struct CommonMOp<PrefixPad: KnownSize, RegWidth: Size, SrcCount: KnownSize> {
pub prefix_pad: UIntType<PrefixPad>,
pub dest: UIntType<RegWidth>,
pub src: Array<UIntType<RegWidth>, { COMMON_MOP_SRC_REG_COUNT }>,
pub other: UInt<{ COMMON_MOP_OTHER_WIDTH }>,
pub src: Array<UIntType<RegWidth>, { COMMON_MOP_SRC_LEN }>,
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
pub imm_sign: SInt<1>,
pub _phantom: PhantomData<SrcCount>,
}
#[hdl]
pub struct CommonMOpImmParts<ImmInSrcCount: Size> {
// fields must be in this exact order
pub imm_low: UInt<{ COMMON_MOP_IMM_LOW_WIDTH }>,
pub reversed_src: ArrayType<UInt<{ MOP_MIN_REG_WIDTH }>, ImmInSrcCount>,
pub imm_sign: SInt<1>,
}
type CommonMOpWithMaxSrcCount = CommonMOpForImm<{ COMMON_MOP_SRC_LEN }>;
type CommonMOpForImm<const SRC_COUNT: usize> =
CommonMOp<ConstUsize<0>, ConstUsize<{ MOP_MIN_REG_WIDTH }>, ConstUsize<SRC_COUNT>>;
pub const COMMON_MOP_0_IMM_WIDTH: usize = CommonMOpForImm::<0>::IMM_WIDTH;
pub const COMMON_MOP_1_IMM_WIDTH: usize = CommonMOpForImm::<1>::IMM_WIDTH;
pub const COMMON_MOP_2_IMM_WIDTH: usize = CommonMOpForImm::<2>::IMM_WIDTH;
pub const COMMON_MOP_3_IMM_WIDTH: usize = CommonMOpForImm::<3>::IMM_WIDTH;
const COMMON_MOP_0_IMM_IN_SRC_COUNT: usize = CommonMOpForImm::<0>::IMM_IN_SRC_COUNT;
impl<PrefixPad: KnownSize, RegWidth: Size, SrcCount: KnownSize>
CommonMOp<PrefixPad, RegWidth, SrcCount>
{
pub fn imm_ty(self) -> SInt {
assert!(self.src.element().width() >= MOP_MIN_REG_WIDTH);
assert!(SrcCount::VALUE <= COMMON_MOP_SRC_REG_COUNT);
SInt[(COMMON_MOP_SRC_REG_COUNT - SrcCount::VALUE) * MOP_MIN_REG_WIDTH
+ COMMON_MOP_OTHER_WIDTH]
pub const IMM_IN_SRC_COUNT: usize = {
assert!(SrcCount::VALUE <= COMMON_MOP_SRC_LEN, "too many sources");
const _: () = assert!(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM <= COMMON_MOP_SRC_LEN);
(COMMON_MOP_SRC_LEN - COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM)
- SrcCount::VALUE.saturating_sub(COMMON_MOP_MIN_SRC_LEN_WITH_FULL_IMM)
};
pub const IMM_IN_SRC_RANGE: std::ops::Range<usize> =
(COMMON_MOP_SRC_LEN - Self::IMM_IN_SRC_COUNT)..COMMON_MOP_SRC_LEN;
pub const IMM_WIDTH: usize = {
MOP_IMM_WIDTH - (COMMON_MOP_0_IMM_IN_SRC_COUNT - Self::IMM_IN_SRC_COUNT) * MOP_MIN_REG_WIDTH
};
pub fn imm_ty() -> SInt {
SInt::new(Self::IMM_WIDTH)
}
pub fn imm_parts_ty() -> CommonMOpImmParts<DynSize> {
let retval = CommonMOpImmParts[Self::IMM_IN_SRC_COUNT];
assert_eq!(
retval.canonical().bit_width(),
Self::IMM_WIDTH,
"{retval:#?}"
);
retval
}
#[hdl]
pub fn new(
prefix_pad: impl ToExpr<Type = UIntType<PrefixPad>>,
dest: impl ToExpr<Type = UIntType<RegWidth>>,
src: impl ToExpr<Type = ArrayType<UIntType<RegWidth>, SrcCount>>,
imm: impl ToExpr<Type = SInt>,
) -> Expr<Self> {
let prefix_pad = prefix_pad.to_expr();
let dest = dest.to_expr();
let src_in = src.to_expr();
let imm = imm.to_expr();
assert_eq!(Expr::ty(imm), Self::imm_ty());
let reg_ty = Expr::ty(dest);
assert_eq!(reg_ty, Expr::ty(src_in).element());
let imm_parts = imm.cast_to_bits().cast_bits_to(Self::imm_parts_ty());
let mut src = [0_hdl_u0.cast_to(reg_ty); COMMON_MOP_SRC_LEN];
for i in 0..SrcCount::VALUE {
src[i] = src_in[i];
}
for (reversed_src_index, src_index) in Self::IMM_IN_SRC_RANGE.rev().enumerate() {
src[src_index] = imm_parts.reversed_src[reversed_src_index].cast_to(reg_ty);
}
#[hdl]
Self {
prefix_pad,
dest,
src: ArrayLiteral::new(
reg_ty,
Interned::from_iter(src.iter().map(|v| Expr::canonical(*v))),
)
.to_expr(),
imm_low: Expr::from_dyn_int(imm[..COMMON_MOP_IMM_LOW_WIDTH]),
imm_sign: Expr::from_dyn_int(imm >> (Self::IMM_WIDTH - 1)),
_phantom: PhantomData,
}
}
#[hdl]
pub fn imm(expr: impl ToExpr<Type = Self>) -> Expr<SInt> {
let expr = expr.to_expr();
assert!(Expr::ty(expr).src.element().width() >= MOP_MIN_REG_WIDTH);
let mut acc = expr.other[..COMMON_MOP_OTHER_WIDTH - 1];
for i in SrcCount::VALUE..COMMON_MOP_SRC_REG_COUNT {
acc = (acc, expr.src[i][..MOP_MIN_REG_WIDTH]).cast_to_bits();
}
acc = (acc, expr.other[COMMON_MOP_OTHER_WIDTH - 1]).cast_to_bits();
#[hdl]
let imm = wire(Expr::ty(expr).imm_ty());
debug_assert_eq!(Expr::ty(acc).width(), Expr::ty(imm).width());
connect(imm, acc.cast_to(Expr::ty(imm)));
imm
let reversed_src = Vec::from_iter(
Self::IMM_IN_SRC_RANGE
.rev()
.map(|src_index| expr.src[src_index].cast_to_static()),
);
let imm_parts = {
#[hdl]
CommonMOpImmParts {
imm_low: expr.imm_low,
reversed_src,
imm_sign: expr.imm_sign,
}
};
imm_parts.cast_to_bits().cast_bits_to(Self::imm_ty())
}
#[hdl]
pub fn connect_to_imm(expr: impl ToExpr<Type = Self>, imm: impl ToExpr<Type = SInt>) {
let expr = expr.to_expr();
let reg_ty = Expr::ty(expr).dest;
assert_eq!(reg_ty, Expr::ty(expr).src.element());
let imm = imm.to_expr();
let imm_ty = Expr::ty(expr).imm_ty();
assert_eq!(Expr::ty(imm), imm_ty);
let mut pos = COMMON_MOP_OTHER_WIDTH - 1;
connect_any(
expr.other,
(imm[..pos], imm[imm_ty.width() - 1]).cast_to_bits(),
);
for i in SrcCount::VALUE..COMMON_MOP_SRC_REG_COUNT {
connect_any(expr.src[i], imm[pos..pos + MOP_MIN_REG_WIDTH]);
pos += MOP_MIN_REG_WIDTH;
assert_eq!(Expr::ty(imm), Self::imm_ty());
let imm_parts = imm.cast_to_bits().cast_bits_to(Self::imm_parts_ty());
let mut src = [Some(0_hdl_u0.cast_to(reg_ty)); COMMON_MOP_SRC_LEN];
for i in 0..SrcCount::VALUE {
src[i] = None;
}
for (reversed_src_index, src_index) in Self::IMM_IN_SRC_RANGE.rev().enumerate() {
src[src_index] = Some(imm_parts.reversed_src[reversed_src_index].cast_to(reg_ty));
}
for i in 0..COMMON_MOP_SRC_LEN {
if let Some(v) = src[i] {
connect(expr.src[i], v);
}
}
}
}

View file

@ -2,9 +2,9 @@
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
instruction::{MOp, UnitNum},
instruction::MOp,
unit::{TrapData, UnitTrait},
util::tree_reduce::{tree_reduce, tree_reduce_with_state},
util::tree_reduce::tree_reduce_with_state,
};
use fayalite::{module::instance_with_loc, prelude::*, util::ready_valid::ReadyValid};
use std::num::NonZeroUsize;
@ -124,5 +124,13 @@ pub fn reg_alloc(config: &CpuConfig) {
);
connect(unit_free_regs_tracker.cd, cd);
// TODO: finish
connect(
unit_free_regs_tracker.free_in[0].data,
HdlOption[UInt[config.out_reg_num_width]].uninit(), // FIXME: just for debugging
);
connect(
unit_free_regs_tracker.alloc_out[0].ready,
Bool.uninit(), // FIXME: just for debugging
);
}
}

View file

@ -13,6 +13,8 @@ use fayalite::{
util::ready_valid::ReadyValid,
};
pub mod alu_branch;
macro_rules! all_units {
(
#[hdl_unit_kind = $HdlUnitKind:ident]
@ -107,7 +109,7 @@ all_units! {
#[unit_kind = UnitKind]
#[hdl]
pub enum UnitMOp<RegWidth: Size> {
#[create_dyn_unit_fn = |config| todo!()]
#[create_dyn_unit_fn = |config| alu_branch::AluBranch::new(config).to_dyn()]
AluBranch(AluBranchMOp<RegWidth>),
#[create_dyn_unit_fn = |config| todo!()]
L2RegisterFile(L2RegisterFileMOp<RegWidth>),

View file

@ -0,0 +1,83 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use crate::{
config::CpuConfig,
instruction::AluBranchMOp,
unit::{DynUnit, DynUnitWrapper, UnitCancelInput, UnitKind, UnitOutput, UnitTrait},
};
use fayalite::{
intern::{Intern, Interned},
prelude::*,
util::ready_valid::ReadyValid,
};
#[hdl_module]
pub fn alu_branch(config: &CpuConfig) {
#[hdl]
let cd: ClockDomain = m.input();
// TODO: finish
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct AluBranch {
config: Interned<CpuConfig>,
module: Interned<Module<alu_branch>>,
}
impl AluBranch {
pub fn new(config: &CpuConfig) -> Self {
Self {
config: config.intern(),
module: alu_branch(config),
}
}
}
impl UnitTrait for AluBranch {
type Type = alu_branch;
type ExtraOut = ();
type MOp = AluBranchMOp<DynSize>;
fn ty(&self) -> Self::Type {
self.module.io_ty()
}
fn extra_out_ty(&self) -> Self::ExtraOut {
()
}
fn mop_ty(&self) -> Self::MOp {
AluBranchMOp[self.config.p_reg_num().canonical().bit_width()]
}
fn unit_kind(&self) -> UnitKind {
UnitKind::AluBranch
}
fn make_module(&self) -> Interned<Module<Self::Type>> {
self.module
}
fn cancel_input(
&self,
this: Expr<Self::Type>,
) -> Expr<ReadyValid<UnitCancelInput<DynSize, DynSize>>> {
todo!()
}
fn output(
&self,
this: Expr<Self::Type>,
) -> Expr<ReadyValid<UnitOutput<DynSize, DynSize, Self::ExtraOut>>> {
todo!()
}
fn cd(&self, this: Expr<Self::Type>) -> Expr<ClockDomain> {
this.cd
}
fn to_dyn(&self) -> DynUnit {
DynUnitWrapper(*self).to_dyn()
}
}

View file

@ -0,0 +1,880 @@
$timescale 1 ps $end
$scope module reg_alloc $end
$scope struct cd $end
$var wire 1 ! clk $end
$var wire 1 " rst $end
$upscope $end
$scope struct fetch_decode_interface $end
$scope struct decoded_insns $end
$scope struct [0] $end
$scope struct data $end
$var string 1 # \$tag $end
$scope struct HdlSome $end
$scope struct uop $end
$var string 1 $ \$tag $end
$scope struct AluBranch $end
$var string 1 % \$tag $end
$scope struct AddSub $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 & prefix_pad $end
$var wire 8 ' dest $end
$scope struct src $end
$var wire 8 ( \[0] $end
$var wire 8 ) \[1] $end
$var wire 8 * \[2] $end
$upscope $end
$var wire 25 + imm_low $end
$var wire 1 , imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 - output_integer_mode $end
$upscope $end
$var wire 1 . invert_src0 $end
$var wire 1 / invert_carry_in $end
$var wire 1 0 invert_carry_out $end
$var wire 1 1 add_pc $end
$upscope $end
$scope struct AddSubI $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 2 prefix_pad $end
$var wire 8 3 dest $end
$scope struct src $end
$var wire 8 4 \[0] $end
$var wire 8 5 \[1] $end
$var wire 8 6 \[2] $end
$upscope $end
$var wire 25 7 imm_low $end
$var wire 1 8 imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 9 output_integer_mode $end
$upscope $end
$var wire 1 : invert_src0 $end
$var wire 1 ; invert_carry_in $end
$var wire 1 < invert_carry_out $end
$var wire 1 = add_pc $end
$upscope $end
$scope struct Logical $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 > prefix_pad $end
$var wire 8 ? dest $end
$scope struct src $end
$var wire 8 @ \[0] $end
$var wire 8 A \[1] $end
$var wire 8 B \[2] $end
$upscope $end
$var wire 25 C imm_low $end
$var wire 1 D imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 E output_integer_mode $end
$upscope $end
$var wire 4 F lut $end
$upscope $end
$upscope $end
$scope struct L2RegisterFile $end
$var string 1 G \$tag $end
$scope struct ReadL2Reg $end
$scope struct common $end
$var wire 1 H prefix_pad $end
$var wire 8 I dest $end
$scope struct src $end
$var wire 8 J \[0] $end
$var wire 8 K \[1] $end
$var wire 8 L \[2] $end
$upscope $end
$var wire 25 M imm_low $end
$var wire 1 N imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$scope struct WriteL2Reg $end
$scope struct common $end
$var wire 1 O prefix_pad $end
$var wire 8 P dest $end
$scope struct src $end
$var wire 8 Q \[0] $end
$var wire 8 R \[1] $end
$var wire 8 S \[2] $end
$upscope $end
$var wire 25 T imm_low $end
$var wire 1 U imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$scope struct LoadStore $end
$var string 1 V \$tag $end
$scope struct Load $end
$var wire 1 W prefix_pad $end
$var wire 8 X dest $end
$scope struct src $end
$var wire 8 Y \[0] $end
$var wire 8 Z \[1] $end
$var wire 8 [ \[2] $end
$upscope $end
$var wire 25 \ imm_low $end
$var wire 1 ] imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$scope struct Store $end
$var wire 1 ^ prefix_pad $end
$var wire 8 _ dest $end
$scope struct src $end
$var wire 8 ` \[0] $end
$var wire 8 a \[1] $end
$var wire 8 b \[2] $end
$upscope $end
$var wire 25 c imm_low $end
$var wire 1 d imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$var wire 1 e is_unrelated_pc $end
$var wire 64 f pc $end
$upscope $end
$upscope $end
$var wire 1 g ready $end
$upscope $end
$scope struct [1] $end
$scope struct data $end
$var string 1 h \$tag $end
$scope struct HdlSome $end
$scope struct uop $end
$var string 1 i \$tag $end
$scope struct AluBranch $end
$var string 1 j \$tag $end
$scope struct AddSub $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 k prefix_pad $end
$var wire 8 l dest $end
$scope struct src $end
$var wire 8 m \[0] $end
$var wire 8 n \[1] $end
$var wire 8 o \[2] $end
$upscope $end
$var wire 25 p imm_low $end
$var wire 1 q imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 r output_integer_mode $end
$upscope $end
$var wire 1 s invert_src0 $end
$var wire 1 t invert_carry_in $end
$var wire 1 u invert_carry_out $end
$var wire 1 v add_pc $end
$upscope $end
$scope struct AddSubI $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 w prefix_pad $end
$var wire 8 x dest $end
$scope struct src $end
$var wire 8 y \[0] $end
$var wire 8 z \[1] $end
$var wire 8 { \[2] $end
$upscope $end
$var wire 25 | imm_low $end
$var wire 1 } imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 ~ output_integer_mode $end
$upscope $end
$var wire 1 !" invert_src0 $end
$var wire 1 "" invert_carry_in $end
$var wire 1 #" invert_carry_out $end
$var wire 1 $" add_pc $end
$upscope $end
$scope struct Logical $end
$scope struct alu_common $end
$scope struct common $end
$var string 0 %" prefix_pad $end
$var wire 8 &" dest $end
$scope struct src $end
$var wire 8 '" \[0] $end
$var wire 8 (" \[1] $end
$var wire 8 )" \[2] $end
$upscope $end
$var wire 25 *" imm_low $end
$var wire 1 +" imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$var string 1 ," output_integer_mode $end
$upscope $end
$var wire 4 -" lut $end
$upscope $end
$upscope $end
$scope struct L2RegisterFile $end
$var string 1 ." \$tag $end
$scope struct ReadL2Reg $end
$scope struct common $end
$var wire 1 /" prefix_pad $end
$var wire 8 0" dest $end
$scope struct src $end
$var wire 8 1" \[0] $end
$var wire 8 2" \[1] $end
$var wire 8 3" \[2] $end
$upscope $end
$var wire 25 4" imm_low $end
$var wire 1 5" imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$scope struct WriteL2Reg $end
$scope struct common $end
$var wire 1 6" prefix_pad $end
$var wire 8 7" dest $end
$scope struct src $end
$var wire 8 8" \[0] $end
$var wire 8 9" \[1] $end
$var wire 8 :" \[2] $end
$upscope $end
$var wire 25 ;" imm_low $end
$var wire 1 <" imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$scope struct LoadStore $end
$var string 1 =" \$tag $end
$scope struct Load $end
$var wire 1 >" prefix_pad $end
$var wire 8 ?" dest $end
$scope struct src $end
$var wire 8 @" \[0] $end
$var wire 8 A" \[1] $end
$var wire 8 B" \[2] $end
$upscope $end
$var wire 25 C" imm_low $end
$var wire 1 D" imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$scope struct Store $end
$var wire 1 E" prefix_pad $end
$var wire 8 F" dest $end
$scope struct src $end
$var wire 8 G" \[0] $end
$var wire 8 H" \[1] $end
$var wire 8 I" \[2] $end
$upscope $end
$var wire 25 J" imm_low $end
$var wire 1 K" imm_sign $end
$scope struct _phantom $end
$upscope $end
$upscope $end
$upscope $end
$upscope $end
$var wire 1 L" is_unrelated_pc $end
$var wire 64 M" pc $end
$upscope $end
$upscope $end
$var wire 1 N" ready $end
$upscope $end
$upscope $end
$scope struct fetch_decode_special_op $end
$scope struct data $end
$var string 1 O" \$tag $end
$scope struct HdlSome $end
$var string 1 P" \$tag $end
$scope struct Trap $end
$upscope $end
$upscope $end
$upscope $end
$var wire 1 Q" ready $end
$upscope $end
$upscope $end
$scope struct available_units $end
$scope struct [0] $end
$var wire 1 R" \[0] $end
$upscope $end
$scope struct [1] $end
$var wire 1 S" \[0] $end
$upscope $end
$upscope $end
$scope struct selected_unit_nums $end
$scope struct [0] $end
$var string 1 T" \$tag $end
$scope struct HdlSome $end
$var wire 1 U" value $end
$upscope $end
$upscope $end
$scope struct [1] $end
$var string 1 V" \$tag $end
$scope struct HdlSome $end
$var wire 1 W" value $end
$upscope $end
$upscope $end
$upscope $end
$var string 1 X" unit_kind $end
$scope struct available_units_for_kind $end
$var wire 1 Y" \[0] $end
$upscope $end
$scope struct selected_unit_leaf $end
$var string 1 Z" \$tag $end
$scope struct HdlSome $end
$var wire 1 [" value $end
$upscope $end
$upscope $end
$scope struct unit_num $end
$var wire 1 \" value $end
$upscope $end
$var string 1 ]" unit_kind $end
$scope struct available_units_for_kind $end
$var wire 1 ^" \[0] $end
$upscope $end
$scope struct selected_unit_leaf $end
$var string 1 _" \$tag $end
$scope struct HdlSome $end
$var wire 1 `" value $end
$upscope $end
$upscope $end
$scope struct unit_num $end
$var wire 1 a" value $end
$upscope $end
$scope struct unit_0 $end
$scope struct cd $end
$var wire 1 d" clk $end
$var wire 1 e" rst $end
$upscope $end
$upscope $end
$scope module alu_branch $end
$scope struct cd $end
$var wire 1 b" clk $end
$var wire 1 c" rst $end
$upscope $end
$upscope $end
$scope struct unit_0_free_regs_tracker $end
$scope struct cd $end
$var wire 1 Q# clk $end
$var wire 1 R# rst $end
$upscope $end
$scope struct free_in $end
$scope struct [0] $end
$scope struct data $end
$var string 1 S# \$tag $end
$var wire 4 T# HdlSome $end
$upscope $end
$var wire 1 U# ready $end
$upscope $end
$upscope $end
$scope struct alloc_out $end
$scope struct [0] $end
$scope struct data $end
$var string 1 V# \$tag $end
$var wire 4 W# HdlSome $end
$upscope $end
$var wire 1 X# ready $end
$upscope $end
$upscope $end
$upscope $end
$scope module unit_free_regs_tracker $end
$scope struct cd $end
$var wire 1 f" clk $end
$var wire 1 g" rst $end
$upscope $end
$scope struct free_in $end
$scope struct [0] $end
$scope struct data $end
$var string 1 h" \$tag $end
$var wire 4 i" HdlSome $end
$upscope $end
$var wire 1 j" ready $end
$upscope $end
$upscope $end
$scope struct alloc_out $end
$scope struct [0] $end
$scope struct data $end
$var string 1 k" \$tag $end
$var wire 4 l" HdlSome $end
$upscope $end
$var wire 1 m" ready $end
$upscope $end
$upscope $end
$scope struct allocated_reg $end
$var reg 1 n" \[0] $end
$var reg 1 o" \[1] $end
$var reg 1 p" \[2] $end
$var reg 1 q" \[3] $end
$var reg 1 r" \[4] $end
$var reg 1 s" \[5] $end
$var reg 1 t" \[6] $end
$var reg 1 u" \[7] $end
$var reg 1 v" \[8] $end
$var reg 1 w" \[9] $end
$var reg 1 x" \[10] $end
$var reg 1 y" \[11] $end
$var reg 1 z" \[12] $end
$var reg 1 {" \[13] $end
$var reg 1 |" \[14] $end
$var reg 1 }" \[15] $end
$upscope $end
$scope struct firing_data $end
$var string 1 ~" \$tag $end
$var wire 4 !# HdlSome $end
$upscope $end
$var wire 1 "# reduced_count_0_2 $end
$var wire 1 ## reduced_count_overflowed_0_2 $end
$scope struct reduced_alloc_nums_0_2 $end
$var wire 1 $# \[0] $end
$upscope $end
$var wire 1 %# reduced_count_2_4 $end
$var wire 1 &# reduced_count_overflowed_2_4 $end
$scope struct reduced_alloc_nums_2_4 $end
$var wire 1 '# \[0] $end
$upscope $end
$var wire 1 (# reduced_count_0_4 $end
$var wire 1 )# reduced_count_overflowed_0_4 $end
$scope struct reduced_alloc_nums_0_4 $end
$var wire 2 *# \[0] $end
$upscope $end
$var wire 1 +# reduced_count_4_6 $end
$var wire 1 ,# reduced_count_overflowed_4_6 $end
$scope struct reduced_alloc_nums_4_6 $end
$var wire 1 -# \[0] $end
$upscope $end
$var wire 1 .# reduced_count_6_8 $end
$var wire 1 /# reduced_count_overflowed_6_8 $end
$scope struct reduced_alloc_nums_6_8 $end
$var wire 1 0# \[0] $end
$upscope $end
$var wire 1 1# reduced_count_4_8 $end
$var wire 1 2# reduced_count_overflowed_4_8 $end
$scope struct reduced_alloc_nums_4_8 $end
$var wire 2 3# \[0] $end
$upscope $end
$var wire 1 4# reduced_count_0_8 $end
$var wire 1 5# reduced_count_overflowed_0_8 $end
$scope struct reduced_alloc_nums_0_8 $end
$var wire 3 6# \[0] $end
$upscope $end
$var wire 1 7# reduced_count_8_10 $end
$var wire 1 8# reduced_count_overflowed_8_10 $end
$scope struct reduced_alloc_nums_8_10 $end
$var wire 1 9# \[0] $end
$upscope $end
$var wire 1 :# reduced_count_10_12 $end
$var wire 1 ;# reduced_count_overflowed_10_12 $end
$scope struct reduced_alloc_nums_10_12 $end
$var wire 1 <# \[0] $end
$upscope $end
$var wire 1 =# reduced_count_8_12 $end
$var wire 1 ># reduced_count_overflowed_8_12 $end
$scope struct reduced_alloc_nums_8_12 $end
$var wire 2 ?# \[0] $end
$upscope $end
$var wire 1 @# reduced_count_12_14 $end
$var wire 1 A# reduced_count_overflowed_12_14 $end
$scope struct reduced_alloc_nums_12_14 $end
$var wire 1 B# \[0] $end
$upscope $end
$var wire 1 C# reduced_count_14_16 $end
$var wire 1 D# reduced_count_overflowed_14_16 $end
$scope struct reduced_alloc_nums_14_16 $end
$var wire 1 E# \[0] $end
$upscope $end
$var wire 1 F# reduced_count_12_16 $end
$var wire 1 G# reduced_count_overflowed_12_16 $end
$scope struct reduced_alloc_nums_12_16 $end
$var wire 2 H# \[0] $end
$upscope $end
$var wire 1 I# reduced_count_8_16 $end
$var wire 1 J# reduced_count_overflowed_8_16 $end
$scope struct reduced_alloc_nums_8_16 $end
$var wire 3 K# \[0] $end
$upscope $end
$var wire 1 L# reduced_count_0_16 $end
$var wire 1 M# reduced_count_overflowed_0_16 $end
$scope struct reduced_alloc_nums_0_16 $end
$var wire 4 N# \[0] $end
$upscope $end
$scope struct firing_data $end
$var string 1 O# \$tag $end
$var wire 4 P# HdlSome $end
$upscope $end
$upscope $end
$upscope $end
$enddefinitions $end
$dumpvars
0!
1"
sHdlSome\x20(1) #
sAluBranch\x20(0) $
sAddSub\x20(0) %
s0 &
b1 '
b10 (
b11 )
b100 *
b1001000110100 +
0,
sFull64\x20(0) -
1.
1/
10
11
s0 2
b1 3
b10 4
b11 5
b100 6
b1001000110100 7
08
sFull64\x20(0) 9
1:
1;
1<
1=
s0 >
b1 ?
b10 @
b11 A
b100 B
b1001000110100 C
0D
sFull64\x20(0) E
b1111 F
sReadL2Reg\x20(0) G
0H
b1 I
b10 J
b11 K
b100 L
b1001000110100 M
0N
0O
b1 P
b10 Q
b11 R
b100 S
b1001000110100 T
0U
sLoad\x20(0) V
0W
b1 X
b10 Y
b11 Z
b100 [
b1001000110100 \
0]
0^
b1 _
b10 `
b11 a
b100 b
b1001000110100 c
0d
1e
b1000000000000 f
1g
sHdlSome\x20(1) h
sAluBranch\x20(0) i
sLogical\x20(2) j
s0 k
b10 l
b11 m
b100 n
b0 o
b0 p
0q
sFull64\x20(0) r
0s
1t
1u
0v
s0 w
b10 x
b11 y
b100 z
b0 {
b0 |
0}
sFull64\x20(0) ~
0!"
1""
1#"
0$"
s0 %"
b10 &"
b11 '"
b100 ("
b0 )"
b0 *"
0+"
sFull64\x20(0) ,"
b110 -"
sReadL2Reg\x20(0) ."
1/"
b10 0"
b11 1"
b100 2"
b0 3"
b0 4"
05"
16"
b10 7"
b11 8"
b100 9"
b0 :"
b0 ;"
0<"
sLoad\x20(0) ="
1>"
b10 ?"
b11 @"
b100 A"
b0 B"
b0 C"
0D"
1E"
b10 F"
b11 G"
b100 H"
b0 I"
b0 J"
0K"
0L"
b1000000000100 M"
1N"
sHdlNone\x20(0) O"
sTrap\x20(0) P"
1Q"
1R"
1S"
sHdlSome\x20(1) T"
0U"
sHdlSome\x20(1) V"
0W"
sAluBranch\x20(0) X"
1Y"
sHdlSome\x20(1) Z"
0["
0\"
sAluBranch\x20(0) ]"
1^"
sHdlSome\x20(1) _"
0`"
0a"
0b"
1c"
0d"
1e"
0f"
1g"
sHdlNone\x20(0) h"
b0 i"
1j"
sHdlSome\x20(1) k"
b0 l"
0m"
0n"
0o"
0p"
0q"
0r"
0s"
0t"
0u"
0v"
0w"
0x"
0y"
0z"
0{"
0|"
0}"
sHdlNone\x20(0) ~"
b0 !#
0"#
1##
0$#
0%#
1&#
0'#
0(#
1)#
b0 *#
0+#
1,#
0-#
0.#
1/#
00#
01#
12#
b0 3#
04#
15#
b0 6#
07#
18#
09#
0:#
1;#
0<#
0=#
1>#
b0 ?#
0@#
1A#
0B#
0C#
1D#
0E#
0F#
1G#
b0 H#
0I#
1J#
b0 K#
0L#
1M#
b0 N#
sHdlNone\x20(0) O#
b0 P#
0Q#
1R#
sHdlNone\x20(0) S#
b0 T#
1U#
sHdlSome\x20(1) V#
b0 W#
0X#
$end
#500000
1!
1b"
1d"
1f"
1Q#
#1000000
0!
0"
0b"
0c"
0d"
0e"
0f"
0g"
0Q#
0R#
#1500000
1!
1b"
1d"
1f"
1Q#
#2000000
0!
0b"
0d"
0f"
0Q#
#2500000
1!
1b"
1d"
1f"
1Q#
#3000000
0!
0b"
0d"
0f"
0Q#
#3500000
1!
1b"
1d"
1f"
1Q#
#4000000
0!
0b"
0d"
0f"
0Q#
#4500000
1!
1b"
1d"
1f"
1Q#
#5000000
0!
0b"
0d"
0f"
0Q#
#5500000
1!
1b"
1d"
1f"
1Q#
#6000000
0!
0b"
0d"
0f"
0Q#
#6500000
1!
1b"
1d"
1f"
1Q#
#7000000
0!
0b"
0d"
0f"
0Q#
#7500000
1!
1b"
1d"
1f"
1Q#
#8000000
0!
0b"
0d"
0f"
0Q#
#8500000
1!
1b"
1d"
1f"
1Q#
#9000000
0!
0b"
0d"
0f"
0Q#
#9500000
1!
1b"
1d"
1f"
1Q#
#10000000

View file

@ -0,0 +1,101 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
// See Notices.txt for copyright information
use cpu::{
config::CpuConfig,
instruction::{
AddSubMOp, AluCommonMOp, CommonMOp, LogicalMOp, MOp, OutputIntegerMode,
COMMON_MOP_2_IMM_WIDTH, COMMON_MOP_3_IMM_WIDTH,
},
reg_alloc::{reg_alloc, FetchedDecodedMOp},
unit::UnitKind,
};
use fayalite::{
prelude::*,
sim::{time::SimDuration, vcd::VcdWriterDecls, Simulation},
util::RcWriter,
};
use std::num::NonZeroUsize;
#[hdl]
#[test]
fn test_reg_alloc() {
let _n = SourceLocation::normalize_files_for_tests();
let mut config = CpuConfig::new(vec![UnitKind::AluBranch]);
config.fetch_width = NonZeroUsize::new(2).unwrap();
let mut sim = Simulation::new(reg_alloc(&config));
let mut writer = RcWriter::default();
sim.add_trace_writer(VcdWriterDecls::new(writer.clone()));
let fetch_decode_interface = sim.io().fetch_decode_interface;
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, true);
sim.write_bool(fetch_decode_interface.fetch_decode_special_op.ready, true);
sim.write(
fetch_decode_interface.decoded_insns[0].data,
HdlSome(
#[hdl]
FetchedDecodedMOp {
uop: MOp.AluBranch(MOp.AluBranch.AddSub(
#[hdl]
AddSubMOp {
alu_common: #[hdl]
AluCommonMOp {
common: CommonMOp::new(
0_hdl_u0,
1u8,
[2u8, 3u8, 4u8],
0x1234.cast_to(SInt[COMMON_MOP_3_IMM_WIDTH]),
),
output_integer_mode: OutputIntegerMode.Full64(),
},
invert_src0: true,
invert_carry_in: true,
invert_carry_out: true,
add_pc: true,
},
)),
is_unrelated_pc: true,
pc: 0x1000_hdl_u64,
},
),
);
sim.write(
fetch_decode_interface.decoded_insns[1].data,
HdlSome(
#[hdl]
FetchedDecodedMOp {
uop: MOp.AluBranch(MOp.AluBranch.Logical(
#[hdl]
LogicalMOp {
alu_common: #[hdl]
AluCommonMOp {
common: CommonMOp::new(
0_hdl_u0,
2u8,
[3u8, 4u8],
SInt[COMMON_MOP_2_IMM_WIDTH].zero(),
),
output_integer_mode: OutputIntegerMode.Full64(),
},
lut: 0b0110_hdl_u4,
},
)),
is_unrelated_pc: false,
pc: 0x1004_hdl_u64,
},
),
);
for cycle in 0..10 {
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, true);
sim.advance_time(SimDuration::from_nanos(500));
sim.write_clock(sim.io().cd.clk, false);
sim.write_reset(sim.io().cd.rst, false);
}
// FIXME: vcd is just whatever reg_alloc does now, which isn't known to be correct
let vcd = String::from_utf8(writer.take()).unwrap();
println!("####### VCD:\n{vcd}\n#######");
if vcd != include_str!("expected/reg_alloc.vcd") {
panic!();
}
}

View file

@ -45,6 +45,9 @@ function main()
*/LICENSE.md|*/Notices.txt)
# copyright file
;;
/crates/cpu/tests/expected/*.vcd)
# file that can't contain copyright header
;;
/.forgejo/workflows/*.yml|*/.gitignore|*.toml)
check_file "$file" "${POUND_HEADER[@]}"
;;