replace defined_parameters with core_parameters
[shakti-core.git] / src / core / fpu / fpu_divider.bsv
1 /*
2 Authors : Vinod.G, Arjun Menon, Aditya Govardhan
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_divider;
10 import DReg::*;
11 import defined_types::*; //contains typedef of exceptions which are generated here
12 import integer_divider::*; //divider module
13 `include "core_parameters.bsv"
14 import RegFile::*;
15
16 typedef struct{
17 Bit#(TAdd#(fpexp,2)) exponent;
18 Bit#(TAdd#(fpman,1)) dividend;
19 Bit#(TAdd#(fpman,1)) divisor;
20 bit sign;
21 bit invalid;
22 bit infinity;
23 bit dz;
24 bit zero;
25 Bit#(3) rounding_mode;
26 bit quiet_nan;
27 } Stage1_type#(numeric type fpman,numeric type fpexp) deriving (Bits,Eq); //Structure of 1st Stage of the pipeline
28
29 typedef struct {
30 Bit#(fpexp2) exponent;
31 Bit#(1) sign;
32 Bit#(1) infinity;
33 Bit#(1) invalid;
34 Bit#(1) dz;
35 Bit#(1) zero;
36 Bit#(3) rounding_mode;
37 bit quiet_nan;
38 } Stage2_type#(numeric type fpexp2) deriving (Bits,Eq);
39
40 typedef struct {
41 Bit#(TAdd#(fpman,4)) lv_quotient;
42 Bit#(TAdd#(fpman,5)) lv_remainder;
43 Bit#(fpexp2) lv_exponent;
44 Bit#(1) lv_sign;
45 Bit#(1) lv_infinity;
46 Bit#(1) lv_invalid;
47 Bit#(1) lv_dz;
48 bit lv_underflow;
49 bit lv_overflow;
50 bit lv_sticky;
51 Bit#(1) lv_zero;
52 Bit#(3) lv_rounding_mode;
53 bit lv_quotient_is_subnormal;
54 bit quiet_nan;
55 } Stage3_type#(numeric type fpexp2, numeric type fpman) deriving (Bits,Eq);
56
57 typedef enum {
58 Begin,
59 Stage1,
60 Stage2,
61 Stage3
62 }Div_states deriving (Bits,Eq);
63
64
65 interface Ifc_fpu_divider#(numeric type fpinp, numeric type fpman, numeric type fpexp);
66 method Action _start(Bit#(1) lv_sign, Bit#(fpman) lv_mantissa1, Bit#(fpexp) lv_exponent1, Bit#(fpman) lv_mantissa2, Bit#(fpexp) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
67 method Floating_output#(fpinp) final_result_(); // Output method
68 method Action flush;
69 endinterface
70
71 `ifdef fpu_hierarchical
72 interface Ifc_fpu_divider32;
73 method Action _start(Bit#(1) lv_sign, Bit#(23) lv_mantissa1, Bit#(8) lv_exponent1, Bit#(23) lv_mantissa2, Bit#(8) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
74 method Floating_output#(32) final_result_(); // Output method
75 method Action flush;
76 endinterface
77
78 interface Ifc_fpu_divider64;
79 method Action _start(Bit#(1) lv_sign, Bit#(52) lv_mantissa1, Bit#(11) lv_exponent1, Bit#(52) lv_mantissa2, Bit#(11) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
80 method Floating_output#(64) final_result_(); // Output method
81 method Action flush;
82 endinterface
83 `endif
84
85 //(*synthesize*)
86 module mkfpu_divider(Ifc_fpu_divider#(fpinp,fpman,fpexp))
87 provisos(
88 Add#(TAdd#(fpman,fpexp),1,fpinp), // fpman -23 fpexp=8 fpinp = 32
89 Add#(fpman,2,fpman2), // fpman2 = 25
90 Add#(fpman2,2,fpman4), // fpman4 = 27
91 Add#(fpman4,1,fpman5), // fpman5 = 28
92 Add#(fpexp,2,fpexp2), // fpexp2 = 10
93 Add#(fpman5,1,fpman6), // fpman6 = 29
94 Add#(fpman4,fpman6,acc_bits), // acc_bits= 56
95 Add#(fpexp2,b__,fpman),
96 Add#(TSub#(fpexp,1),c__,fpman),
97 //per request of bsc
98 Add#(a__, 1, fpexp2),
99 Add#(d__, TLog#(TAdd#(1, TAdd#(fpexp, c__))), fpexp2),
100 Add#(e__, TLog#(fpman5), fpexp2),
101 Add#(1, f__, fpman2),
102 Add#(g__, 1, fpman4),
103 Add#(h__, TLog#(TAdd#(1, TAdd#(c__, fpexp))), fpexp2),
104 Add#(1, fpexp2, TAdd#(fpexp, i__))
105 );
106
107 Ifc_integer_divider#(fpman4) int_div <- mkinteger_divider(); // instantiation of divider module
108
109 //Wire#(Floating_output#(fpinp)) wr_final_out <- mkWire(); // instantiation of output FIFO whose structure definition is given in riscv_types.bsv
110 Wire#(Floating_output#(fpinp)) wr_final_out <- mkWire();
111 Reg#(Stage1_type#(fpman,fpexp)) rg_stage1 <- mkRegU(); // instantiation of Stage 1 FIFO
112 Reg#((Stage2_type#(fpexp2))) rg_stage2 <- mkRegU();
113 Reg#((Stage3_type#(fpexp2,fpman))) rg_stage3 <- mkRegU();
114 Reg#(Div_states) rg_state_handler <- mkReg(Begin);
115 Wire#(Bool) wr_flush <- mkDWire(False);
116 let fPINP = valueOf(fpinp);
117 let fPMAN = valueOf(fpman);
118 let fPMAN5 = valueOf(fpman5);
119 let fPEXP = valueOf(fpexp);
120 let aCC = valueOf(acc_bits);
121
122 (*mutually_exclusive = "rl_flush,rl_stage2,rl_stage3"*)
123 rule rl_flush(wr_flush);
124 rg_state_handler <= Begin;
125 //rg_stage1 <= tagged Invalid;
126 //rg_stage2 <= tagged Invalid;
127 int_div.flush();
128 endrule
129
130 //This is the second stage of the pipe. Here the division of the two mantissas take place. Rest of the data are enqueued in another FIFO.
131 rule rl_stage2 (rg_state_handler == Stage1 && !wr_flush);
132 int_div._inputs({rg_stage1.divisor,3'd0},
133 {rg_stage1.dividend,3'd0}
134 );
135 rg_state_handler <= Stage2;
136 //`ifdef verbose $display("Dividing Op1: %h (%d) Op2: %h (%d)",{stage1_data.dividend,3'd0},{stage1_data.dividend,3'd0},{stage1_data.divisor,3'd0},{stage1_data.divisor,3'd0}); `endif
137 //`ifdef verbose $display("dz : %b",stage1_data.dz); `endif
138 rg_stage2 <= Stage2_type { exponent : rg_stage1.exponent,
139 sign : rg_stage1.sign,
140 infinity : rg_stage1.infinity,
141 invalid : rg_stage1.invalid,
142 dz : rg_stage1.dz,
143 zero : rg_stage1.zero,
144 rounding_mode : rg_stage1.rounding_mode,
145 quiet_nan : rg_stage1.quiet_nan
146 };
147
148
149 endrule
150
151 rule rl_stage3(rg_state_handler == Stage2 && !wr_flush);
152 let int_out = int_div.result_();
153 Bit#(TSub#(fpexp,1)) bias = '1;
154 `ifdef verbose $display("Int Data %h", int_out); `endif
155 Bit#(fpman4) lv_quotient = int_out[fPMAN+3:0]; //Quotient from the integer divider
156 Bit#(fpman5) lv_remainder = int_out[aCC-1:fPMAN5]; //Remainder from the integer divider
157 Bit#(fpexp2) lv_exponent = rg_stage2.exponent;
158 Bit#(1) lv_sign = rg_stage2.sign;
159 Bit#(1) lv_infinity = rg_stage2.infinity;
160 Bit#(1) lv_invalid = rg_stage2.invalid;
161 Bit#(1) lv_dz = rg_stage2.dz;
162 Bit#(1) lv_zero = rg_stage2.zero;
163 Bit#(3) lv_rounding_mode = rg_stage2.rounding_mode;
164 let quiet_nan = rg_stage2.quiet_nan;
165
166 //rg_stage2 <= tagged Invalid;
167
168 bit lv_underflow = 0;
169 bit lv_overflow = 0;
170
171 Int#(fpexp2) lv_actual_exponent = unpack(lv_exponent - {3'b0,bias});
172 //Change-1 Removing not_required variable
173 // Int#(fpman) lv_actual_exponent_temp = signExtend(lv_actual_exponent);
174 let msb_zeros = pack(countZerosMSB(lv_quotient));
175 `ifdef verbose $display("MSB Zeros: %d",msb_zeros); `endif
176 let lsb_zeros = 0;
177
178 // lv_quotient_is_subnormal construct is like a flag which can be used in difficult situations
179 bit lv_quotient_is_subnormal = 0;
180 bit lv_sticky = lv_quotient[0];
181 //Bit#(fpman) bias_temp = zeroExtend(bias);
182 /*
183 if exponent is > 128 then obviously none of the numbers are subnormal
184 so the product is of the form 1x.xxxx or 01.xxxx
185 the overflow conditions are handled in the following if condition accordingly
186 */
187 if(lv_actual_exponent > unpack({3'b0,bias} + 1)) begin //CHECK THIS CASE WITHOUT FAIL - OPTIMIZE IT
188 lv_overflow = 1;
189 `ifdef verbose $display("lv_overflow!!!"); `endif
190 end
191 /*
192 -bias -fPMAN
193 -150 = -126 -23 -1
194 -1075 = -1022 -52 -1 //for DP?
195 -1 is for the implicit bit
196 i.e. if all the bits are shifted out then its an underflow
197 */
198 else if(lv_actual_exponent < unpack(-zeroExtend(bias)-fromInteger(fPMAN)-1)) begin //TODO What here? TODO Check <-150 or <-151
199 //else if(lv_actual_exponent_temp < unpack(-bias_temp-fromInteger(fPMAN)-1)) begin //TODO What here? TODO Check <-150 or <-151
200 //`ifdef verbose $display("lv_actual_exponent : %d bias-fpman-1 : %d", lv_actual_exponent, -bias_temp-fromInteger(fPMAN-1)); `endif
201 lv_underflow = 1;
202 lv_quotient = 1;
203 lv_exponent = 0;
204 //When the exponent is < -151, sticky bit is automatically set to one
205 `ifdef verbose $display("lv_underflow!!!"); `endif
206 end
207
208 else begin
209
210 // possible shift is positive when exponent is lesser than -126
211 //Change-x it's enough if possible shift is reduced from lv_exponent - reducing again from bias is actually redundant and incurs another adder
212 //Same Experiment here, do all the if-else parallely and just use the if and else for assignments
213 Int#(fpexp2) possible_shift = 1-unpack(lv_exponent);
214 `ifdef verbose $display("possible_shift = %0d", possible_shift); `endif
215
216 lsb_zeros = pack(countZerosLSB(lv_quotient));
217
218 let lv_quotient_shiftR = lv_quotient >> pack(possible_shift);
219 //lv_quotient = {lv_quotient[fPMAN+3:1], lv_quotient[0] | lv_sticky};
220 let lv_exponent_inc_shift = lv_exponent + pack(possible_shift);
221 let shift_neg = (~pack(possible_shift)+1);
222 let lv_quotient_shiftL_expo = lv_quotient << shift_neg;
223 let lv_exponent_sub_shift = lv_exponent - shift_neg;
224 let lv_quotient_shiftL_zerosMSB = lv_quotient << (msb_zeros);
225 let lv_exponent_sub_zerosMSB = lv_exponent - (zeroExtend(msb_zeros));
226
227
228
229 if(possible_shift > 0) begin
230
231 //Setting sticky if all lsb zeros are removed out
232
233 if(possible_shift > unpack(zeroExtend(lsb_zeros)) || lv_quotient[0] == 1)
234 lv_sticky = 1;
235
236 //Handling sticky
237 //lv_sticky = lv_quotient[0];
238 lv_quotient = {lv_quotient_shiftR[fPMAN+3:1],lv_quotient_shiftR[0]|lv_sticky};
239 lv_sticky = lv_quotient[0];
240 lv_exponent = lv_exponent_inc_shift;
241
242 `ifdef verbose $display("lv_quotient = %h since exp < -126", lv_quotient); `endif
243 `ifdef verbose $display("and thus the sticky bit = %b", lv_sticky); `endif
244
245 `ifdef verbose $display("lv_exponent : %b",lv_exponent); `endif
246 lv_quotient_is_subnormal = 1;
247 end
248
249 /*
250 msb_zeros != 1 means product is of the form 00.xxxx, important case
251 */
252 else if(msb_zeros != 0) begin
253 /*
254 if possible shift is < the number of leading zeros then the number can't be made normal
255 */
256 if(shift_neg < zeroExtend(msb_zeros)) begin
257 lv_quotient = lv_quotient_shiftL_expo;
258 lv_exponent = lv_exponent_sub_shift;
259 lv_quotient_is_subnormal = 1;
260 end
261 /*
262 if exponent affords to give away enough such that shifting left leads to 01.xxxx and exponent >= -126
263 */
264 else begin
265 lv_quotient = lv_quotient_shiftL_zerosMSB;
266 lv_exponent = lv_exponent_sub_zerosMSB;
267 lv_quotient_is_subnormal = 0;
268 end
269 end
270 end
271
272 if(lv_quotient_is_subnormal == 1)
273 lv_exponent = 0;
274
275 rg_state_handler <= Stage3;
276 rg_stage3 <= Stage3_type{
277 lv_quotient : lv_quotient,
278 lv_remainder : lv_remainder,
279 lv_exponent : lv_exponent,
280 lv_sign : lv_sign,
281 lv_infinity : lv_infinity,
282 lv_invalid : lv_invalid,
283 lv_underflow : lv_underflow,
284 lv_overflow : lv_overflow,
285 lv_dz : lv_dz,
286 lv_zero : lv_zero,
287 lv_sticky : lv_sticky,
288 lv_quotient_is_subnormal : lv_quotient_is_subnormal,
289 lv_rounding_mode : lv_rounding_mode,
290 quiet_nan : quiet_nan
291 };
292
293 endrule
294 //------------------------------------------------------------------Ex-1 Splitting Here ---------------------------------------------------------//
295 //Required - 1. lv_quotient 2. lv_remainder 3. lv_quotient_is_subnormal 4. lv_rounding_mode 5. all exception lv's
296 //Splitting the stage here
297
298 rule rl_stage4(rg_state_handler==Stage3 && !wr_flush);
299
300 let lv_quotient = rg_stage3.lv_quotient;
301 let lv_remainder = rg_stage3.lv_remainder;
302 let lv_exponent = rg_stage3.lv_exponent;
303 let lv_sign = rg_stage3.lv_sign;
304 let lv_infinity = rg_stage3.lv_infinity;
305 let lv_invalid = rg_stage3.lv_invalid;
306 let lv_dz = rg_stage3.lv_dz;
307 let lv_zero = rg_stage3.lv_zero;
308 let lv_rounding_mode = rg_stage3.lv_rounding_mode;
309 let lv_overflow = rg_stage3.lv_overflow;
310 let lv_underflow = rg_stage3.lv_underflow;
311 let lv_sticky = rg_stage3.lv_sticky;
312 let lv_quotient_is_subnormal = rg_stage3.lv_quotient_is_subnormal;
313 let quiet_nan = rg_stage3.quiet_nan;
314
315 `ifdef verbose $display("lv_quotient = %h, lv_remainder = %h, lv_exponent = %h", lv_quotient, lv_remainder, lv_exponent); `endif
316
317 bit lv_guard = lv_quotient[2];
318 bit lv_round = lv_quotient[1];
319 bit lv_inexact = 0;
320 bit lv_round_up = 0;
321
322 if(lv_remainder!=0 || lv_quotient[0] == 1) // if the remainder is zero, sticky bit is set to 1.
323 lv_sticky = 1;
324
325 if((lv_sticky | lv_guard | lv_round) == 1)// if any of the sticky,guard or round bit is set, the value is inexact.
326 lv_inexact = 1;
327
328 if(lv_inexact == 1 && lv_quotient_is_subnormal == 1) //Was buried deep inside the SPEC. Phew! Maybe Wrong!!!
329 lv_underflow = 1;
330
331 // Following if-else condition determine the value of lv_round_up. If set, the mantissa needs to be incremented, else the mantissa remains unchanged.
332 if(lv_rounding_mode == 'b000)
333 lv_round_up = lv_guard & (lv_round|lv_sticky|lv_quotient[3]);
334 else if(lv_rounding_mode == 'b100)
335 lv_round_up = lv_guard; //& (lv_round|lv_sticky|lv_sign);
336 else if(lv_rounding_mode == 'b011)
337 lv_round_up = (lv_guard|lv_round|lv_sticky) & ~lv_sign;
338 else if(lv_rounding_mode == 'b010)
339 lv_round_up = (lv_guard|lv_round|lv_sticky) & lv_sign;
340
341 // otherwise if round to zero mode, then do nothing
342
343 Bit#(fpman2) lv_rounded_quotient = {1'b0,lv_quotient[fPMAN+3:3]};
344
345 if( lv_round_up == 1) begin
346 lv_rounded_quotient = lv_rounded_quotient + 1;
347 end
348
349 if(lv_rounded_quotient[fPMAN+1] == 1 ) begin
350 `ifdef verbose $display("Exponent Incremented 1"); `endif
351 lv_exponent = lv_exponent + 1;
352 lv_rounded_quotient = lv_rounded_quotient >> 1;
353 end
354 if(lv_quotient[fPMAN+3] == 0 && lv_rounded_quotient[fPMAN] == 1) begin
355 `ifdef verbose $display("Exponent Incremented 2"); `endif
356 lv_exponent = lv_exponent + 1;
357 end
358 Bit#(fpexp) out_exp = lv_exponent[fPEXP-1:0];
359 Bit#(fpman) out_man = lv_rounded_quotient[fPMAN-1:0];
360 Bit#(fpexp) exp_all_zeros = '0;
361 Bit#(fpexp) exp_all_ones = '1;
362 Bit#(TSub#(fpexp,1)) exp_all_ones_1 = '1;
363 Bit#(fpman) man_all_zeros = '0;
364 Bit#(fpman) man_all_ones = '1;
365 Bit#(TSub#(fpman,1)) man1_all_zeros = '0;
366 Bit#(TSub#(fpman,1)) man_all_ones_1 = '1;
367 Bit#(fpinp) lv_final_output= 0;
368 Bit#(5) exception = 0;
369
370 // result is infinity
371 if(lv_infinity == 1) begin
372 lv_final_output = {lv_sign, exp_all_ones, man_all_zeros};
373 if(lv_dz==1)
374 exception[3] = 1;
375 end
376
377 // the result is invalid
378 else if(lv_invalid == 1) begin
379 lv_final_output = {1'b0, exp_all_ones,1'b1, man1_all_zeros};
380 exception[4] = ~quiet_nan;//Invalid;
381 end
382 // operation is divide by zero
383 else if(lv_dz==1) begin
384 lv_final_output= {lv_sign, exp_all_ones, man_all_zeros};
385 exception[3] = 1;//Divide_by_Zero;
386 end
387 // result is zero
388 else if(lv_zero == 1)
389 lv_final_output={lv_sign,exp_all_zeros,man_all_zeros};
390 // result is underflow
391 else if(lv_underflow == 1) begin
392
393 lv_final_output= {lv_sign,exp_all_zeros,lv_rounded_quotient[fPMAN-1:0]}; //TODO to verify if it needs to be lv_rounded_quotient[22:1] and lv_inexact bit.
394 exception[1] = 1;//Underflow;
395 exception[0] = 1;
396 end
397 // result is overflow
398 else if(lv_overflow == 1 || out_exp == '1) begin
399 exception[2] = 1;//Overflow;
400 exception[0] = 1; //inexact -- is it? let's see!
401 if(lv_rounding_mode == 'b001)
402 lv_final_output = {lv_sign,{exp_all_ones_1,1'b0},man_all_ones};
403 else if(lv_rounding_mode == 'b010 && lv_sign ==0)
404 lv_final_output = {lv_sign,{exp_all_ones_1,1'b0},man_all_ones};
405 else if(lv_rounding_mode == 'b011 && lv_sign==1)
406 lv_final_output = {lv_sign,{exp_all_ones_1,1'b0},man_all_ones};
407 else
408 lv_final_output ={lv_sign,exp_all_ones,man_all_zeros};
409 end
410 else begin
411 lv_final_output = {lv_sign,out_exp,out_man};
412 if(lv_inexact==1)
413 exception[0] = 1;//Inexact;
414 end
415 rg_state_handler <= Begin;
416 // Forming the new Floating point Status Register
417 // Enqueing the final result into the output FIFO
418 wr_final_out <= Floating_output{
419 final_result : lv_final_output,//Appending zeros at the MSB since the result is a Single Precision number which is 32-bits wide whereas the rob entries are 64-bits.
420 fflags : exception};
421
422 endrule
423
424 method Action _start(Bit#(1) lv_sign, Bit#(fpman) lv_mantissa1, Bit#(fpexp) lv_exponent1, Bit#(fpman) lv_mantissa2, Bit#(fpexp) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
425
426 Bit#(TSub#(fpexp,1)) bias = '1;
427 let condFlags1 = tpl_1(flags);
428 let condFlags2 = tpl_2(flags);
429 Int#(fpexp) actual_exponent1 = unpack(lv_exponent1 - {1'b0,bias});
430 Int#(fpexp) actual_exponent2 = unpack(lv_exponent2 - {1'b0,bias});
431 `ifdef verbose $display("Exp1: %h, Man1: %h, Exp2: %h Man2: %h",lv_exponent1,lv_mantissa1,lv_exponent2,lv_mantissa2); `endif
432 `ifdef verbose $display("condFlags1 : %b condFlags2: %b",condFlags1,condFlags2); `endif
433 Bit#(1) lv_inf = 0;
434 Bit#(1) lv_inv = 0;
435 Bit#(1) lv_zero = 0;
436 Bit#(1) lv_dz = 0;
437 bit quiet_nan = condFlags1[2] & ~condFlags2[0] | condFlags2[2] & ~condFlags1[0] ;
438 Bit#(1) lv_op1_is_zero = condFlags1[3]; //1 when operand1=0
439 Bit#(1) lv_op2_is_zero = condFlags2[3]; //1 when operand2=0
440
441 Bit#(1) lv_op1_subnormal = condFlags1[4]; //1 when operand1 is subnormal
442 Bit#(1) lv_op2_subnormal = condFlags2[4]; //1 when operand2 is subnormal
443
444 Bit#(1) lv_op1_is_infinity = condFlags1[1];
445 Bit#(1) lv_op2_is_infinity = condFlags2[1];
446
447 `ifdef verbose $display("op1 is subnormal = %b , op2 is subnormal = %b", lv_op1_subnormal, lv_op2_subnormal); `endif
448 // `ifdef verbose $display("sign1 = %b exponent1 = %b actual_exponent1 = %0d mantissa1 = %b.%b", _operand1[31], _operand1[fPINP-2:fPMAN], actual_exponent1, ~lv_op1_subnormal, _operand1[fPMAN-1:0]); `endif
449 // `ifdef verbose $display("sign2 = %b exponent2 = %b actual_exponent2 = %0d mantissa2 = %b.%b", _operand2[31], _operand2[fPEXP-1:fPMAN], actual_exponent2, ~lv_op2_subnormal, _operand2[fPMAN-1:0]); `endif
450
451
452 if(((condFlags1[2] | condFlags1[0])==1) || ((condFlags2[2] | condFlags2[0])==1) || (lv_op1_is_infinity == 1 && lv_op2_is_infinity == 1) || (lv_op1_is_zero == 1 && lv_op2_is_zero == 1)) begin //op1 or op2 are NaN (or) both are infinity (or) both are zero
453 lv_inv = 1; //result is invalid
454 end
455 else if(lv_op1_is_infinity ==1) begin //op 2 is neither NaN nor infinity, and op1 is infinity
456 lv_inf=1; //result is infinity
457 end
458 else if(lv_op2_is_zero==1) begin //op 1 is neither NaN nor infinity, and op2 is zero
459 lv_inf=1; //result is infinity
460 lv_dz=1; //setting the divide by zero flag
461 end
462 else if(lv_op2_is_infinity == 1 || lv_op1_is_zero == 1) //{op1 and op2 are not NaN} (and) {op1 is zero and op2 is not zero (or) op2 is infinity and op1 is not infinity}
463 lv_zero=1; //result is zero
464
465
466 let man1 ={~lv_op1_subnormal,lv_mantissa1};
467 let man2 ={~lv_op2_subnormal,lv_mantissa2};
468 let zeros1 =countZerosMSB(man1);
469 let zeros2 =countZerosMSB(man2);
470 man1=man1<<zeros1;
471 man2=man2<<zeros2;
472 Bit#(fpexp2) exp1={2'b0,lv_exponent1};
473 Bit#(fpexp2) exp2={2'b0,lv_exponent2};
474 exp1=exp1- zeroExtend(unpack(pack(zeros1)));
475 exp2=exp2- zeroExtend(unpack(pack(zeros2)));
476 /*
477 total_baised_exponent = (biased_exponent - bias) - (1 - bias) + bias in the case of normal divided by subnormal
478 total_biased_exponent = (1 - bias) - (biased_exponent - bias) + bias in the case of subnormal divided by normal
479 total_biased_exponent = (biased_exponent - bias) - (biased_exponent - bias) + bias in the case of normal divided by normal
480 total_biased_exponent = (1 - bias) - (1 - bias) + bias in the case of subnormal divided by normal
481
482 SO equivalently to handle all the cases:
483 total_biased_exponent = bias + (op1_biased_expo + is_op1_denorm) - (op2_biased_expo + is_op2_denorm)
484 */
485
486 Bit#(fpexp2) lv_exponent = {3'b0,bias} + ((exp1 + zeroExtend(lv_op1_subnormal)) - (exp2 + zeroExtend(lv_op2_subnormal))); //error will come obv
487
488
489 Int#(fpexp2) lv_actual_exponent = unpack(lv_exponent - {3'b0,bias});
490 `ifdef verbose $display("lv_sign: %h lv_exponent = %h, lv_actual_exponent = %d",lv_sign, lv_exponent, lv_actual_exponent); `endif
491 `ifdef verbose $display("lv_inv: %b lv_inf %b lv_dz %b lv_zero %b",lv_inv,lv_inf,lv_dz,lv_zero); `endif
492 rg_state_handler <= Stage1;
493 rg_stage1 <= Stage1_type { exponent : lv_exponent,
494 dividend : man1,
495 divisor : man2,
496 sign : lv_sign,
497 invalid : lv_inv,
498 infinity : lv_inf,
499 dz : lv_dz,
500 zero : lv_zero,
501 rounding_mode : rounding_mode,
502 quiet_nan : quiet_nan
503 };
504
505 endmethod
506
507 // Output method which send the result
508 method Floating_output#(fpinp) final_result_();
509 return wr_final_out;
510 endmethod
511
512 method Action flush;
513 wr_flush <= True;
514 endmethod
515
516 // This method needs to be called whenever the method final_result is called.
517 // This method frees the final FIFO and resets the ready signal.
518
519 endmodule
520
521 /* TEST BENCH */
522
523 //(*synthesize*)
524 /*
525 module mkTb_fpu_divider(Empty);
526
527 function Tuple2#(Bit#(5), Bit#(5)) condFlags (Tuple2#(Bit#(52), Bit#(11)) x, Tuple2#(Bit#(52), Bit#(11)) y);
528 let man1 = tpl_1(x);
529 let expo1 = tpl_2(x);
530 let man2 = tpl_1(y);
531 let expo2 = tpl_2(y);
532 Bit#(5) flags1, flags2;
533 Bool expZ1 = (expo1 == 0);
534 Bool manZ1 = (man1 == 0);
535 Bool expO1 = (expo1 == '1);
536 Bool manO1 = (man1 == '1);
537 Bool topB1 = (man1[51] == 1);
538 Bool expZ2 = (expo2 == 0);
539 Bool manZ2 = (man2 == 0);
540 Bool expO2 = (expo2 == '1);
541 Bool manO2 = (man2 == '1);
542 Bool topB2 = (man2[51] == 1);
543 flags1 = {pack(expZ1 && !manZ1),pack(manZ1 && expZ1),pack(expO1 && topB1),pack(expO1 && manZ1),pack(expO1 && !topB1)}; //Denormal, isZero, QNaN, Infinity, SNaN
544 flags2 = {pack(expZ2 && !manZ2),pack(manZ2 && expZ2),pack(expO2 && topB2),pack(expO2 && manZ2),pack(expO2 && !topB2)}; //Denormal, isZero, QNaN, Infinity, SNaN
545 return tuple2(flags1,flags2);
546 endfunction
547
548 function Tuple2#(Bit#(52),Bit#(52)) getMantissa (Bit#(64) op1, Bit#(64) op2);
549 return tuple2(op1[51:0],op2[51:0]);
550 endfunction
551
552 function Tuple2#(Bit#(11), Bit#(11)) getExp (Bit#(64) op1, Bit#(64) op2);
553 return tuple2(op1[62:52], op2[62:52]);
554 endfunction
555
556
557 // Reg#(Bit#(64)) rg_operand1<-mkReg(64'h006069e454c8dc70);
558 // Reg#(Bit#(64)) rg_operand2<-mkReg(64'h41e4864ef5800000);
559 Reg#(Bit#(64)) rg_operand1<-mkReg(64'h00000000fffff89d);
560 Reg#(Bit#(64)) rg_operand2<-mkReg(64'hbff0000000000000);
561
562 Reg#(Bit#(32)) rg_clock<-mkReg(0);
563 Ifc_fpu_divider#(64,52,11) divider<-mkfpu_divider();
564
565 Reg#(Bit#(32)) rg_arbit <-mkReg(0);
566
567 rule rl_clk_count;
568 rg_clock<=rg_clock+1;
569 endrule
570
571
572 rule rl_start_1(rg_clock=='d0);
573 let {man1,man2} = getMantissa(rg_operand1, rg_operand2);
574 let {exp1,exp2} = getExp(rg_operand1, rg_operand2);
575 let {x1,x2} = condFlags(tuple2(man1,exp1),tuple2(man2,exp2));
576 `ifdef verbose $display("Giving inputs rg_operand 1 : %h rg_operand 2 : %h through testbench",rg_operand1,rg_operand2,$time); `endif
577 divider._start(rg_operand1[63]^rg_operand2[63],man1,exp1,man2,exp2,3'b100,tuple2(x1,x2));
578 endrule
579
580 rule rl_display_result;
581 let abc = divider.final_result_();
582 `ifdef verbose $display("output: %h fflags: %h",abc.final_result, abc.fflags); `endif
583 endrule
584
585 rule rl_finish_(rg_clock=='d60);
586 $finish(0);
587 endrule
588
589 endmodule:mkTb_fpu_divider
590 */
591
592 `ifdef fpu_hierarchical
593 (*synthesize*)
594 module mkfpu_divider32(Ifc_fpu_divider32);
595 Ifc_fpu_divider#(32,23,8) uut <- mkfpu_divider();
596 method Action _start(Bit#(1) lv_sign, Bit#(23) lv_mantissa1, Bit#(8) lv_exponent1, Bit#(23) lv_mantissa2, Bit#(8) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
597 uut._start(lv_sign,lv_mantissa1,lv_exponent1,lv_mantissa2,lv_exponent2,rounding_mode,flags);
598 endmethod
599 method Floating_output#(32) final_result_(); // Output method
600 return uut.final_result_;
601 endmethod
602 method Action flush;
603 uut.flush;
604 endmethod
605 endmodule
606
607 (*synthesize*)
608 module mkfpu_divider64(Ifc_fpu_divider64);
609 Ifc_fpu_divider#(64,52,11) uut <- mkfpu_divider();
610 method Action _start(Bit#(1) lv_sign, Bit#(52) lv_mantissa1, Bit#(11) lv_exponent1, Bit#(52) lv_mantissa2, Bit#(11) lv_exponent2, Bit#(3) rounding_mode, Tuple2#(Bit#(5),Bit#(5)) flags);
611 uut._start(lv_sign,lv_mantissa1,lv_exponent1,lv_mantissa2,lv_exponent2,rounding_mode,flags);
612 endmethod
613 method Floating_output#(64) final_result_(); // Output method
614 return uut.final_result_;
615 endmethod
616 method Action flush;
617 uut.flush;
618 endmethod
619 endmodule
620 `endif
621
622 //module mkTb_fpu_divider_2(Empty);
623 //
624 // RegFile #(Bit #(10), Bit #(68)) input_data <- mkRegFileFullLoad("./testcases/Div_denormal_testcases.hex");
625 // Reg #(Bit #(10)) index <- mkReg(0);
626 //
627 // Reg #(Bit #(32)) state_clock <- mkReg(1);
628 // Reg #(Bit #(32)) rg_state <- mkReg(0);
629 // /*****************Module Instantiation******************************/
630 // Ifc_fpu_divider#(32,23,8) divider <- mkfpu_divider();
631 //
632 //
633 // /******************File Creation************************************/
634 // Reg#(int) cnt <- mkReg(0); //File Creation counter
635 // let fh <- mkReg(InvalidFile) ; //File Handler
636 // rule open (cnt == 0 ) ;
637 // File tb_mul_output <- $fopen("tb_div_output.hex", "w+");
638 // fh <= tb_mul_output;
639 // cnt <= 1 ;
640 // endrule
641 //
642 // /******************clock_count**************************************/
643 // rule state_clock_count;
644 // state_clock <= state_clock + 1;
645 // endrule
646 //
647 // /*******************input******************************************/
648 // rule take_input_in (rg_state == 0);
649 // divider._start(input_data.sub(index)[67:36],input_data.sub(index)[35:4],0,input_data.sub(index)[2:0]);
650 // index <= index + 1;
651 // rg_state <= 1;
652 // endrule
653 //
654 // /*******************output*****************************************/
655 // rule display_output (rg_state == 1);
656 // let abc = divider.final_result_();
657 // $fwrite(fh, "%h\n", abc.final_result[31:0]);
658 // rg_state <= 0;
659 // endrule
660 //
661 // /******************end testing*************************************/
662 // rule end_testing (index == 407);
663 // $finish(0);
664 // endrule
665 //
666 //endmodule
667 endpackage