add core
[shakti-core.git] / src / core / fpu / fpu_convert_sp_dp.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_convert_sp_dp;
11 import defined_types::*;
12 import UniqueWrappers::*;
13 `include "defined_parameters.bsv"
14 interface Ifc_fpu_convert_sp_dp;
15 method ActionValue#(Floating_output#(64))_start(Bit#(1) sign, Bit#(8) exponent, Bit#(23) mantissa, Bit#(3) rounding_mode, Bit#(5) flags);
16 endinterface
17
18 interface Ifc_fpu_convert_dp_sp;
19 method ActionValue#(Floating_output#(32)) _start(Bit#(1) sign, Bit#(11) exponent, Bit#(52) mantissa, Bit#(3) rounding_mode, Bit#(5) flags);
20 endinterface
21
22 function Bit#(m) zeroExtendLSB(Bit#(n) value)
23 provisos(Add#(a__, n, m));
24
25 Bit#(m) resp = 0;
26 resp[valueOf(m)-1:valueOf(m)-valueOf(n)] = value;
27 return resp;
28 endfunction
29
30 function Bit#(m) truncateLSB(Bit#(n) value);
31 return value[valueOf(n)-1:valueOf(n)-valueOf(m)];
32 endfunction
33
34 function Bit#(69) floatDouble(Bit#(1) sign, Bit#(8) exponent, Bit#(23) mantissa, Bit#(3) rounding_mode, Bit#(5) flags);
35 Bit#(5) exception = 0;
36 if (flags[3]==1)
37 return {5'b0,sign,63'b0};
38 else if (flags[2] == 1 || flags[0] == 1) begin
39 exception[4] = flags[0];
40 return {exception,1'b0,11'd-1,1'b1,51'b0};
41 end
42 else if (flags[1] == 1)
43 return {exception,sign,11'd-1,52'd0};
44 else begin
45 if(flags[4]==0) begin //Normal numbers
46 Bit#(11) expo = zeroExtend(exponent) + 'd896;
47 Bit#(52) mant = zeroExtendLSB(mantissa);
48 return {exception,sign,expo,mant};
49 end
50 else begin //Denormal numbers
51 let lv_zeros = countZerosMSB(mantissa);
52 Bit#(11) expo = 'd896 - zeroExtend(pack(lv_zeros)); //What if lv_zeros is so much?
53 Bit#(52) man = zeroExtendLSB(mantissa << lv_zeros);
54 man = man<<1; //To throw off implicit bit
55 return {exception,sign, expo, man};
56 end
57 end
58 endfunction
59
60 function ActionValue#(Bit#(37)) doubleFloat(Bit#(1) sign, Bit#(11) exponent, Bit#(52) mantissa, Bit#(3) rounding_mode, Bit#(5) flags)
61 =actionvalue
62 Bit#(5) exception = 0;
63 bit denormal = 0;
64 `ifdef verbose $display("sign : %b exponent : %b mantissa : %b flags : %b",sign,exponent,mantissa, flags); `endif
65 if (flags[3]==1) begin
66 return {5'b0,sign,31'b0};
67 end
68 else if (flags[2] == 1 || flags[0] == 1) begin
69 exception[4] = flags[0];
70 return {exception,1'b0,8'd-1,1'b1,22'b0};
71 end
72 else if (flags[1] == 1)
73 return {exception,sign,8'd-1,23'd0};
74 else if (exponent > 'd1150) begin
75 exception[2] = 1;
76 exception[0] = 1;
77 `ifdef verbose $display("overflow"); `endif
78 if(rounding_mode == 3'b001) //Round to zero
79 return {exception,sign,7'd-1,1'b0,23'd-1}; //Highest positive number 7f7fffff
80 else if (rounding_mode == 3'b010) //Round down
81 if(sign == 0)
82 return {exception,1'b0,7'd-1,1'b0,23'd-1};
83 else
84 return {exception,1'b1,8'd-1,23'd0};
85 else if (rounding_mode == 3'b011 && sign == 1)
86 return {exception,1'b1,7'd-1,1'b0,23'd-1};
87 else
88 return {exception,sign,8'd-1,23'd0};
89 end
90 else begin
91 `ifdef verbose $display("sign : %b exponent %b mantissa %b rounding %b flags %b",sign,exponent,mantissa,rounding_mode,flags); `endif
92 Bit#(32) res = 0;
93 Bit#(49) man = 0;
94 Bit#(8) expo = 0;
95 bit underflow = 0;
96 bit lv_guard = 0;
97 bit lv_denormal_roundup = 0;
98 let lv_sticky = |mantissa[26:0];
99 `ifdef verbose $display("exponent : %d",exponent); `endif
100 if (exponent <= 'd872) begin //1023-127-24 Underflow
101 if(rounding_mode == 3'b010 && sign == 1) //Round Down
102 res = {1'b1,30'b0,1'b1};
103 else if(rounding_mode == 3'b011 && sign == 0)
104 res = 1;
105 else
106 res = {sign,'0};
107 underflow = 1;
108 exception[1] = 1;
109 exception[0] = 1;
110 end
111 else if (exponent <= 'd896) begin //Denormal number //Set sticky bit!!!
112 `ifdef verbose $display("Denormal lv_sticky : %b", lv_sticky); `endif
113 let shiftDist = 'd896 - exponent;
114 man = {1'b1,mantissa[51:27],23'd0} >> shiftDist;
115 if(man[23:0] != 0)
116 lv_sticky = 1;
117 `ifdef verbose $display("lv_guard : %b shiftDist : %d",lv_guard, shiftDist); `endif
118 expo = '0;
119 denormal = 1;
120 end
121 else begin //Normal number
122 expo = truncate(exponent - 'd896);
123 man = zeroExtendLSB(mantissa[51:27]);
124 `ifdef verbose $display("expo : %b man : %b",expo,man); `endif
125 end
126 lv_guard = man[25];
127 let lv_round = man[24];
128 let lv_inexact = 0;
129 let lv_round_up = 0;
130 if(((lv_guard | lv_round | lv_sticky)) == 1)
131 lv_inexact = 1;
132 if(denormal == 1 && lv_inexact == 1) begin
133 exception[1] = 1;
134 exception[0] = 1;
135 end
136 exception[0] = exception[0] | lv_inexact;
137 if(flags[2]==0 && flags[0] == 0 && flags[1]==0 && flags[3] == 0) begin
138 if(rounding_mode == 'b000)
139 lv_round_up = lv_guard & (lv_round|lv_sticky|mantissa[29]);
140 else if(rounding_mode == 'b100)
141 lv_round_up = lv_guard; //& (lv_round|lv_sticky|sign);
142 else if(rounding_mode == 'b011)
143 lv_round_up = (lv_guard|lv_round|lv_sticky) & ~sign;
144 else if(rounding_mode == 'b010)
145 lv_round_up = (lv_guard|lv_round|lv_sticky) & sign;
146 `ifdef verbose $display("lv_roundup : %b",lv_round_up); `endif
147 Bit#(24) fman = zeroExtend(man[48:26]);
148 `ifdef verbose $display("fman: %b",fman); `endif
149 if(lv_round_up == 1)
150 fman = fman + 1;
151 if(fman[23] == 1)
152 expo = expo + 1;
153 if(underflow==0)
154 res = {sign,expo,fman[22:0]};
155 end
156 return {exception,res};
157 end
158 endactionvalue;
159
160 `ifdef fpu_hierarchical
161 (*synthesize*)
162 `endif
163 module mkfpu_convert_sp_dp(Ifc_fpu_convert_sp_dp);
164 method ActionValue#(Floating_output#(64))_start(Bit#(1) sign, Bit#(8) exponent, Bit#(23) mantissa, Bit#(3) rounding_mode, Bit#(5) flags);
165 `ifdef verbose $display("sign : %b exponent %b mantissa %b rounding_mode %b flags %b",sign,exponent,mantissa,rounding_mode,flags); `endif
166 let x = floatDouble(sign,exponent,mantissa,rounding_mode,flags);
167 return Floating_output{
168 final_result : x[63:0],
169 fflags : x[68:64]
170 };
171 endmethod
172 endmodule
173
174 `ifdef fpu_hierarchical
175 (*synthesize*)
176 `endif
177 module mkfpu_convert_dp_sp(Ifc_fpu_convert_dp_sp);
178 method ActionValue#(Floating_output#(32)) _start(Bit#(1) sign, Bit#(11) exponent, Bit#(52) mantissa, Bit#(3) rounding_mode, Bit#(5) flags);
179 `ifdef verbose $display("sign : %b exponent %b mantissa %b rounding_mode %b flags %b",sign,exponent,mantissa,rounding_mode,flags); `endif
180 let x<- doubleFloat(sign,exponent,mantissa,rounding_mode,flags);
181 return Floating_output{
182 final_result : x[31:0],
183 fflags : x[36:32] //raise flags
184 };
185 endmethod
186 endmodule
187
188 module mkTb(Empty);
189
190 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);
191 let s = valueOf(m);
192 let man1 = tpl_1(x);
193 let expo1 = tpl_2(x);
194 let man2 = tpl_1(y);
195 let expo2 = tpl_2(y);
196 let man3 = tpl_1(z);
197 let expo3 = tpl_2(z);
198 Bit#(5) flags1, flags2,flags3;
199 Bool expZ1 = (expo1 == 0);
200 Bool manZ1 = (man1 == 0);
201 Bool expO1 = (expo1 == '1);
202 Bool manO1 = (man1 == '1);
203 Bool topB1 = (man1[s-1] == 1);
204 Bool expZ2 = (expo2 == 0);
205 Bool manZ2 = (man2 == 0);
206 Bool expO2 = (expo2 == '1);
207 Bool manO2 = (man2 == '1);
208 Bool topB2 = (man2[s-1] == 1 && man2 !=0);
209 Bool expZ3 = (expo3 == 0);
210 Bool manZ3 = (man3 == 0);
211 Bool expO3 = (expo3 == '1);
212 Bool manO3 = (man3 == '1);
213 Bool topB3 = (man3[s-1] == 1 && man3 !=0);
214 flags1 = {pack(expZ1 && !manZ1),pack(manZ1 && expZ1),pack(expO1 && topB1),pack(expO1 && manZ1),pack(expO1 && !topB1 && !manZ1)}; //Denormal, isZero, QNaN, Infinity, SNaN
215 flags2 = {pack(expZ2 && !manZ2),pack(manZ2 && expZ2),pack(expO2 && topB2),pack(expO2 && manZ2),pack(expO2 && !topB2 && !manZ2)}; //Denormal, isZero, QNaN, Infinity, SNaN
216 flags3 = {pack(expZ3 && !manZ3),pack(manZ3 && expZ3),pack(expO3 && topB3),pack(expO3 && manZ3),pack(expO3 && !topB3 && !manZ3)}; //Denormal, isZero, QNaN, Infinity, SNaN
217 return tuple3(flags1,flags2,flags3);
218 endfunction
219
220 function Tuple3#(Bit#(m),Bit#(m), Bit#(m)) getMantissa (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
221 provisos(Add#(TAdd#(m,1),e,n),
222 Add#(7,a__,e)
223 );
224 let expo = valueOf(e);
225 let man = valueOf(m);
226 return tuple3(op1[man-1:0],op2[man-1:0],op3[man-1:0]);
227 endfunction
228
229 function Tuple3#(Bit#(e), Bit#(e), Bit#(e)) getExp (Bit#(n) op1, Bit#(n) op2, Bit#(n) op3)
230 provisos(Add#(TAdd#(m,1),e,n),
231 Add#(7,a__,e)
232 );
233 let inp = valueOf(n);
234 let man = valueOf(m);
235 return tuple3(op1[inp-2:man], op2[inp-2:man], op3[inp-2:man]);
236 endfunction
237
238 function Bool isNaNBox(Bit#(64) op);
239 return (op[63:32]=='1);
240 endfunction
241
242 function Tuple3#(Bit#(32),Bit#(32),Bit#(32)) setCanNaN (Bit#(64) op1, Bit#(64) op2, Bit#(64) op3);
243 return tuple3(isNaNBox(op1)? truncate(op1) : 32'h7fc00000, isNaNBox(op2)? truncate(op2) : 32'h7fc00000, isNaNBox(op3)? truncate(op3) : 32'h7fc00000);
244 endfunction
245 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);
246 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);
247 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(23),Bit#(23),Bit#(23))) getMant32 <- mkUniqueWrapper3(getMantissa);
248 Wrapper3#(Bit#(32),Bit#(32),Bit#(32),Tuple3#(Bit#(8),Bit#(8),Bit#(8))) getExp32 <- mkUniqueWrapper3(getExp);
249 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(52),Bit#(52),Bit#(52))) getMant64 <- mkUniqueWrapper3(getMantissa);
250 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(11),Bit#(11),Bit#(11))) getExp64 <- mkUniqueWrapper3(getExp);
251 Wrapper3#(Bit#(64),Bit#(64),Bit#(64),Tuple3#(Bit#(32),Bit#(32),Bit#(32))) setCanonicalNaN <- mkUniqueWrapper3(setCanNaN);
252
253
254 Reg#(Bit#(32)) rg_clock <-mkReg(0);
255 //Reg#(Bit#(64)) wr_operand1 <- mkReg(64'h3721795900000000);
256 //Reg#(Bit#(64)) wr_operand1 <- mkReg(64'h372741b800000000);
257 Reg#(Bit#(64)) wr_operand1 <- mkReg(64'hffffffff7f814000);
258 //Reg#(Bit#(64)) rg__operand1ut1 <- mkReg(64'h019000000000000);
259
260 Ifc_fpu_convert_dp_sp cvt <- mkfpu_convert_dp_sp;
261
262 rule rl_clock;
263 rg_clock<=rg_clock+1;
264 if(rg_clock=='d60) begin
265 $finish(0);
266 end
267 endrule
268
269 rule give__operand1ut(rg_clock==2);
270 let {man1,man2,man3} <- getMant64.func(wr_operand1, 0,0);
271 let {exp1,exp2,exp3} <- getExp64.func(wr_operand1, 0,0);
272 let {x1,x2,x3} <- condFlags64.func(tuple2(man1,exp1),tuple2(0,0),tuple2(0,0));
273 `ifdef verbose $display("sign: %b exponent : %b mantissa : %b",wr_operand1[63],exp1,man1); `endif
274 `ifdef verbose $display("exponent: %d",exp1); `endif
275 let x <- cvt._start(wr_operand1[63],exp1,man1,3'b011,x1);
276 `ifdef verbose $display("Output= %h fflags %h" , x.final_result,x.fflags,$time); `endif
277 endrule
278
279
280 endmodule
281
282 endpackage