2 Authors : Vinod.G, Arjun Menon
3 Email : g.vinod1993@gmail.com, c.arjunmenon@gmail.com
4 Last update : 27th November 2017
5 See LICENSE for more details
10 /*==== Project imports ==== */
11 `include "defined_parameters.bsv"
12 import defined_types::*;
13 import fpu_compare_min_max::*;
14 import fpu_int_to_sp::*;
15 import fpu_int_to_dp::*;
16 import fpu_sign_injection::*;
17 import fpu_divider::*;
19 import fpu_sp_to_int::*;
20 import fpu_dp_to_int::*;
21 import fpu_fm_add_sub::*;
22 import fpu_convert_sp_dp::*;
24 /*========================= */
25 /*===== Package imports ==== */
28 import SpecialFIFOs::*;
30 import UniqueWrappers::*;
31 import SpecialFIFOs::*;
33 /*========================= */
35 interface Ifc_fpu; //interface to module mk_fpu
36 method Action _start(Bit#(`FLEN) operand1, Bit#(`FLEN) operand2, Bit#(`FLEN) operand3, Bit#(4) opcode, Bit#(7) funct7, Bit#(3) funct3, Bit#(2) imm, Bit#(3) fsr, Bool issp);
37 method ActionValue#(Floating_output#(`FLEN)) get_result;
51 }Input_Packet deriving (Bits,Eq);
54 module mkfpu(Ifc_fpu);
55 // ============================================
56 // Decode and Maintenance Registers
57 // ============================================
58 FIFO# (Floating_output#(`FLEN)) ff_result <- mkFIFO1;
59 FIFO# (Input_Packet) ff_input <- mkFIFO1;
60 Wire#(Bool) wr_flush<-mkDWire(False);
61 // =============================================
63 // ==============================================
64 // Module Instantiations
65 // ==============================================
67 `ifdef fpu_hierarchical
68 Ifc_fpu_compare_min_max32 inst_fpu_compare_min_max <- mkfpu_compare_min_max32();
69 Ifc_fpu_sign_injection32 inst_spfpu_sign_injection <- mkfpu_sign_injection32();
70 Ifc_fpu_divider32 inst_spfpu_divider <- mkfpu_divider32();
71 Ifc_fpu_sqrt32 inst_spfpu_sqrt <- mkfpu_sqrt32();
72 Ifc_fpu_fm_add_sub32 inst_spfm_add_sub <- mkfpu_fm_add_sub32();
73 Ifc_fpu_fclass32 inst_spfpu_fclass <- mkfpu_fclass32();
75 Ifc_fpu_compare_min_max64 inst_dpfpu_compare_min_max <- mkfpu_compare_min_max64();
76 Ifc_fpu_sign_injection64 inst_dpfpu_sign_injection <- mkfpu_sign_injection64();
77 Ifc_fpu_divider64 inst_dpfpu_divider <- mkfpu_divider64();
78 Ifc_fpu_sqrt64 inst_dpfpu_sqrt <- mkfpu_sqrt64();
79 Ifc_fpu_fm_add_sub64 inst_dpfm_add_sub <- mkfpu_fm_add_sub64();
80 Ifc_fpu_fclass64 inst_dpfpu_fclass <- mkfpu_fclass64();
83 Ifc_fpu_compare_min_max#(32,23,8) inst_fpu_compare_min_max <- mkfpu_compare_min_max(); // No Flush
84 Ifc_fpu_sign_injection#(32,23,8) inst_spfpu_sign_injection <- mkfpu_sign_injection(); // No Flush
85 Ifc_fpu_divider#(32,23,8) inst_spfpu_divider <- mkfpu_divider();
86 Ifc_fpu_sqrt#(32,23,8) inst_spfpu_sqrt <- mkfpu_sqrt();
87 Ifc_fpu_fm_add_sub#(32,23,8) inst_spfm_add_sub <- mkfpu_fm_add_sub();
88 Ifc_fpu_fclass#(32,23,8) inst_spfpu_fclass <- mkfpu_fclass(); // No Flush
90 Ifc_fpu_compare_min_max#(64,52,11) inst_dpfpu_compare_min_max <- mkfpu_compare_min_max(); // No Flush
91 Ifc_fpu_sign_injection#(64,52,11) inst_dpfpu_sign_injection <- mkfpu_sign_injection(); // No Flush
92 Ifc_fpu_divider#(64,52,11) inst_dpfpu_divider <- mkfpu_divider();
93 Ifc_fpu_sqrt#(64,52,11) inst_dpfpu_sqrt <- mkfpu_sqrt();
94 Ifc_fpu_fm_add_sub#(64,52,11) inst_dpfm_add_sub <- mkfpu_fm_add_sub();
95 Ifc_fpu_fclass#(64,52,11) inst_dpfpu_fclass <- mkfpu_fclass(); // No Flush
98 Ifc_fpu_sp_to_int inst_spfp_to_int <- mkfpu_sp_to_int(); // No Flush
99 Ifc_fpu_convert_sp_dp inst_spfpu_cnvt <- mkfpu_convert_sp_dp(); // No Flush
100 Ifc_fpu_int_to_sp inst_fpu_int_to_fp <- mkfpu_int_to_sp(); // No Flush
102 Ifc_fpu_dp_to_int inst_dpfp_to_int <- mkfpu_dp_to_int(); // No Flush
103 Ifc_fpu_convert_dp_sp inst_dpfpu_cnvt <- mkfpu_convert_dp_sp(); // No Flush
104 Ifc_fpu_int_to_dp inst_dpfpu_int_to_fp <- mkfpu_int_to_dp(); // No Flush
107 // ==============================================
109 // ==============================================
110 // Function definitions
111 // ==============================================
112 function Tuple3#(Bit#(5), Bit#(5), Bit#(5)) condFlags (Tuple2#(Bit#(m), Bit#(e)) x, Tuple2#(Bit#(m), Bit#(e)) y, Tuple2#(Bit#(m),Bit#(e)) z);
114 let mantissa1 = tpl_1(x);
115 let exponent1 = tpl_2(x);
116 let mantissa2 = tpl_1(y);
117 let exponent2 = tpl_2(y);
118 let mantissa3 = tpl_1(z);
119 let exponent3 = tpl_2(z);
120 bit man10 = |mantissa1; bit man20 = |mantissa2; bit man30 = |mantissa3;
121 bit exp10 = |exponent1; bit exp20 = |exponent2; bit exp30 = |exponent3;
122 bit man11 = &mantissa1; bit man21 = &mantissa2; bit man31 = &mantissa3;
123 bit exp11 = &exponent1; bit exp21 = &exponent2; bit exp31 = &exponent3;
124 Bit#(5) flags1, flags2,flags3;
125 Bool expZ1 = (exp10 == 0);
126 Bool manZ1 = (man10 == 0);
127 Bool expO1 = (exp11 == '1);
128 Bool manO1 = (man11 == '1);
129 Bool topB1 = (mantissa1[s-1] == 1);
130 Bool expZ2 = (exp20 == 0);
131 Bool manZ2 = (man20 == 0);
132 Bool expO2 = (exp21 == '1);
133 Bool manO2 = (man21 == '1);
134 Bool topB2 = (mantissa2[s-1] == 1 && man20 ==1);
135 Bool expZ3 = (exp30 == 0);
136 Bool manZ3 = (man30 == 0);
137 Bool expO3 = (exp31 == 1);
138 Bool manO3 = (man31 == 1);
139 Bool topB3 = (mantissa3[s-1] == 1 && man30 ==1);
140 flags1 = {pack(expZ1 && !manZ1),pack(manZ1 && expZ1),pack(expO1 && topB1),pack(expO1 && manZ1),pack(expO1 && !topB1 && !manZ1)}; //Denormal, isZero, QNaN, Infinity, SNaN
141 flags2 = {pack(expZ2 && !manZ2),pack(manZ2 && expZ2),pack(expO2 && topB2),pack(expO2 && manZ2),pack(expO2 && !topB2 && !manZ2)}; //Denormal, isZero, QNaN, Infinity, SNaN
142 flags3 = {pack(expZ3 && !manZ3),pack(manZ3 && expZ3),pack(expO3 && topB3),pack(expO3 && manZ3),pack(expO3 && !topB3 && !manZ3)}; //Denormal, isZero, QNaN, Infinity, SNaN
143 return tuple3(flags1,flags2,flags3);
146 function Tuple3#(Bit#(m),Bit#(m), Bit#(m)) getMantissa (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
147 provisos(Add#(TAdd#(m,1),e,n),
150 let expo = valueOf(e);
151 let man = valueOf(m);
152 return tuple3(op1[man-1:0],op2[man-1:0],op3[man-1:0]);
155 function Tuple3#(Bit#(e), Bit#(e), Bit#(e)) getExp (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
156 provisos(Add#(TAdd#(m,1),e,n),
159 let inp = valueOf(n);
160 let man = valueOf(m);
161 return tuple3(op1[inp-2:man], op2[inp-2:man], op3[inp-2:man]);
164 function Bool isNaNBox(Bit#(64) op);
165 return (&(op[63:32])==1);
168 function Tuple3#(Bit#(32),Bit#(32),Bit#(32)) setCanNaN (Bit#(64) op1, Bit#(64) op2, Bit#(64) op3);
169 return tuple3(isNaNBox(op1)? truncate(op1) : 32'h7fc00000, isNaNBox(op2)? truncate(op2) : 32'h7fc00000, isNaNBox(op3)? truncate(op3) : 32'h7fc00000);
172 // ================================================
174 // ================================================
175 Wrapper3#(Tuple2#(Bit#(23), Bit#(8)),Tuple2#(Bit#(23), Bit#(8)), Tuple2#(Bit#(23), Bit#(8)), Tuple3#(Bit#(5),Bit#(5),Bit#(5))) condFlags32 <- mkUniqueWrapper3(condFlags);
176 Wrapper3#(Tuple2#(Bit#(52), Bit#(11)),Tuple2#(Bit#(52), Bit#(11)),Tuple2#(Bit#(52), Bit#(11)), Tuple3#(Bit#(5),Bit#(5),Bit#(5))) condFlags64 <- mkUniqueWrapper3(condFlags);
177 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(23),Bit#(23),Bit#(23))) getMant32 <- mkUniqueWrapper3(getMantissa);
178 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(8),Bit#(8),Bit#(8))) getExp32 <- mkUniqueWrapper3(getExp);
179 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(52),Bit#(52),Bit#(52))) getMant64 <- mkUniqueWrapper3(getMantissa);
180 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(11),Bit#(11),Bit#(11))) getExp64 <- mkUniqueWrapper3(getExp);
181 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(32),Bit#(32),Bit#(32))) setCanonicalNaN <- mkUniqueWrapper3(setCanNaN);
182 Reg#(Bool) rg_multicycle_op <-mkReg(False);
185 (*mutually_exclusive="rl_get_output_from_spfpu_divider, rl_get_output_from_dpfpu_divider,rl_get_output_from_spfpu_sqrt, rl_get_output_from_dpfpu_sqrt,rl_get_output_from_fm_add_sub,rl_get_output_from_dpfm_add_sub"*)
189 /// Bool issp = (funct7[0] == 0);
190 let input_packet = ff_input.first;
191 Bit#(`FLEN) operand1 = input_packet.operand1;
192 Bit#(`FLEN) operand2 = input_packet.operand2;
193 Bit#(`FLEN) operand3 = input_packet.operand3;
194 Bit#(4) opcode = input_packet.opcode;
195 Bit#(7) funct7 = input_packet.funct7;
196 Bit#(3) funct3 = input_packet.funct3;
197 Bit#(2) imm = input_packet.imm;
198 Bit#(3) fsr = input_packet.fsr;
199 Bool issp = input_packet.issp;
201 funct3 = (funct3 == 'b111) ? fsr : funct3;
202 if(((funct7[6:2]==`FCMP_f5) || funct7[6:2] == `FMMAX_f5) && opcode == `FP_OPCODE)begin // compare min max
204 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,'1);
205 let {man1,man2,man3} <- getMant32.func(op1, op2,0);
206 let {exp1,exp2,exp3} <- getExp32.func(op1, op2,0);
207 let {flags1,flags2,flags3} <- condFlags32.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(0,0));
210 let x<-inst_fpu_compare_min_max._start(op1,op2,funct3,funct7[2],tuple2(flags1,flags2));
211 Floating_output#(`Reg_width) y=?;
213 y.final_result=funct7[2]==0?zeroExtend(x.final_result):{'1,x.final_result};
215 y.final_result=x.final_result;
221 let {man3,man4,man5} <- getMant64.func(operand1, operand2,0);
222 let {exp3,exp4,exp5} <- getExp64.func(operand1,operand2,0);
223 let {f1,f2,f3} <- condFlags64.func(tuple2(man3,exp3),tuple2(man4,exp4),tuple2(0,0));
224 let sign3 = operand1[63];
225 let sign4 = operand2[63];
226 let x<-inst_dpfpu_compare_min_max._start(operand1,operand2,funct3,funct7[2],tuple2(f1,f2));
229 `ifdef verbose $display($time,"\tGiving inputs to fpu_compare_min_max %h operand2 %h funct7 : %h",operand1, operand2,funct7); `endif
231 else if((funct7[6:2]==`FCVT_F_I_f5) && opcode == `FP_OPCODE) begin
233 let x <-inst_fpu_int_to_fp._start(operand1, imm[0],imm[1], funct3);
234 Floating_output#(`Reg_width) y=?;
236 y.final_result={'1,x.final_result};
238 y.final_result=x.final_result;
244 let x<-inst_dpfpu_int_to_fp._start(operand1,imm[0],imm[1],funct3);
247 `ifdef verbose $display($time,"\tGiving inputs to fpu_int_to_fp %h operand2[0] %h operand2[1] : %h",operand1, operand2[0],operand2[1]); `endif
249 else if((funct7[6:2] == `FSGNJN_f5) && opcode == `FP_OPCODE)begin
251 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,'1);
252 let x <-inst_spfpu_sign_injection._start(op1, op2, funct3);
253 Floating_output#(`Reg_width) y=?;
255 y.final_result={'1,x.final_result};
257 y.final_result=x.final_result;
263 let x<-inst_dpfpu_sign_injection._start(operand1,operand2,funct3);
266 `ifdef verbose $display($time,"\tGiving inputs to the fpu sign injection"); `endif
268 else if((funct7[6:2] == `FCVT_I_F_f5) && opcode == `FP_OPCODE) begin
270 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,'0,'0);
271 let {man1,man2,man3} <- getMant32.func(op1, 0,0);
272 let {exp1,exp2,exp3} <- getExp32.func(op1, 0,0);
273 let {flags1,flags2,flags3} <- condFlags32.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
274 let x <- inst_spfp_to_int._start(op1[31],exp1,man1, imm[0],imm[1],funct3,flags1);
278 let {man4,man5,man6} <- getMant64.func(operand1, 0,0);
279 let {exp4,exp5,exp6} <- getExp64.func(operand1, 0,0);
280 let {flags4,flags5,flags6} <- condFlags64.func(tuple2(man4,exp4),tuple2(0,0),tuple2(0,0));
281 let x<-inst_dpfp_to_int._start(operand1[63],exp4,man4,imm[0],imm[1],funct3,flags4);
284 `ifdef verbose $display($time,"\tGiving Inputs to fpu to int Conversion Module"); `endif
286 else if(((funct7[6:2] == `FCLASS_f5)&&(funct3=='b001))&&(opcode == `FP_OPCODE))begin
288 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,'1,'1);
289 let {man1,man2,man3} <- getMant32.func(op1, 0,0);
290 let {exp1,exp2,exp3} <- getExp32.func(op1, 0,0);
291 let {x1,x2,x3} <- condFlags32.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
292 let x<-inst_spfpu_fclass._start(op1[31],man1,exp1,x1);
293 Floating_output#(`FLEN) y = Floating_output{final_result:zeroExtend(x.final_result),fflags:x.fflags};
297 let {man1,man2,man3} <- getMant64.func(operand1, 0,0);
298 let {exp1,exp2,exp3} <- getExp64.func(operand1, 0,0);
299 let {x1,x2,x3} <- condFlags64.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
300 let x<-inst_dpfpu_fclass._start(operand1[63],man1,exp1,x1);
303 `ifdef verbose $display($time,"\tGiving inputs to floating classify module"); `endif
305 else if((funct7[6:2] == `FCVT_S_D_f5) && opcode == `FP_OPCODE)begin
307 `ifdef verbose $display("Giving inputs to Convert SP to DP"); `endif
308 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,'1,'1);
309 let {man1,man2,man3} <- getMant32.func(op1, 0,0);
310 let {exp1,exp2,exp3} <- getExp32.func(op1, 0,0);
311 let {x1,x2,x3} <- condFlags32.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
312 let x<-inst_spfpu_cnvt._start(op1[31],exp1,man1,funct3,x1);
316 `ifdef verbose $display("Giving inputs to Convert DP to SP"); `endif
317 let {man1,man2,man3} <- getMant64.func(operand1, 0,0);
318 let {exp1,exp2,exp3} <- getExp64.func(operand1, 0,0);
319 let {x1,x2,x3} <- condFlags64.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
320 let x<-inst_dpfpu_cnvt._start(operand1[63],exp1,man1,funct3,x1);
321 Floating_output#(`Reg_width) y=?;
323 y.final_result = {'hffffffff,x.final_result[31:0]};
325 y.final_result = x.final_result;
331 else if(((funct7 == `FMV_X_S_f7 || funct7 == `FMV_S_X_f7) && funct3 == 'b000) && opcode == `FP_OPCODE)begin
332 `ifdef verbose $display($time,"\tGiving inputs to FMV"); `endif
333 Bit#(`FLEN) final_result=0;
334 if(funct7==`FMV_X_S_f7) // sp to integer FMV.X.W
335 final_result = signExtend(operand1[31:0]);
336 else // integer to sp FMV.W.X
338 final_result = {'1,operand1[31:0]};
340 final_result= operand1[31:0];
342 ff_result.enq(Floating_output{final_result:final_result, fflags : 0});
344 else if(((funct7 == `FMV_X_D_f7 || funct7 == `FMV_D_X_f7) && funct3 == 'b000) && opcode == `FP_OPCODE)begin // TODO merge with above condition
345 `ifdef verbose $display($time,"\tGiving inputs to FMV"); `endif
346 Bit#(`FLEN) final_result=0;
347 if(funct7==`FMV_X_D_f7) // sp to integer FMV.X.W
348 final_result = operand1;
349 else // integer to sp FMV.W.X
350 final_result= operand1;
351 ff_result.enq(Floating_output{final_result:final_result, fflags : 0});
353 else if(((funct7[6:2] == `FADD_f5 || funct7[6:2] == `FSUB_f5) && opcode == `FP_OPCODE))begin // add sub
354 rg_multicycle_op<=True;
356 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,'1);
357 let {man1,man2,man3} <- getMant32.func(32'h3f800000,op1, op2);
358 let {exp1,exp2,exp3} <- getExp32.func(32'h3f800000,op1, op2);
359 let x <- condFlags32.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
363 inst_spfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2),tuple3(sign3,exp3,man3),funct3,funct7[2],1'b0,1'b0,0,x);
366 let {man1,man2,man3} <- getMant64.func(64'h3ff0000000000000,operand1, operand2);
367 let {exp1,exp2,exp3} <- getExp64.func(64'h3ff0000000000000,operand1, operand2);
368 let x <- condFlags64.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
370 let sign2 = operand1[63];
371 let sign3 = operand2[63];
372 inst_dpfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2), tuple3(sign3,exp3,man3), funct3, funct7[2], 1'b0, 1'b0,0,x);
374 `ifdef verbose $display($time,"\tGiving inputs to the fpu add_sub"); `endif
376 else if((funct7[6:2] == `FDIV_f5) && opcode == `FP_OPCODE)begin// spfpu divider
377 rg_multicycle_op<=True;
379 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,'1);
380 let {man1,man2,man3} <- getMant32.func(op1, op2,op3);
381 let {exp1,exp2,exp3} <- getExp32.func(op1, op2,op3);
382 let {f1,f2,f3} <- condFlags32.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
383 inst_spfpu_divider._start(op1[31]^op2[31],man1,exp1,man2,exp2,funct3,tuple2(f1,f2));
386 let {man3,man4,man5} <- getMant64.func(operand1, operand2,0);
387 let {exp3,exp4,exp5} <- getExp64.func(operand1,operand2,0);
388 let {y1,y2,y3} <- condFlags64.func(tuple2(man3,exp3),tuple2(man4,exp4),tuple2(0,0));
389 inst_dpfpu_divider._start(operand1[63]^operand2[63],man3,exp3,man4,exp4,funct3, tuple2(y1,y2));
391 `ifdef verbose $display($time,"\tGiving inputs to the spfpu divider"); `endif
393 else if((funct7[6:2] == `FSQRT_f5) && opcode == `FP_OPCODE)begin// sqrt
394 rg_multicycle_op<=True;
396 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,'1,'1);
397 let {man1,man2,man3} <- getMant32.func(op1, 0,0);
398 let {exp1,exp2,exp3} <- getExp32.func(op1, 0,0);
399 let x <- condFlags32.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
400 inst_spfpu_sqrt._start(operand1[31], man1, exp1, funct3, tpl_1(x));
403 let {man3,man4,man5} <- getMant64.func(operand1, 0,0);
404 let {exp3,exp4,exp5} <- getExp64.func(operand1,0,0);
405 let y <- condFlags64.func(tuple2(man3,exp3),tuple2(0,0),tuple2(0,0));
406 inst_dpfpu_sqrt._start(operand1[63], man3, exp3, funct3, tpl_1(y));
407 `ifdef verbose $display($time,"\tGiving inputs to the spfpu sqrt"); `endif
410 else if((funct7[6:2] == `FMUL_f5) && opcode == `FP_OPCODE)begin
411 rg_multicycle_op<=True;
412 `ifdef verbose $display("funct3 : %h",funct3); `endif
414 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,'1);
415 let {man1,man2,man3} <- getMant32.func(op1, op2,0);
416 let {exp1,exp2,exp3} <- getExp32.func(op1, op2,0);
417 let x <- condFlags32.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
421 inst_spfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2),tuple3(sign3,exp3,man3),funct3,1'b1,1'b0,1'b1,0,x);
424 let {man1,man2,man3} <- getMant64.func(operand1, operand2,0);
425 let {exp1,exp2,exp3} <- getExp64.func(operand1, operand2,0);
426 let x <- condFlags64.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
427 let sign1 = operand1[63];
428 let sign2 = operand2[63];
430 inst_dpfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2),tuple3(sign3,exp3,man3), funct3, 1'b1, 1'b0, 1'b1,0,x);
432 `ifdef verbose $display($time,"\tGiving inputs to the spfloating multiplier module"); `endif
434 else if((opcode == 'b0000) || (opcode == 'b0001) || (opcode == 'b0010) || opcode == 'b0011)begin
435 rg_multicycle_op<=True;
437 `ifdef verbose $display($time,"\tGiving Inputs to sp fused multiply add Conversion Module"); `endif
438 let {op1,op2,op3} <- setCanonicalNaN.func(operand1,operand2,operand3);
439 let {man1,man2,man3} <- getMant32.func(op1, op2,op3);
440 let {exp1,exp2,exp3} <- getExp32.func(op1, op2,op3);
441 let x <- condFlags32.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
445 inst_spfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2),tuple3(sign3,exp3,man3),funct3,opcode[0]^opcode[1],opcode[1],1'b0,1,x);
448 `ifdef verbose $display($time,"\tGiving Inputs to dp fused multiply add Conversion Module"); `endif
449 let {man1,man2,man3} <- getMant64.func(operand1, operand2,operand3);
450 let {exp1,exp2,exp3} <- getExp64.func(operand1, operand2,operand3);
451 let x <- condFlags64.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(man3,exp3));
452 let sign1 = operand1[63];
453 let sign2 = operand2[63];
454 let sign3 = operand3[63];
455 inst_dpfm_add_sub._start(tuple3(sign1,exp1,man1),tuple3(sign2,exp2,man2),tuple3(sign3,exp3,man3), funct3, opcode[0]^opcode[1],opcode[1], 1'b0,1,x);
457 `ifdef verbose $display($time,"\tOperand 1: %h Operand 2: %h Operand 3: %h",operand1, operand2, operand3); `endif
461 //rule to get output from spfpu divider
462 rule rl_get_output_from_spfpu_divider(!wr_flush && rg_multicycle_op);
463 `ifdef verbose $display($time,"\tGot output from spfpu divider"); `endif
464 let x= inst_spfpu_divider.final_result_;
465 Floating_output#(`FLEN) y=?;
468 y.final_result={'1,x.final_result};
470 y.final_result=x.final_result;
473 rg_multicycle_op<=False;
476 //rule to get output from spfpu divider
477 rule rl_get_output_from_dpfpu_divider(!wr_flush && rg_multicycle_op);
478 `ifdef verbose $display($time,"\tGot output from spfpu divider"); `endif
479 let x= inst_dpfpu_divider.final_result_;
480 Floating_output#(`FLEN) y=?;
482 y.final_result=x.final_result;
484 rg_multicycle_op<=False;
487 //rule to give inputs to spfpu square root module
489 //rule to get output spfpu square root module
490 rule rl_get_output_from_spfpu_sqrt(inst_spfpu_sqrt.get_result matches tagged Valid .res &&& !wr_flush &&& rg_multicycle_op); // TODO check for inexact and underflow
491 `ifdef verbose $display($time,"\tGot output from spfpu sqrt"); `endif
493 Floating_output#(`FLEN) y=?;
496 y.final_result={'1,x.final_result};
498 y.final_result=x.final_result;
501 rg_multicycle_op<=False;
504 //rule to get output spfpu square root module
505 rule rl_get_output_from_dpfpu_sqrt(inst_dpfpu_sqrt.get_result matches tagged Valid .res &&& !wr_flush &&& rg_multicycle_op); // TODO check for inexact and underflow
506 `ifdef verbose $display($time,"\tGot output from spfpu sqrt"); `endif
508 Floating_output#(`FLEN) y=?;
510 y.final_result=x.final_result;
512 rg_multicycle_op<=False;
516 //rule to get output from fused multiply add sub
517 rule rl_get_output_from_fm_add_sub(!wr_flush && rg_multicycle_op);
518 `ifdef verbose $display($time,"\tGot output from sp fused multiple add conversion Module"); `endif
519 let x= inst_spfm_add_sub.get_result;
520 Floating_output#(`FLEN) y=?;
523 y.final_result={'hffffffff,x.final_result[31:0]};
525 y.final_result=x.final_result;
528 `ifdef verbose $display($time,"\tFMA Result : %16h", y.final_result); `endif
529 rg_multicycle_op<=False;
532 //rule to get output from fused multiply add sub
533 rule rl_get_output_from_dpfm_add_sub(!wr_flush && rg_multicycle_op);
534 `ifdef verbose $display($time,"\tGot output from sp fused multiple add conversion Module"); `endif
535 let x= inst_dpfm_add_sub.get_result;
536 Floating_output#(`FLEN) y=?;
538 y.final_result=x.final_result;
540 `ifdef verbose $display($time,"\tFMA Result : %16h", y.final_result); `endif
541 rg_multicycle_op<=False;
544 rule flush_fifo(wr_flush);
546 rg_multicycle_op<=False;
548 //rule to give inputs to spfloating multiplier
550 // input method to start the floating point operation
552 method Action _start(Bit#(`FLEN) operand1, Bit#(`FLEN) operand2, Bit#(`FLEN) operand3, Bit#(4) opcode, Bit#(7) funct7, Bit#(3) funct3, Bit#(2) imm, Bit#(3) fsr, Bool issp) if(!rg_multicycle_op);
553 ff_input.enq ( Input_Packet {
566 method ActionValue#(Floating_output#(`FLEN)) get_result;
568 return ff_result.first;
572 inst_spfpu_divider.flush();
573 inst_dpfpu_divider.flush();
574 inst_spfpu_sqrt.flush();
575 inst_dpfpu_sqrt.flush();
576 inst_spfm_add_sub.flush();
577 inst_dpfm_add_sub.flush();