e8920833ce2d60327500d565a2b57d8032e201ff
1 """IEEE754 Floating Point Divider
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 Copyright (C) 2019 Jacob Lifshay
6 Relevant bugreport: http://bugs.libre-riscv.org/show_bug.cgi?id=99
9 from nmigen
import Module
, Signal
, Cat
, Elaboratable
, Const
, Mux
10 from nmigen
.cli
import main
, verilog
12 from ieee754
.fpcommon
.fpbase
import FPNumBaseRecord
13 from ieee754
.fpcommon
.fpbase
import FPState
14 from ieee754
.fpcommon
.denorm
import FPSCData
15 from ieee754
.fpcommon
.getop
import FPPipeContext
16 from ieee754
.div_rem_sqrt_rsqrt
.div_pipe
import DivPipeInputData
17 from ieee754
.div_rem_sqrt_rsqrt
.core
import DivPipeCoreOperation
as DPCOp
20 class FPDivStage0Mod(Elaboratable
):
21 """ DIV/SQRT/RSQRT "preparation" module.
23 adjusts mantissa and exponent (sqrt/rsqrt exponent must be even),
24 puts exponent (and sign) into data structures for passing through to
25 the end, and puts the (adjusted) mantissa into the processing engine.
27 no *actual* processing occurs here: it is *purely* preparation work.
30 def __init__(self
, pspec
):
36 return FPSCData(self
.pspec
, False)
39 return DivPipeInputData(self
.pspec
)
44 def setup(self
, m
, i
):
45 """ links module to inputs and outputs
47 m
.submodules
.div0
= self
48 m
.d
.comb
+= self
.i
.eq(i
)
50 def elaborate(self
, platform
):
54 # mantissas start in the range [1.0, 2.0)
56 # intermediary temp signals
57 is_div
= Signal(reset_less
=True)
58 need_exp_adj
= Signal(reset_less
=True)
60 # "adjusted" - ``self.i.a.rmw`` fractional bits and 2 integer bits
61 adj_a_mw
= self
.i
.a
.rmw
62 adj_a_m
= Signal(self
.i
.a
.rmw
+ 2, reset_less
=True)
63 adj_a_e
= Signal((len(self
.i
.a
.e
), True), reset_less
=True)
65 # adjust (shift) the exponent so that it is even, but only for [r]sqrt
66 comb
+= [is_div
.eq(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)),
67 need_exp_adj
.eq(~is_div
& self
.i
.a
.e
[0]), # even? !div? adjust
68 adj_a_m
.eq(self
.i
.a
.m
<< need_exp_adj
),
69 adj_a_e
.eq(self
.i
.a
.e
- need_exp_adj
)]
71 # adj_a_m now in the range [1.0, 4.0) for sqrt/rsqrt
72 # and [1.0, 2.0) for div
74 fw
= self
.pspec
.core_config
.fract_width
75 divr_rad
= Signal(len(self
.o
.divisor_radicand
), reset_less
=True)
77 # real mantissa fractional widths
81 comb
+= [self
.o
.dividend
.eq(self
.i
.a
.m
<< (fw
*2 - a_mw
)),
82 divr_rad
.eq(Mux(is_div
, self
.i
.b
.m
<< (fw
- b_mw
),
83 adj_a_m
<< (fw
- adj_a_mw
))),
84 self
.o
.divisor_radicand
.eq(divr_rad
),
87 # set default since it's not always set; non-zero value for debugging
88 comb
+= self
.o
.operation
.eq(1)
90 with m
.If(~self
.i
.out_do_z
):
92 with m
.If(self
.i
.ctx
.op
== int(DPCOp
.UDivRem
)):
93 comb
+= [self
.o
.z
.e
.eq(self
.i
.a
.e
- self
.i
.b
.e
),
94 self
.o
.z
.s
.eq(self
.i
.a
.s ^ self
.i
.b
.s
),
95 self
.o
.operation
.eq(int(DPCOp
.UDivRem
))
99 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.SqrtRem
)):
100 comb
+= [self
.o
.z
.e
.eq(adj_a_e
>> 1),
101 self
.o
.z
.s
.eq(self
.i
.a
.s
),
102 self
.o
.operation
.eq(int(DPCOp
.SqrtRem
))
106 with m
.Elif(self
.i
.ctx
.op
== int(DPCOp
.RSqrtRem
)):
107 comb
+= [self
.o
.z
.e
.eq(-(adj_a_e
>> 1)),
108 self
.o
.z
.s
.eq(self
.i
.a
.s
),
109 self
.o
.operation
.eq(int(DPCOp
.RSqrtRem
))
112 # these are required and must not be touched
113 comb
+= self
.o
.oz
.eq(self
.i
.oz
)
114 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
115 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
120 class FPDivStage0(FPState
):
121 """ First stage of div.
124 def __init__(self
, pspec
):
125 FPState
.__init
__(self
, "divider_0")
126 self
.mod
= FPDivStage0Mod(pspec
)
127 self
.o
= self
.mod
.ospec()
129 def setup(self
, m
, i
):
130 """ links module to inputs and outputs
134 # NOTE: these could be done as combinatorial (merge div0+div1)
135 m
.d
.sync
+= self
.o
.eq(self
.mod
.o
)