011febd20d0ad8319c89e9f7f62e49caf0271365
[shakti-core.git] / src / core / fpu / fpu_dp_to_int.bsv
1 /*
2 Authors : Vinod.G
3 Email : g.vinod1993@gmail.com
4 Last Update : 27th November 2017
5 See LICENSE for more details
6 Description :
7 TODO
8 */
9
10 package fpu_dp_to_int;
11
12 import defined_types::*;
13 import UniqueWrappers::*;
14 `include "defined_parameters.bsv"
15 interface Ifc_fpu_dp_to_int;
16 method ActionValue#(Floating_output#(`Reg_width)) _start(Bit#(1) sign,Bit#(11) exponent, Bit#(52) mantissa, bit convert_unsigned, bit convert_long, Bit#(3) rounding_mode, Bit#(5) flags);
17 endinterface
18
19 `ifdef fpu_hierarchical
20 (*synthesize*)
21 `endif
22 module mkfpu_dp_to_int(Ifc_fpu_dp_to_int);
23 method ActionValue#(Floating_output#(`Reg_width)) _start(Bit#(1) lv_sign,Bit#(11) lv_exponent, Bit#(52) lv_mantissa, bit convert_unsigned, bit convert_long, Bit#(3) rounding_mode, Bit#(5) flags);
24 bit lv_overflow = 0;
25 bit lv_zero = flags[3];
26 bit lv_infinity = flags[1];
27 bit lv_invalid = flags[0] | flags[2];
28 bit lv_denormal = flags[4];
29 bit lv_manzero = |lv_mantissa;
30 bit lv_inexact = 0;
31 Bool to_round = False;
32 Bool rne = (rounding_mode == 3'b000);
33 Bool rtz = (rounding_mode == 3'b001);
34 Bool rdn = (rounding_mode == 3'b010);
35 Bool rup = (rounding_mode == 3'b011);
36 Bool rmm = (rounding_mode == 3'b100);
37 Bit#(12) lv_exp = {1'b0,lv_exponent};
38 `ifdef verbose $display("sign = %b exponent = %h mantissa = %h zero_flag = %b invalid_flag = %b infinity: %b Denormal : %b", lv_sign, lv_exponent, lv_mantissa, lv_zero, lv_invalid, lv_infinity, lv_denormal); `endif
39 Int#(11) lv_original_exponent = unpack(truncate(lv_exp - 1023)); // removing the bias
40 `ifdef verbose $display("lv_original_exponent : %d flags: %b",lv_original_exponent,flags); `endif
41 Bit#(`Reg_width) final_result = 0;
42 Bit#(TAdd#(52, `Reg_width)) final_man = {'0,1'b1,lv_mantissa};
43
44 if(lv_zero == 1)
45 final_result = 0;
46 else if(lv_denormal == 1 || (lv_original_exponent <= -1 && (lv_infinity|lv_invalid) == 0)) begin
47 if(lv_sign==1 && convert_unsigned==1 && ((lv_original_exponent==-1 && (rmm||(rne && lv_manzero==1))) || (lv_original_exponent<=-1 &&rdn)))
48 lv_invalid = 1;
49 else
50 lv_inexact = 1;
51 if(lv_sign == 0 && rup)
52 final_result = 1;
53 else if(rdn && lv_sign == 1 && convert_unsigned == 0)
54 final_result = '1;
55 else if(lv_original_exponent == -1 && (rmm||(rne && lv_manzero == 1)))begin
56 if(lv_sign == 0)
57 final_result = 1;
58 else if(convert_unsigned == 0)
59 final_result = '1;
60 else
61 final_result = 0;
62 end
63 else
64 final_result = 0;
65 end
66 else if(convert_long == 0) begin //FCVT.W.D FCVT.WU.D
67 if(convert_unsigned == 0) begin //FCVT.W.D
68 Bit#(31) all_ones = '1;
69 if(lv_infinity == 1 || lv_invalid == 1) begin
70 final_result = (lv_sign==1) ?(lv_invalid==1? zeroExtend(all_ones) : signExtend(32'h80000000)) : zeroExtend(all_ones);
71 end
72 else if(lv_original_exponent < 'd31) begin
73 final_man = final_man << lv_original_exponent;
74 Bit#(32) y = final_man[83:52];
75 final_result = signExtend(y);
76 lv_mantissa = final_man[51:0];
77 to_round = True;
78 end
79 else if(lv_original_exponent >= 'd31) begin
80 `ifdef verbose $display("Overflow");`endif
81 //lv_overflow = 1;
82 lv_invalid = 1;
83 if(lv_sign == 0)
84 final_result = zeroExtend(all_ones);
85 else begin
86 if(lv_original_exponent == 'd31 && lv_manzero == 0)
87 lv_invalid = 0;
88 final_result = signExtend(32'h80000000);
89 end
90 end
91 end
92 else begin //FCVT.WU.D
93 Bit#(32) all_ones = '1;
94 if(lv_infinity == 1 || lv_invalid == 1)
95 final_result = (lv_sign==1) ? (lv_invalid==1? signExtend(all_ones) : '0) : signExtend(all_ones);
96 else if(lv_original_exponent < 'd32) begin
97 final_man = final_man << lv_original_exponent;
98 Bit#(32) y = final_man[83:52];
99 `ifdef verbose $display("final_man = %d",final_man); `endif
100 final_result = signExtend(y);
101 lv_mantissa = final_man[51:0];
102 to_round = True;
103 end
104 else if(lv_original_exponent >= 'd32) begin
105 `ifdef verbose $display("Overflow");`endif
106 //lv_overflow = 1;
107 lv_invalid = 1;
108 if(lv_sign == 0)
109 final_result = signExtend(all_ones);
110 else
111 final_result = '0;
112 end
113 end
114 end
115 else begin
116 if(convert_unsigned == 0) begin //FCVT.L.D
117 Bit#(63) all_ones = '1;
118 if(lv_infinity == 1 || lv_invalid == 1)
119 final_result = (lv_sign==1) ?(lv_invalid==1? zeroExtend(all_ones) : signExtend(64'h8000000000000000)) : zeroExtend(all_ones);
120 else if(lv_original_exponent < 'd63) begin
121 final_man = final_man << lv_original_exponent;
122 `ifdef verbose $display("final_man : %b",final_man);`endif
123 Bit#(64) y = zeroExtend(final_man[115:52]);
124 final_result = y;
125 lv_mantissa = final_man[51:0];
126 to_round = True;
127 end
128 else if(lv_original_exponent >= 'd63) begin
129 `ifdef verbose $display("Overflow");`endif
130 //lv_overflow = 1;
131 lv_invalid = 1;
132 if(lv_sign == 0)
133 final_result = zeroExtend(all_ones);
134 else begin
135 if(lv_original_exponent == 'd63 && lv_manzero == 0)
136 lv_invalid = 0;
137 final_result = signExtend(64'h8000000000000000);
138 end
139 end
140 end
141 else begin //FCVT.LU.D
142 Bit#(64) all_ones = '1;
143 if(lv_infinity == 1 || lv_invalid == 1)
144 final_result = (lv_sign==1) ? (lv_invalid==1? signExtend(all_ones) : '0) : signExtend(all_ones);
145 else if(lv_original_exponent < 'd64) begin
146 final_man = final_man << lv_original_exponent;
147 `ifdef verbose $display("final_man = %d",final_man); `endif
148 Bit#(64) y = zeroExtend(final_man[115:52]);
149 final_result = y;
150 lv_mantissa = final_man[51:0];
151 to_round = True;
152 end
153 else if(lv_original_exponent >= 'd64) begin
154 `ifdef verbose $display("Overflow");`endif
155 //lv_overflow = 1;
156 lv_invalid = 1;
157 if(lv_sign == 0)
158 final_result = signExtend(all_ones);
159 else
160 final_result = '0;
161 end
162 end
163
164 end
165
166 bit lv_guard = lv_mantissa[51]; //MSB of the already shifted mantissa is guard bit
167 bit lv_round = lv_mantissa[50]; //next bit is round bit
168 bit lv_sticky = |(lv_mantissa<<2); //remaining bits determine the sticky bit
169 bit lv_round_up = 0;
170 bit lv_inexact1 = lv_guard | lv_round | lv_sticky;
171 if(to_round) begin
172 if(rne) lv_round_up = lv_guard & (final_result[0] | lv_round | lv_sticky); //Round to nearest ties to even
173 else if(rmm) lv_round_up = lv_guard; //& (lv_round | lv_sticky | ~lv_sign); //Round to nearest ties to max magnitude
174 else if(rdn) lv_round_up = lv_inexact1 & (lv_sign); //Round down to -infinity
175 else if(rup) lv_round_up = lv_inexact1 & (~lv_sign); //Round up to +infinity
176 lv_inexact = lv_inexact | lv_inexact1;
177 `ifdef verbose $display("lv_inexact: %b lv_guard: %b lv_round : %b lv_sticky: %b lv_sign %b",lv_inexact,lv_guard,lv_round,lv_sticky,lv_sign); `endif
178 if(lv_round_up == 1) begin
179 lv_invalid = 1;
180 if(convert_long == 0 && convert_unsigned == 0 && lv_original_exponent == 30 && final_result[30:0] == '1 && lv_sign == 0) //Overflow.. Beyond representable number after rounding
181 final_result = 64'h7fffffff;
182 else if(convert_long == 0 && convert_unsigned == 1 && lv_original_exponent == 31 && final_result[31:0] == '1 && lv_sign == 0)
183 final_result = 64'hffffffffffffffff; //Should verify again
184 else if(convert_long == 1 && convert_unsigned == 0 && lv_original_exponent == 62 && final_result[62:0] == '1 && lv_sign == 0) //Overflow.. Beyond representable number after rounding
185 final_result = 64'h7fffffffffffffff;
186 else if(convert_long == 1 && convert_unsigned == 1 && lv_original_exponent == 63 && final_result[63:0] == '1 && lv_sign == 0)
187 final_result = 64'hffffffffffffffff;
188 else begin
189 lv_invalid = 0;
190 final_result = final_result + 1;
191 if(convert_long == 0 && final_result[31]==1)
192 final_result = signExtend(final_result[31:0]);
193 end
194 end
195 `ifdef verbose $display("rounding_mode == %b",rounding_mode); `endif
196 `ifdef verbose $display("round_up = %b", lv_round_up); `endif
197
198 if(convert_unsigned == 0 && lv_sign == 1)begin //Negating the output if floating point number is negative and converted to signed word/long
199 final_result = ~final_result + 1;
200 if(convert_long == 0 && final_result[31]==1)
201 final_result = signExtend(final_result[31:0]);
202 `ifdef verbose $display("Negating output final_result : %b", final_result); `endif
203 end
204 else if(convert_unsigned == 1 && lv_sign == 1) begin //TODO What happens when negative floating point is converted to unsigned int, right now rounded to zero
205 final_result = 0;
206 lv_invalid = 1;
207 end
208 end
209 if((lv_invalid|lv_infinity) == 1) begin //What about Quiet NaN?? What does the Spec Say?
210 lv_overflow = 0;
211 lv_inexact = 0;
212 end
213 Bit#(5) fflags={lv_invalid|lv_infinity,1'b0,lv_overflow,1'b0,lv_inexact};
214 return Floating_output{
215 final_result: final_result,
216 fflags: fflags};
217
218
219 endmethod
220 endmodule
221 module mkTb(Empty);
222
223 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);
224 let s = valueOf(m);
225 let man1 = tpl_1(x);
226 let expo1 = tpl_2(x);
227 let man2 = tpl_1(y);
228 let expo2 = tpl_2(y);
229 let man3 = tpl_1(z);
230 let expo3 = tpl_2(z);
231 Bit#(5) flags1, flags2,flags3;
232 Bool expZ1 = (expo1 == 0);
233 Bool manZ1 = (man1 == 0);
234 Bool expO1 = (expo1 == '1);
235 Bool manO1 = (man1 == '1);
236 Bool topB1 = (man1[s-1] == 1);
237 Bool expZ2 = (expo2 == 0);
238 Bool manZ2 = (man2 == 0);
239 Bool expO2 = (expo2 == '1);
240 Bool manO2 = (man2 == '1);
241 Bool topB2 = (man2[s-1] == 1 && man2 !=0);
242 Bool expZ3 = (expo3 == 0);
243 Bool manZ3 = (man3 == 0);
244 Bool expO3 = (expo3 == '1);
245 Bool manO3 = (man3 == '1);
246 Bool topB3 = (man3[s-1] == 1 && man3 !=0);
247 flags1 = {pack(expZ1 && !manZ1),pack(manZ1 && expZ1),pack(expO1 && topB1),pack(expO1 && manZ1),pack(expO1 && !topB1 && !manZ1)}; //Denormal, isZero, QNaN, Infinity, SNaN
248 flags2 = {pack(expZ2 && !manZ2),pack(manZ2 && expZ2),pack(expO2 && topB2),pack(expO2 && manZ2),pack(expO2 && !topB2 && !manZ2)}; //Denormal, isZero, QNaN, Infinity, SNaN
249 flags3 = {pack(expZ3 && !manZ3),pack(manZ3 && expZ3),pack(expO3 && topB3),pack(expO3 && manZ3),pack(expO3 && !topB3 && !manZ3)}; //Denormal, isZero, QNaN, Infinity, SNaN
250 return tuple3(flags1,flags2,flags3);
251 endfunction
252
253 function Tuple3#(Bit#(m),Bit#(m), Bit#(m)) getMantissa (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
254 provisos(Add#(TAdd#(m,1),e,n),
255 Add#(7,a__,e)
256 );
257 let expo = valueOf(e);
258 let man = valueOf(m);
259 return tuple3(op1[man-1:0],op2[man-1:0],op3[man-1:0]);
260 endfunction
261
262 function Tuple3#(Bit#(e), Bit#(e), Bit#(e)) getExp (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
263 provisos(Add#(TAdd#(m,1),e,n),
264 Add#(7,a__,e)
265 );
266 let inp = valueOf(n);
267 let man = valueOf(m);
268 return tuple3(op1[inp-2:man], op2[inp-2:man], op3[inp-2:man]);
269 endfunction
270
271 function Bool isNaNBox(Bit#(64) op);
272 return (op[63:32]=='1);
273 endfunction
274
275 function Tuple3#(Bit#(32),Bit#(32),Bit#(32)) setCanNaN (Bit#(64) op1, Bit#(64) op2, Bit#(64) op3);
276 return tuple3(isNaNBox(op1)? truncate(op1) : 32'h7fc00000, isNaNBox(op2)? truncate(op2) : 32'h7fc00000, isNaNBox(op3)? truncate(op3) : 32'h7fc00000);
277 endfunction
278 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);
279 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);
280 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(23),Bit#(23),Bit#(23))) getMant32 <- mkUniqueWrapper3(getMantissa);
281 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(8),Bit#(8),Bit#(8))) getExp32 <- mkUniqueWrapper3(getExp);
282 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(52),Bit#(52),Bit#(52))) getMant64 <- mkUniqueWrapper3(getMantissa);
283 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(11),Bit#(11),Bit#(11))) getExp64 <- mkUniqueWrapper3(getExp);
284 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(32),Bit#(32),Bit#(32))) setCanonicalNaN <- mkUniqueWrapper3(setCanNaN);
285
286
287 Ifc_fpu_dp_to_int converter <- mkfpu_dp_to_int();
288 Reg#(Bit#(32)) state_clock <- mkReg(0);
289 Reg#(Bit#(64)) wr_operand1 <- mkReg('h0200000000000000);
290 //Reg#(Bit#(32)) wr_operand1 <- mkReg('hbf214efa);
291 //Reg#(Bit#(32)) wr_operand1 <- mkReg('h91c82527);
292
293 rule state_clock_count;
294 state_clock <= state_clock + 1;
295 if(state_clock == 'd5) $finish;
296 endrule
297
298 rule give_input(state_clock == 'd1);
299 // let {op1,op2,op3} <- setCanonicalNaN.func(wr_operand1,'0,'0);
300 let {man1,man2,man3} <- getMant64.func(wr_operand1, 0,0);
301 let {exp1,exp2,exp3} <- getExp64.func(wr_operand1, 0,0);
302 let {flags1,flags2,flags3} <- condFlags64.func(tuple2(man1,exp1),tuple2(man2,exp2),tuple2(0,0));
303 let sign1 = wr_operand1[63];
304 `ifdef verbose $display("input %b %b %b given at %0d", sign1, exp1, man1, state_clock); `endif
305 let x<- converter._start(sign1,exp1,man1, 0, 0, 3'b000,flags1);
306 `ifdef verbose $display("output %h fflags : %h at %h", x.final_result, x.fflags, state_clock); `endif
307 endrule
308
309
310 endmodule
311 endpackage