/ coreblocks / func_blocks / fu / fpu / fpu_sign_injection.py
fpu_sign_injection.py
 1  from amaranth import *
 2  from amaranth.lib import enum
 3  from transactron import TModule, Method, def_method
 4  from coreblocks.func_blocks.fu.fpu.fpu_common import FPUParams, create_data_input_layout, create_data_output_layout
 5  
 6  
 7  class SIOperations(enum.IntFlag):
 8      FSGNJ_S = enum.auto()  # sign of second operand
 9      FSGNJN_S = enum.auto()  # opposite of sign of second operand
10      FSGNJX_S = enum.auto()  # xor of both signs
11  
12  
13  class SIMethodLayout:
14      """Sign injection module layouts for methods
15  
16      Parameters
17      ----------
18      fpu_params: FPUParams
19          FPU parameters
20      """
21  
22      def __init__(self, *, fpu_params: FPUParams):
23          """
24          op_1 - first operand
25          op_2 - second operand
26          operation - type of sign injection operation
27          """
28          self.si_in_layout = [
29              ("op_1", create_data_input_layout(fpu_params)),
30              ("op_2", create_data_input_layout(fpu_params)),
31              ("operation", SIOperations),
32          ]
33          self.si_out_layout = create_data_output_layout(fpu_params)
34  
35  
36  class SIModule(Elaboratable):
37      """Sign injection module
38      Module responsible for performing sign injection operations.
39      Only things worth noting about this module are:
40      1. Sign injection do not set floating-point exception flags
41      2. Sign injection do not canonicalize NaNs
42  
43      Parameters
44      ----------
45      fpu_params: FPUParams
46          FPU rounding module parameters
47  
48      Attributes
49      ----------
50      si_request: Method
51          Transactional method for initiating leading sign injection.
52          Takes 'si_in_layout' as argument
53          Returns result as 'si_out_layout'
54      """
55  
56      def __init__(self, *, fpu_params: FPUParams):
57  
58          self.si_params = fpu_params
59          self.method_layouts = SIMethodLayout(fpu_params=self.si_params)
60          self.si_request = Method(
61              i=self.method_layouts.si_in_layout,
62              o=self.method_layouts.si_out_layout,
63          )
64  
65      def elaborate(self, platform):
66          m = TModule()
67  
68          @def_method(m, self.si_request)
69          def _(op_1, op_2, operation):
70  
71              final_sign = Signal()
72  
73              with m.Switch(operation):
74                  with m.Case(SIOperations.FSGNJ_S):
75                      m.d.av_comb += final_sign.eq(op_2.sign)
76                  with m.Case(SIOperations.FSGNJN_S):
77                      m.d.av_comb += final_sign.eq(~op_2.sign)
78                  with m.Case(SIOperations.FSGNJX_S):
79                      m.d.av_comb += final_sign.eq(op_2.sign ^ op_1.sign)
80  
81              return {
82                  "sign": final_sign,
83                  "sig": op_1.sig,
84                  "exp": op_1.exp,
85                  "errors": 0,
86              }
87  
88          return m