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