/ coreblocks / func_blocks / fu / fpu / fpu_class.py
fpu_class.py
  1  from amaranth import *
  2  from transactron import TModule, Method, def_method
  3  from coreblocks.func_blocks.fu.fpu.fpu_common import (
  4      FPUParams,
  5      FPUClasses,
  6      create_data_input_layout,
  7      Errors,
  8  )
  9  
 10  
 11  class FPUClassMethodLayout:
 12      """FPU classification module method layout
 13  
 14      Parameters
 15      ----------
 16      fpu_params; FPUParams
 17          FPU parameters
 18      """
 19  
 20      def __init__(self, *, fpu_params: FPUParams):
 21          self.class_in_layout = [
 22              ("op", create_data_input_layout(fpu_params)),
 23          ]
 24          """
 25          | Input layout for classification
 26          | op - layout containing data of the only operand
 27          """
 28          self.class_out_layout = [
 29              ("result", FPUClasses),
 30              ("errors", Errors),
 31          ]
 32          """
 33          | Output layout for classification
 34          | result - Class of operand
 35          | errors - Exceptions, in case of classification it is always 0 (empty mask)
 36          """
 37  
 38  
 39  class FPUClassModule(Elaboratable):
 40      """Classification module
 41      Module responsible for performing classification.
 42  
 43      Parameters
 44      ----------
 45      fpu_params: FPUParams
 46          FPU format parameters
 47  
 48      Attributes
 49      ----------
 50      class_request: Method
 51          Transactional method for initiating classification.
 52          Takes 'class_in_layout' as argument
 53          Returns result as 'class_out_layout'
 54      """
 55  
 56      def __init__(self, *, fpu_params: FPUParams):
 57  
 58          self.class_params = fpu_params
 59          self.method_layouts = FPUClassMethodLayout(fpu_params=self.class_params)
 60          self.class_request = Method(
 61              i=self.method_layouts.class_in_layout,
 62              o=self.method_layouts.class_out_layout,
 63          )
 64  
 65      def elaborate(self, platform):
 66          m = TModule()
 67  
 68          @def_method(m, self.class_request)
 69          def _(op):
 70              normal_case = Signal()
 71              neg_sign = Signal()
 72              pos_sign = Signal()
 73              op_norm = Signal()
 74              op_sub = Signal()
 75              op_sig_nan = Signal()
 76              m.d.av_comb += neg_sign.eq(op.sign)
 77              m.d.av_comb += pos_sign.eq(~op.sign)
 78              m.d.av_comb += normal_case.eq((~op.is_inf) & (~op.is_zero) & (~op.is_nan))
 79              m.d.av_comb += op_norm.eq(normal_case & (op.exp > 0))
 80              m.d.av_comb += op_sub.eq(normal_case & (op.exp == 0))
 81              m.d.av_comb += op_sig_nan.eq(op.is_nan & (~op.sig[-2]))
 82  
 83              result = Signal(FPUClasses)
 84  
 85              with m.If(op.is_nan):
 86                  with m.If(~op_sig_nan):
 87                      m.d.av_comb += result.eq(FPUClasses.QUIET_NAN)
 88                  with m.Elif(op_sig_nan):
 89                      m.d.av_comb += result.eq(FPUClasses.SIG_NAN)
 90              with m.Elif(neg_sign):
 91                  with m.If(op.is_inf):
 92                      m.d.av_comb += result.eq(FPUClasses.NEG_INF)
 93                  with m.Elif(op_norm):
 94                      m.d.av_comb += result.eq(FPUClasses.NEG_NORM)
 95                  with m.Elif(op_sub):
 96                      m.d.av_comb += result.eq(FPUClasses.NEG_SUB)
 97                  with m.Elif(op.is_zero):
 98                      m.d.av_comb += result.eq(FPUClasses.NEG_ZERO)
 99              with m.Elif(pos_sign):
100                  with m.If(op.is_inf):
101                      m.d.av_comb += result.eq(FPUClasses.POS_INF)
102                  with m.Elif(op_norm):
103                      m.d.av_comb += result.eq(FPUClasses.POS_NORM)
104                  with m.Elif(op_sub):
105                      m.d.av_comb += result.eq(FPUClasses.POS_SUB)
106                  with m.Elif(op.is_zero):
107                      m.d.av_comb += result.eq(FPUClasses.POS_ZERO)
108  
109              return {
110                  "result": result,
111                  "errors": 0,
112              }
113  
114          return m