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