/ coreblocks / func_blocks / fu / zbs.py
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)