Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement zicond #747

Merged
merged 11 commits into from
Nov 26, 2024
2 changes: 2 additions & 0 deletions coreblocks/arch/isa.py
Hazardu marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ class Extension(enum.IntFlag):
ZICNTR = auto()
#: Enables hardware performance counters
ZIHPM = auto()
#: Integer conditional operations
ZICOND = auto()
#: Misaligned atomic operations
ZAM = auto()
#: Half precision floating-point operations (16-bit)
Expand Down
5 changes: 3 additions & 2 deletions coreblocks/arch/isa_consts.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ class Funct3(IntEnum, shape=3):
W = SLT = CSRRS = MULHSU = SH1ADD = CLMULR = _EBREAKPOINT = 0b010
D = SLTU = CSRRC = MULHU = CLMULH = _EINSTRPAGEFAULT = 0b011
BLT = BU = XOR = DIV = DIVW = SH2ADD = MIN = XNOR = ZEXTH = 0b100
BGE = HU = SR = CSRRWI = DIVU = DIVUW = BEXT = ORCB = REV8 = ROR = MINU = 0b101
BGE = HU = SR = CSRRWI = DIVU = DIVUW = BEXT = ORCB = REV8 = ROR = MINU = CZEROEQZ = 0b101
BLTU = OR = CSRRSI = REM = REMW = SH3ADD = MAX = ORN = 0b110
BGEU = AND = CSRRCI = REMU = REMUW = ANDN = MAXU = 0b111
BGEU = AND = CSRRCI = REMU = REMUW = ANDN = MAXU = CZERONEZ = 0b111


class Funct7(IntEnum, shape=7):
Expand All @@ -67,6 +67,7 @@ class Funct7(IntEnum, shape=7):
BINV = REV8 = 0b0110100
BSET = ORCB = 0b0010100
MAX = MIN = CLMUL = 0b0000101
CZERO = 0b0000111
ROL = ROR = SEXTB = SEXTH = CPOP = CLZ = CTZ = 0b0110000
ZEXTH = 0b0000100
SFENCEVMA = 0b0001001
Expand Down
4 changes: 4 additions & 0 deletions coreblocks/arch/optypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class OpType(IntEnum):
CLMUL = auto()
SRET = auto()
SFENCEVMA = auto()
CZERO = auto()
#: Internal Coreblocks OpType, specifing that instruction caused Exception before FU execution
EXCEPTION = auto()

Expand Down Expand Up @@ -154,6 +155,9 @@ def is_jalr(val: ValueLike) -> Value:
OpType.SRET,
OpType.SFENCEVMA,
],
Extension.ZICOND: [
OpType.CZERO,
],
}


Expand Down
4 changes: 4 additions & 0 deletions coreblocks/frontend/decoder/instr_description.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,4 +204,8 @@ class Encoding:
Opcode.SYSTEM, Funct3.PRIV, Funct7.SFENCEVMA, rd_zero=True, instr_type_override=InstrType.R
), # sfence.vma
],
OpType.CZERO: [
Encoding(Opcode.OP, Funct3.CZEROEQZ, Funct7.CZERO),
Encoding(Opcode.OP, Funct3.CZERONEZ, Funct7.CZERO),
],
}
31 changes: 28 additions & 3 deletions coreblocks/func_blocks/fu/alu.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@


class AluFn(DecoderManager):
def __init__(self, zba_enable=False, zbb_enable=False) -> None:
def __init__(self, zba_enable=False, zbb_enable=False, zicond_enable=False) -> None:
Hazardu marked this conversation as resolved.
Show resolved Hide resolved
self.zba_enable = zba_enable
self.zbb_enable = zbb_enable
self.zicond_enable = zicond_enable

class Fn(IntFlag):
ADD = auto() # Addition
Expand Down Expand Up @@ -60,6 +61,10 @@ class Fn(IntFlag):
ORCB = auto() # Bitwise or combine
REV8 = auto() # Reverse byte ordering

# ZICOND extension
CZEROEQZ = auto() # Move zero if condition if equal to zero
CZERONEZ = auto() # Move zero if condition is nonzero

def get_instructions(self) -> Sequence[tuple]:
return (
[
Expand Down Expand Up @@ -95,6 +100,11 @@ def get_instructions(self) -> Sequence[tuple]:
(self.Fn.CPOP, OpType.UNARY_BIT_MANIPULATION_5, Funct3.CPOP),
]
* self.zbb_enable
+ [
(self.Fn.CZEROEQZ, OpType.CZERO, Funct3.CZEROEQZ),
(self.Fn.CZERONEZ, OpType.CZERO, Funct3.CZERONEZ),
]
* self.zicond_enable
)


Expand All @@ -114,6 +124,7 @@ class Alu(Elaboratable):
def __init__(self, gen_params: GenParams, alu_fn=AluFn()):
self.zba_enable = alu_fn.zba_enable
self.zbb_enable = alu_fn.zbb_enable
self.zicond_enable = alu_fn.zicond_enable
self.gen_params = gen_params

self.fn = alu_fn.get_function()
Expand Down Expand Up @@ -206,6 +217,19 @@ def _or(s: Value) -> Value:
for i in range(en):
j = en - i - 1
m.d.comb += self.out[i * 8 : (i + 1) * 8].eq(self.in1[j * 8 : (j + 1) * 8])

if self.zicond_enable:
czero_cases = [
(AluFn.Fn.CZERONEZ, lambda is_zero: self.in1 if is_zero else 0),
(AluFn.Fn.CZEROEQZ, lambda is_zero: 0 if is_zero else self.in1),
]
for fn, output_fn in czero_cases:
with OneHotCase(fn):
with m.If(self.in2.any()):
m.d.comb += self.out.eq(output_fn(False))
with m.Else():
m.d.comb += self.out.eq(output_fn(True))

return m


Expand Down Expand Up @@ -254,10 +278,11 @@ def _(arg):


class ALUComponent(FunctionalComponentParams):
def __init__(self, zba_enable=False, zbb_enable=False):
def __init__(self, zba_enable=False, zbb_enable=False, zicond_enable=False):
self.zba_enable = zba_enable
self.zbb_enable = zbb_enable
self.alu_fn = AluFn(zba_enable=zba_enable, zbb_enable=zbb_enable)
self.zicond_enable = zicond_enable
self.alu_fn = AluFn(zba_enable=zba_enable, zbb_enable=zbb_enable, zicond_enable=zicond_enable)

def get_module(self, gen_params: GenParams) -> FuncUnit:
return AluFuncUnit(gen_params, self.alu_fn)
Expand Down
2 changes: 1 addition & 1 deletion coreblocks/params/configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ def replace(self, **kwargs) -> Self:
func_units_config=(
RSBlockComponent(
[
ALUComponent(zba_enable=True, zbb_enable=True),
ALUComponent(zba_enable=True, zbb_enable=True, zicond_enable=True),
ShiftUnitComponent(zbb_enable=True),
ZbcComponent(),
ZbsComponent(),
Expand Down
18 changes: 17 additions & 1 deletion test/frontend/test_instr_decoder.py
Original file line number Diff line number Diff line change
Expand Up @@ -170,11 +170,24 @@ def __init__(
op=OpType.UNARY_BIT_MANIPULATION_1,
),
]
DECODER_TESTS_ZICOND = [
# CZERO RS2 RS1 EQZ RD OP
# nez 0b0000111 00000 00000 111 00000 0110011
# eqz 0b0000111 00000 00000 101 00000 0110011
# CZERO.NEZ
InstrTest(0x0E007033, Opcode.OP, Funct3.CZERONEZ, Funct7.CZERO, rd=0, rs1=0, rs2=0, op=OpType.CZERO),
# CZERO.EQZ
InstrTest(0x0E005033, Opcode.OP, Funct3.CZEROEQZ, Funct7.CZERO, rd=0, rs1=0, rs2=0, op=OpType.CZERO),
]

def setup_method(self):
self.gen_params = GenParams(
test_core_config.replace(
_implied_extensions=Extension.G | Extension.XINTMACHINEMODE | Extension.XINTSUPERVISOR | Extension.ZBB
_implied_extensions=Extension.G
| Extension.XINTMACHINEMODE
| Extension.XINTSUPERVISOR
| Extension.ZBB
| Extension.ZICOND
)
)
self.decoder = InstrDecoder(self.gen_params)
Expand Down Expand Up @@ -263,6 +276,9 @@ def test_xintsupervisor(self):
def test_zbb(self):
self.do_test(self.DECODER_TESTS_ZBB)

def test_zicond(self):
self.do_test(self.DECODER_TESTS_ZICOND)


class TestDecoderEExtLegal(TestCaseWithSimulator):
E_TEST = [
Expand Down
14 changes: 13 additions & 1 deletion test/func_blocks/fu/test_alu.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@


class TestAluUnit(FunctionalUnitTestCase[AluFn.Fn]):
func_unit = ALUComponent(zba_enable=True, zbb_enable=True)
func_unit = ALUComponent(zba_enable=True, zbb_enable=True, zicond_enable=True)
zero_imm = False

ops = {
Expand Down Expand Up @@ -36,6 +36,8 @@ class TestAluUnit(FunctionalUnitTestCase[AluFn.Fn]):
AluFn.Fn.CLZ: ExecFn(OpType.UNARY_BIT_MANIPULATION_3, Funct3.CLZ),
AluFn.Fn.CTZ: ExecFn(OpType.UNARY_BIT_MANIPULATION_4, Funct3.CTZ),
AluFn.Fn.CPOP: ExecFn(OpType.UNARY_BIT_MANIPULATION_5, Funct3.CPOP),
AluFn.Fn.CZERONEZ: ExecFn(OpType.CZERO, Funct3.CZERONEZ, Funct7.CZERO),
AluFn.Fn.CZEROEQZ: ExecFn(OpType.CZERO, Funct3.CZEROEQZ, Funct7.CZERO),
}

@staticmethod
Expand Down Expand Up @@ -118,6 +120,16 @@ def compute_result(i1: int, i2: int, i_imm: int, pc: int, fn: AluFn.Fn, xlen: in
while (i1 & 1) == 0:
res += 1
i1 >>= 1
case AluFn.Fn.CZEROEQZ:
if i2 == 0:
res = 0
else:
res = i1
case AluFn.Fn.CZERONEZ:
if i2 == 0:
res = i1
else:
res = 0

return {"result": res & mask}

Expand Down
6 changes: 3 additions & 3 deletions test/params/test_configurations.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ class ISAStrTest:
),
ISAStrTest(
full_core_config,
"rv32imcbzicsr_zifencei_xintmachinemode",
"rv32imcbzicsr_zifencei_xintmachinemode",
"rv32imcbzicsr_zifencei_xintmachinemode",
"rv32imcbzicsr_zifencei_zicond_xintmachinemode",
"rv32imcbzicsr_zifencei_zicond_xintmachinemode",
"rv32imcbzicsr_zifencei_zicond_xintmachinemode",
),
ISAStrTest(tiny_core_config, "rv32e", "rv32e", "rv32e"),
ISAStrTest(test_core_config, "rv32", "rv32", "rv32i"),
Expand Down