Skip to content

Commit e2105fa

Browse files
committed
Fix mkFixedPointSquareRooter and add safe-guard to mkSquareRooter
1 parent 9dfe8f5 commit e2105fa

File tree

1 file changed

+31
-15
lines changed

1 file changed

+31
-15
lines changed

src/Libraries/Base3-Math/SquareRoot.bsv

+31-15
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export mkNonPipelinedSquareRooter;
1717

1818
module mkSquareRooter#(Integer n)(Server#(UInt#(m),Tuple2#(UInt#(m),Bool)))
1919
provisos(
20+
Div#(m, 2, m2),
21+
// m must be even for this implementation to work
22+
Mul#(m2, 2, m),
2023
// per request of bsc
2124
Add#(a__, 2, m),
2225
Log#(TAdd#(1, m), TLog#(TAdd#(m, 1)))
@@ -48,7 +51,7 @@ module mkSquareRooter#(Integer n)(Server#(UInt#(m),Tuple2#(UInt#(m),Bool)))
4851
FIFO#(Tuple4#(Maybe#(Bit#(m)),Bit#(m),Bit#(m),Bit#(m))) fThis = fFirst;
4952
FIFO#(Tuple4#(Maybe#(Bit#(m)),Bit#(m),Bit#(m),Bit#(m))) fNext;
5053

51-
for (Integer i = 0; i < (valueOf(m)/2)/n+1; i = i + 1) begin
54+
for (Integer i = 0; i < valueOf(m2)/n+1; i = i + 1) begin
5255
fNext <- mkLFIFO;
5356
rule work;
5457
//match {.res, .s, .r, .b} <- toGet(fThis).get;
@@ -59,7 +62,7 @@ module mkSquareRooter#(Integer n)(Server#(UInt#(m),Tuple2#(UInt#(m),Bool)))
5962
Bit#(m) b = tpl_4(x);
6063

6164
for (Integer j = 0; j < n; j = j + 1) begin
62-
if ((i + j) <= (valueOf(m)/2)) begin
65+
if ((i + j) <= valueOf(m2)) begin
6366
if (res matches tagged Invalid) begin
6467
if (b == 0) begin
6568
res = tagged Valid r;
@@ -101,6 +104,7 @@ module mkFixedPointSquareRooter#(Integer n)(Server#(FixedPoint#(isize,fsize),Tup
101104
provisos(
102105
Add#(isize,fsize,m),
103106
// per request of bsc
107+
Mul#(TDiv#(m, 2), 2, m),
104108
Add#(a__, 2, m),
105109
Add#(b__, TLog#(TAdd#(1, m)), TAdd#(TLog#(m), 1)),
106110
Log#(TAdd#(1, m), TLog#(TAdd#(m, 1))),
@@ -120,17 +124,24 @@ module mkFixedPointSquareRooter#(Integer n)(Server#(FixedPoint#(isize,fsize),Tup
120124
let zeros = countZerosMSB(pack(value));
121125
Int#(TAdd#(TLog#(m),1)) shift;
122126

127+
// if (fsize + zeros) is not even, round zeros down
128+
if (valueOf(fsize) % 2 == 0)
129+
zeros = zeros & (~1);
130+
else
131+
zeros = (zeros & 1) == 0 ? zeros - 1 : zeros;
132+
123133
// align input
124-
value = value << (zeros - 1);
134+
value = value << zeros;
125135

126-
// compute shift for output
127-
shift = (fromInteger(valueOf(isize)) - cExtend(zeros)) >> 1;
128-
shift = shift + 1;
129-
if ((shift & 1) == 0) begin
130-
value = value >> 1;
131-
end
136+
// A conversion to UInt behaves like the value was multiplied by 2**fsize.
137+
// Then, the value is shifted by zeros, which multiplies it by 2**zeros.
138+
// Therefore, after computing the square root of the resulting value,
139+
// it must be divided by sqrt(2**(fsize + zeros)) = 2**((fsize + zeros) / 2)
140+
shift = extend(unpack(pack( (zeros + fromInteger(valueOf(fsize))) >> 1 )));
132141

133-
shift = fromInteger(valueOf(isize)) - shift;
142+
// Converting the value back from UInt to FixedPoint will already divide it
143+
// by 2**fsize, therefore this is excluded from the shift
144+
shift = shift - fromInteger(valueOf(fsize));
134145

135146
sqrt.request.put(value);
136147
fShift.enq(shift);
@@ -141,11 +152,14 @@ module mkFixedPointSquareRooter#(Integer n)(Server#(FixedPoint#(isize,fsize),Tup
141152
let shift <- toGet(fShift).get;
142153

143154
// shift result as necessary
144-
result = result >> shift;
155+
if (shift >= 0)
156+
result = result >> shift;
157+
else // invert direction if shift is negative
158+
result = result << (-shift);
145159

146160
FixedPoint#(isize,fsize) fx;
147-
fx.i = cExtendLSB(result);
148-
fx.f = cExtend(result);
161+
fx.i = truncateLSB(pack(result));
162+
fx.f = truncate(pack(result));
149163

150164
fResponse.enq(tuple2(fx,inexact));
151165
endrule
@@ -287,6 +301,8 @@ module mkTb(Empty);
287301
testSqrtPipe('hffff0000_00000000);
288302
testSqrtPipe('hfffe0000);
289303

304+
testSqrtPipe(536870912.9375);
305+
testSqrtPipe(1073741824.96875);
290306
testSqrtPipe(0.5);
291307
testSqrtPipe(0.25);
292308

@@ -307,10 +323,10 @@ module mkTb(Empty);
307323
end
308324

309325
if (rfx != rrfx) begin
310-
$display("sqrtfx(", fshow(nfx), ") = ", fshow(rfx), " (expected ", fshow(rrfx) ,")");
326+
$display("sqrtfx(", fshow(nfx), ") = ", fshow(rrfx), " (expected ", fshow(rfx) ,")");
311327
end
312328
else begin
313-
$display("sqrtfx(", fshow(nfx), ") = ", fshow(rfx));
329+
$display("sqrtfx(", fshow(nfx), ") = ", fshow(rrfx));
314330
end
315331
endrule
316332

0 commit comments

Comments
 (0)