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