SDRAM uses SDR0MemBase now
[shakti-core.git] / src / core / fpu / fpu.bsv
1 /*
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
6 Description:
7 TODO
8 */
9 package fpu;
10 /*==== Project imports ==== */
11 `include "core_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::*;
18 import fpu_sqrt::*;
19 import fpu_sp_to_int::*;
20 import fpu_dp_to_int::*;
21 import fpu_fm_add_sub::*;
22 import fpu_convert_sp_dp::*;
23 import fpu_fclass::*;
24 /*========================= */
25 /*===== Package imports ==== */
26 import FIFO::*;
27 import FIFOF::*;
28 import SpecialFIFOs::*;
29 import DReg::*;
30 import UniqueWrappers::*;
31 import SpecialFIFOs::*;
32 import Clocks::*;
33 /*========================= */
34
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;
38 method Action flush;
39 endinterface
40
41 typedef struct{
42 Bit#(`FLEN) operand1;
43 Bit#(`FLEN) operand2;
44 Bit#(`FLEN) operand3;
45 Bit#(4) opcode;
46 Bit#(7) funct7;
47 Bit#(3) funct3;
48 Bit#(2) imm;
49 Bit#(3) fsr;
50 Bool issp;
51 }Input_Packet deriving (Bits,Eq);
52
53 (*synthesize*)
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 // =============================================
62
63 // ==============================================
64 // Module Instantiations
65 // ==============================================
66
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();
74
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();
81
82 `else
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
89
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
96 `endif
97
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
101
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
105
106
107 // ==============================================
108
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);
113 let s = valueOf(m);
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);
144 endfunction
145
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),
148 Add#(7,a__,e)
149 );
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]);
153 endfunction
154
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),
157 Add#(7,a__,e)
158 );
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]);
162 endfunction
163
164 function Bool isNaNBox(Bit#(64) op);
165 return (&(op[63:32])==1);
166 endfunction
167
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);
170 endfunction
171
172 // ================================================
173 // Function Wrappers
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);
183
184
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"*)
186
187
188 rule start_stage;
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;
200 ff_input.deq;
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
203 if(issp) begin
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));
208 let sign1 = op1[31];
209 let sign2 = op2[31];
210 let x<-inst_fpu_compare_min_max._start(op1,op2,funct3,funct7[2],tuple2(flags1,flags2));
211 Floating_output#(`Reg_width) y=?;
212 `ifdef dpfpu
213 y.final_result=funct7[2]==0?zeroExtend(x.final_result):{'1,x.final_result};
214 `else
215 y.final_result=x.final_result;
216 `endif
217 y.fflags=x.fflags;
218 ff_result.enq(y);
219 end
220 else begin
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));
227 ff_result.enq(x);
228 end
229 `ifdef verbose $display($time,"\tGiving inputs to fpu_compare_min_max %h operand2 %h funct7 : %h",operand1, operand2,funct7); `endif
230 end
231 else if((funct7[6:2]==`FCVT_F_I_f5) && opcode == `FP_OPCODE) begin
232 if(issp)begin
233 let x <-inst_fpu_int_to_fp._start(operand1, imm[0],imm[1], funct3);
234 Floating_output#(`Reg_width) y=?;
235 `ifdef dpfpu
236 y.final_result={'1,x.final_result};
237 `else
238 y.final_result=x.final_result;
239 `endif
240 y.fflags=x.fflags;
241 ff_result.enq(y);
242 end
243 else begin
244 let x<-inst_dpfpu_int_to_fp._start(operand1,imm[0],imm[1],funct3);
245 ff_result.enq(x);
246 end
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
248 end
249 else if((funct7[6:2] == `FSGNJN_f5) && opcode == `FP_OPCODE)begin
250 if(issp)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=?;
254 `ifdef dpfpu
255 y.final_result={'1,x.final_result};
256 `else
257 y.final_result=x.final_result;
258 `endif
259 y.fflags=x.fflags;
260 ff_result.enq(y);
261 end
262 else begin
263 let x<-inst_dpfpu_sign_injection._start(operand1,operand2,funct3);
264 ff_result.enq(x);
265 end
266 `ifdef verbose $display($time,"\tGiving inputs to the fpu sign injection"); `endif
267 end
268 else if((funct7[6:2] == `FCVT_I_F_f5) && opcode == `FP_OPCODE) begin
269 if(issp) 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);
275 ff_result.enq(x);
276 end
277 else begin
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);
282 ff_result.enq(x);
283 end
284 `ifdef verbose $display($time,"\tGiving Inputs to fpu to int Conversion Module"); `endif
285 end
286 else if(((funct7[6:2] == `FCLASS_f5)&&(funct3=='b001))&&(opcode == `FP_OPCODE))begin
287 if(issp) 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};
294 ff_result.enq(y);
295 end
296 else begin
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);
301 ff_result.enq(x);
302 end
303 `ifdef verbose $display($time,"\tGiving inputs to floating classify module"); `endif
304 end
305 else if((funct7[6:2] == `FCVT_S_D_f5) && opcode == `FP_OPCODE)begin
306 if(!issp) 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);
313 ff_result.enq(x);
314 end
315 else begin
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=?;
322 `ifdef dpfpu
323 y.final_result = {'hffffffff,x.final_result[31:0]};
324 `else
325 y.final_result = x.final_result;
326 `endif
327 y.fflags=x.fflags;
328 ff_result.enq(y);
329 end
330 end
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
337 `ifdef dpfpu
338 final_result = {'1,operand1[31:0]};
339 `else
340 final_result= operand1[31:0];
341 `endif
342 ff_result.enq(Floating_output{final_result:final_result, fflags : 0});
343 end
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});
352 end
353 else if(((funct7[6:2] == `FADD_f5 || funct7[6:2] == `FSUB_f5) && opcode == `FP_OPCODE))begin // add sub
354 rg_multicycle_op<=True;
355 if(issp) begin
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));
360 let sign1 = 0;
361 let sign2 = op1[31];
362 let sign3 = op2[31];
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);
364 end
365 else begin
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));
369 let sign1 = 0;
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);
373 end
374 `ifdef verbose $display($time,"\tGiving inputs to the fpu add_sub"); `endif
375 end
376 else if((funct7[6:2] == `FDIV_f5) && opcode == `FP_OPCODE)begin// spfpu divider
377 rg_multicycle_op<=True;
378 if(issp) begin
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));
384 end
385 else begin
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));
390 end
391 `ifdef verbose $display($time,"\tGiving inputs to the spfpu divider"); `endif
392 end
393 else if((funct7[6:2] == `FSQRT_f5) && opcode == `FP_OPCODE)begin// sqrt
394 rg_multicycle_op<=True;
395 if(issp) begin
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));
401 end
402 else begin
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
408 end
409 end
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
413 if(issp) begin
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));
418 let sign1 = op1[31];
419 let sign2 = op2[31];
420 let sign3 = 0;
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);
422 end
423 else begin
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];
429 let sign3 = 0;
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);
431 end
432 `ifdef verbose $display($time,"\tGiving inputs to the spfloating multiplier module"); `endif
433 end
434 else if((opcode == 'b0000) || (opcode == 'b0001) || (opcode == 'b0010) || opcode == 'b0011)begin
435 rg_multicycle_op<=True;
436 if(issp) begin
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));
442 let sign1 = op1[31];
443 let sign2 = op2[31];
444 let sign3 = op3[31];
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);
446 end
447 else begin
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);
456 end
457 `ifdef verbose $display($time,"\tOperand 1: %h Operand 2: %h Operand 3: %h",operand1, operand2, operand3); `endif
458 end
459 endrule
460
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=?;
466 y.fflags=x.fflags;
467 `ifdef dpfpu
468 y.final_result={'1,x.final_result};
469 `else
470 y.final_result=x.final_result;
471 `endif
472 ff_result.enq(y);
473 rg_multicycle_op<=False;
474 endrule
475
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=?;
481 y.fflags=x.fflags;
482 y.final_result=x.final_result;
483 ff_result.enq(y);
484 rg_multicycle_op<=False;
485 endrule
486
487 //rule to give inputs to spfpu square root module
488
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
492 let x = res;
493 Floating_output#(`FLEN) y=?;
494 y.fflags=x.fflags;
495 `ifdef dpfpu
496 y.final_result={'1,x.final_result};
497 `else
498 y.final_result=x.final_result;
499 `endif
500 ff_result.enq(y);
501 rg_multicycle_op<=False;
502 endrule
503
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
507 let x = res;
508 Floating_output#(`FLEN) y=?;
509 y.fflags=x.fflags;
510 y.final_result=x.final_result;
511 ff_result.enq(y);
512 rg_multicycle_op<=False;
513 endrule
514
515
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=?;
521 y.fflags=x.fflags;
522 `ifdef dpfpu
523 y.final_result={'hffffffff,x.final_result[31:0]};
524 `else
525 y.final_result=x.final_result;
526 `endif
527 ff_result.enq(y);
528 `ifdef verbose $display($time,"\tFMA Result : %16h", y.final_result); `endif
529 rg_multicycle_op<=False;
530 endrule
531
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=?;
537 y.fflags=x.fflags;
538 y.final_result=x.final_result;
539 ff_result.enq(y);
540 `ifdef verbose $display($time,"\tFMA Result : %16h", y.final_result); `endif
541 rg_multicycle_op<=False;
542 endrule
543
544 rule flush_fifo(wr_flush);
545 ff_result.clear;
546 rg_multicycle_op<=False;
547 endrule
548 //rule to give inputs to spfloating multiplier
549
550 // input method to start the floating point operation
551
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 {
554 operand1 : operand1,
555 operand2 : operand2,
556 operand3 : operand3,
557 opcode : opcode,
558 funct7 : funct7,
559 funct3 : funct3,
560 imm : imm,
561 fsr : fsr,
562 issp : issp
563 });
564 endmethod
565
566 method ActionValue#(Floating_output#(`FLEN)) get_result;
567 ff_result.deq;
568 return ff_result.first;
569 endmethod
570 method Action flush;
571 wr_flush<=True;
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();
578 endmethod
579
580 endmodule
581 endpackage