1 """IEEE Floating Point Divider
3 Copyright (C) 2019 Luke Kenneth Casson Leighton <lkcl@lkcl.net>
4 Copyright (C) 2019 Jacob Lifshay
7 * http://bugs.libre-riscv.org/show_bug.cgi?id=99
8 * http://bugs.libre-riscv.org/show_bug.cgi?id=43
9 * http://bugs.libre-riscv.org/show_bug.cgi?id=44
12 from nmigen
import Module
, Signal
, Elaboratable
, Cat
13 from nmigen
.cli
import main
, verilog
15 from ieee754
.fpcommon
.fpbase
import FPState
16 from ieee754
.fpcommon
.postcalc
import FPAddStage1Data
17 from ieee754
.div_rem_sqrt_rsqrt
.div_pipe
import DivPipeOutputData
20 class FPDivStage2Mod(FPState
, Elaboratable
):
21 """ Last stage of div: preparation for normalisation.
23 NOTE: this phase does NOT do ACTUAL DIV processing, it ONLY
24 does "conversion" *out* of the Q/REM last stage
27 def __init__(self
, pspec
):
33 return DivPipeOutputData(self
.pspec
) # Q/Rem in...
36 # XXX REQUIRED. MUST NOT BE CHANGED. this is the format
37 # required for ongoing processing (normalisation, correction etc.)
38 return FPAddStage1Data(self
.pspec
) # out to post-process
43 def setup(self
, m
, i
):
44 """ links module to inputs and outputs
46 m
.submodules
.div1
= self
47 m
.d
.comb
+= self
.i
.eq(i
)
49 def elaborate(self
, platform
):
53 # copies sign and exponent and mantissa (mantissa and exponent to be
55 comb
+= self
.o
.z
.eq(self
.i
.z
)
57 # Operations and input/output mantissa ranges:
71 with m
.If(~self
.i
.out_do_z
):
72 # following section partially normalizes result to range [1.0, 2.0)
73 fw
= self
.pspec
.core_config
.fract_width
74 qr_int_part
= Signal(2, reset_less
=True)
75 comb
+= qr_int_part
.eq(self
.i
.quotient_root
[fw
:][:2])
77 need_shift
= Signal(reset_less
=True)
79 # shift left when result is less than 2.0 since result_m has 1 more
80 # fraction bit, making assigning to it the equivalent of
82 # this all comes out to:
83 # if quotient_root < 2.0:
84 # # div by 2 from assign; mul by 2 from shift left
85 # result = (quotient_root * 2) / 2
87 # # div by 2 from assign
88 # result = quotient_root / 2
89 comb
+= need_shift
.eq(qr_int_part
< 2)
91 # one extra fraction bit to accommodate the result when not
92 # shifting and for effective div by 2
93 result_m_fract_width
= fw
+ 1
94 # 1 integer bit since the numbers are less than 2.0
95 result_m
= Signal(1 + result_m_fract_width
, reset_less
=True)
96 result_e
= Signal(len(self
.i
.z
.e
), reset_less
=True)
99 result_m
.eq(self
.i
.quotient_root
<< need_shift
),
100 result_e
.eq(self
.i
.z
.e
+ (1 - need_shift
))
103 # result_m is now in the range [1.0, 2.0)
105 self
.o
.z
.m
.eq(result_m
[3:]), # mantissa
106 self
.o
.of
.m0
.eq(result_m
[3]), # copy of mantissa LSB
107 self
.o
.of
.guard
.eq(result_m
[2]), # guard
108 self
.o
.of
.round_bit
.eq(result_m
[1]), # round
109 self
.o
.of
.sticky
.eq(result_m
[0] | self
.i
.remainder
.bool()),
110 self
.o
.z
.e
.eq(result_e
),
113 comb
+= self
.o
.out_do_z
.eq(self
.i
.out_do_z
)
114 comb
+= self
.o
.oz
.eq(self
.i
.oz
)
115 comb
+= self
.o
.ctx
.eq(self
.i
.ctx
)
120 class FPDivStage2(FPState
):
122 def __init__(self
, pspec
):
123 FPState
.__init
__(self
, "divider_1")
124 self
.mod
= FPDivStage2Mod(pspec
)
125 self
.out_z
= FPNumBaseRecord(pspec
, False)
126 self
.out_of
= Overflow()
127 self
.norm_stb
= Signal()
129 def setup(self
, m
, i
):
130 """ links module to inputs and outputs
134 m
.d
.sync
+= self
.norm_stb
.eq(0) # sets to zero when not in div1 state
136 m
.d
.sync
+= self
.out_of
.eq(self
.mod
.out_of
)
137 m
.d
.sync
+= self
.out_z
.eq(self
.mod
.out_z
)
138 m
.d
.sync
+= self
.norm_stb
.eq(1)
141 m
.next
= "normalise_1"