[libre-riscv-dev] div/mod algorithm written in python
Luke Kenneth Casson Leighton
lkcl at lkcl.net
Sun Jul 7 12:59:35 BST 2019
workaround.
the graphviz for "|"ing bits together is absolutely dreadful, plus the
RTL that would be generated is a massive chain of OR gates.
this is what "bool" is for (which is a yosys operator, that can be
optimised by the HW generator into a tree-structure-of-OR-gates).
i use a list and Cat(*list) to accumulate and compress the Signals,
and it results in really clean-looking graphviz.
the assignment of "test" to what is in the Mux was what "fixed" the
"problem". examining the IL file, the input was 2 bits wide, somehow.
Mux must only have a 1-bit-wide signal, which is probably what the
problem was.
managed to get a yosys file and examined the graphviz: it looks really
clean. the only thing is: by not using "reset_less=True" in the
signals, "rst" has been jammed into pretty much just about ******
everything.
the operation, setup and final graphviz look really clean. operation
has some weird magic constants that seem to be repeated a lot: this is
probably down to an assignment to a python variable somewhere, that
then gets "innocently used" in a loop. (1<<0b111) or
Const(1)<<Const(7) is probably the cause, where it would be better
just using a python number that gets *converted* to a Const (after the
calculation). otherwise, nmigen thinks it should actually generate
RTL to *generate* (in hardware) that Constant.
yep, here we go:
shifted_trial_bits = Const(trial_bits, log2_radix) << current_shift
if that's replaced with:
shifted_trial_bits = Const(trial_bits<<current_shift,
log2_radix+current_shift)
an awful lot of those dreadful constants will disappear. just tried
that... you'll need to take a look, and in particular examine the
graphviz because some of the magic constants are zero (probably the
Const is not long enough: a shift is making the top bit disappear).
root_times_radicand, quotient_root, divisor_radicant, they're all
multiplied by zero which is probably not what's wanted, at all.
l.
diff --git a/berkeley-softfloat-3 b/berkeley-softfloat-3
--- a/berkeley-softfloat-3
+++ b/berkeley-softfloat-3
@@ -1 +1 @@
-Subproject commit b64af41c3276f97f0e181920400ee056b9c88037
+Subproject commit b64af41c3276f97f0e181920400ee056b9c88037-dirty
diff --git a/src/ieee754/div_rem_sqrt_rsqrt/core.py
b/src/ieee754/div_rem_sqrt_rsqrt/core.py
index 63c1721..ffcd7ce 100644
--- a/src/ieee754/div_rem_sqrt_rsqrt/core.py
+++ b/src/ieee754/div_rem_sqrt_rsqrt/core.py
@@ -18,7 +18,7 @@ Formulas solved are:
The remainder is the left-hand-side of the comparison minus the
right-hand-side of the comparison in the above formulas.
"""
-from nmigen import (Elaboratable, Module, Signal, Const, Mux)
+from nmigen import (Elaboratable, Module, Signal, Const, Mux, Cat)
import enum
@@ -351,14 +351,20 @@ class DivPipeCoreCalculateStage(Elaboratable):
bit_value ^= pass_flags[j]
m.d.comb += next_bits.part(i, 1).eq(bit_value)
- next_compare_rhs = 0
+ next_compare_rhs = Signal(radix, reset_less=True)
+ l = []
for i in range(radix):
next_flag = pass_flags[i + 1] if i + 1 < radix else 0
- next_compare_rhs |= Mux(pass_flags[i] & ~next_flag,
+ flag = Signal(reset_less=True)
+ test = Signal(reset_less=True)
+ m.d.comb += test.eq((pass_flags[i] & ~next_flag))
+ m.d.comb += flag.eq(Mux(test,
trial_compare_rhs_values[i],
- 0)
+ 0))
+ l.append(flag)
- m.d.comb += self.o.compare_rhs.eq(next_compare_rhs)
+ m.d.comb += next_compare_rhs.eq(Cat(*l))
+ m.d.comb += self.o.compare_rhs.eq(next_compare_rhs.bool())
m.d.comb += self.o.root_times_radicand.eq(self.i.root_times_radicand
+ ((self.i.divisor_radicand
* next_bits)
On Sun, Jul 7, 2019 at 12:25 PM Jacob Lifshay <programmerjake at gmail.com> wrote:
>
> On Sun, Jul 7, 2019, 04:23 Luke Kenneth Casson Leighton <lkcl at lkcl.net>
> wrote:
>
> > On Sun, Jul 7, 2019 at 11:24 AM Jacob Lifshay <programmerjake at gmail.com>
> > wrote:
> > >
> > > I refactored core.py into core.py and div_pipe.py.
> > > I also added tests that demonstrate integer and fractional division:
> > > test_algorithm.py:test_int_div/test_fract_div
> > >
> > > I added most of the test code for DivPipeCore, but there's a bug
> > > somewhere (probably in core.py) that makes nmigen generate invalid
> > > rtlil (yosys complains when trying to load it).
> >
> > fascinating
> >
> > yosys> read_ilang div_pipe_core_bit_width_8_fract_width_4_radix_2.il
> > 1. Executing ILANG frontend.
> > Input filename: div_pipe_core_bit_width_8_fract_width_4_radix_2.il
> > ERROR: Found error in internal cell \div_pipe_core_calculate_7.$132
> > ($mux) at kernel/rtlil.cc:717:
> > attribute \src "/home/lkcl/src/riscv/nmigen/nmigen/hdl/ir.py:42"
> > cell $mux $132
> > parameter \WIDTH 24
> > connect \Y $129
> > connect \S $130
> > connect \B \trial_compare_rhs_1
> > connect \A 24'000000000000000000000000
> > end
> >
> > definitely one to raise on the yosys bugtracker.
> >
> I don't think it's a bug in yosys, since the simulator also crashes.
>
> >
> > _______________________________________________
> > libre-riscv-dev mailing list
> > libre-riscv-dev at lists.libre-riscv.org
> > http://lists.libre-riscv.org/mailman/listinfo/libre-riscv-dev
> >
> _______________________________________________
> libre-riscv-dev mailing list
> libre-riscv-dev at lists.libre-riscv.org
> http://lists.libre-riscv.org/mailman/listinfo/libre-riscv-dev
More information about the libre-riscv-dev
mailing list