zbs.py
1 from dataclasses import dataclass, KW_ONLY 2 from enum import IntFlag, auto 3 from typing import Sequence 4 from amaranth import * 5 6 from coreblocks.params import GenParams, FunctionalComponentParams 7 from coreblocks.arch import OpType, Funct3, Funct7 8 from transactron import TModule, def_method 9 from transactron.utils import OneHotSwitch 10 from coreblocks.func_blocks.interface.func_protocols import FuncUnit 11 12 from coreblocks.func_blocks.fu.common import DecoderManager, FuncUnitBase 13 14 15 class ZbsFn(DecoderManager): 16 """ 17 Enum of Zbs functions. 18 """ 19 20 class Fn(IntFlag): 21 BCLR = auto() # Bit clear 22 BEXT = auto() # Bit extract 23 BINV = auto() # Bit invert 24 BSET = auto() # Bit set 25 26 def get_instructions(self) -> Sequence[tuple]: 27 return [ 28 (self.Fn.BCLR, OpType.SINGLE_BIT_MANIPULATION, Funct3.BCLR, Funct7.BCLR), 29 (self.Fn.BEXT, OpType.SINGLE_BIT_MANIPULATION, Funct3.BEXT, Funct7.BEXT), 30 (self.Fn.BINV, OpType.SINGLE_BIT_MANIPULATION, Funct3.BINV, Funct7.BINV), 31 (self.Fn.BSET, OpType.SINGLE_BIT_MANIPULATION, Funct3.BSET, Funct7.BSET), 32 ] 33 34 35 class Zbs(Elaboratable): 36 """ 37 Module responsible for executing Zbs instructions. 38 39 Attributes 40 ---------- 41 fn: ZbsFunction, in 42 Function to be executed. 43 in1: Signal(xlen), in 44 First input. 45 in2: Signal(xlen), in 46 Second input. 47 """ 48 49 def __init__(self, gen_params: GenParams, fn=ZbsFn()): 50 """ 51 Parameters 52 ---------- 53 gen_params : GenParams 54 Core generation parameters. 55 function : ZbsFunction 56 Decoder manager to decode instruction. 57 """ 58 self.gen_params = gen_params 59 60 self.xlen = gen_params.isa.xlen 61 self.fn = fn.get_function() 62 self.in1 = Signal(self.xlen) 63 self.in2 = Signal(self.xlen) 64 65 self.result = Signal(self.xlen) 66 67 def elaborate(self, platform): 68 m = TModule() 69 70 xlen_log = self.gen_params.isa.xlen_log 71 72 with OneHotSwitch(m, self.fn) as OneHotCase: 73 with OneHotCase(ZbsFn.Fn.BCLR): 74 m.d.comb += self.result.eq(self.in1 & ~(1 << self.in2[0:xlen_log])) 75 with OneHotCase(ZbsFn.Fn.BEXT): 76 m.d.comb += self.result.eq((self.in1 >> self.in2[0:xlen_log]) & 1) 77 with OneHotCase(ZbsFn.Fn.BINV): 78 m.d.comb += self.result.eq(self.in1 ^ (1 << self.in2[0:xlen_log])) 79 with OneHotCase(ZbsFn.Fn.BSET): 80 m.d.comb += self.result.eq(self.in1 | (1 << self.in2[0:xlen_log])) 81 82 return m 83 84 85 class ZbsUnit(FuncUnitBase[ZbsFn]): 86 """ 87 Executes Zbs instructions. 88 """ 89 90 def __init__(self, gen_params: GenParams, fn=ZbsFn()): 91 super().__init__(gen_params, fn) 92 93 def elaborate(self, platform): 94 m = super().elaborate(platform) 95 96 m.submodules.zbs = zbs = Zbs(self.gen_params, fn=self.fn) 97 98 @def_method(m, self.issue_decoded) 99 def _(arg): 100 m.d.av_comb += zbs.fn.eq(arg.decode_fn) 101 m.d.av_comb += zbs.in1.eq(arg.s1_val) 102 m.d.av_comb += zbs.in2.eq(Mux(arg.imm, arg.imm, arg.s2_val)) 103 104 self.push_result(m, rob_id=arg.rob_id, result=zbs.result, rp_dst=arg.rp_dst, exception=0) 105 106 return m 107 108 109 @dataclass(frozen=True) 110 class ZbsComponent(FunctionalComponentParams): 111 _: KW_ONLY 112 decoder_manager: ZbsFn = ZbsFn() 113 result_fifo: bool = True 114 115 def get_module(self, gen_params: GenParams) -> FuncUnit: 116 return ZbsUnit(gen_params, self.decoder_manager)