From 6d1ec116f84926a48ffc232f125717bd110d5f0e Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 9 Feb 2020 18:11:57 +0000 Subject: [PATCH] add MoveMSBDown class to be used in carry-out --- src/ieee754/part_cmp/ripple.py | 60 ++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/src/ieee754/part_cmp/ripple.py b/src/ieee754/part_cmp/ripple.py index a300fb03..ed156d74 100644 --- a/src/ieee754/part_cmp/ripple.py +++ b/src/ieee754/part_cmp/ripple.py @@ -6,15 +6,20 @@ # this is actually a useful function, it's one of "set before first" or # "set after first" from vector predication processing. -from nmigen import Signal, Module, Elaboratable, Mux +from nmigen import Signal, Module, Elaboratable, Mux, Cat +from nmigen.cli import main class RippleLSB(Elaboratable): + """RippleLSB + + based on a partition mask, the LSB is "rippled" (duplicated) + up to the beginning of the next partition. + """ def __init__(self, width): self.width = width self.results_in = Signal(width, reset_less=True) self.gates = Signal(width-1, reset_less=True) - self.output = Signal(width, reset_less=True) def elaborate(self, platform): @@ -26,9 +31,52 @@ class RippleLSB(Elaboratable): comb += self.output[0].eq(current_result) for i in range(width-1): - cur = Signal(name="cur%d" % i) - comb += cur.eq(current_result) - current_result = Mux(self.gates[i], self.results_in[i+1], cur) - comb += self.output[i+1].eq(current_result) + cur = Mux(self.gates[i], self.results_in[i+1], self.output[i]) + comb += self.output[i+1].eq(cur) return m + + +class MoveMSBDown(Elaboratable): + """MoveMSBDown + + based on a partition mask, moves the MSB down to the LSB position. + only the MSB is relevant, other bits are ignored. works by first + rippling the MSB across the entire partition (TODO: split that out + into its own useful module), then ANDs the (new) LSB with the + partition mask to isolate it. + """ + def __init__(self, width): + self.width = width + self.results_in = Signal(width, reset_less=True) + self.gates = Signal(width-1, reset_less=True) + self.output = Signal(width, reset_less=True) + + def elaborate(self, platform): + m = Module() + comb = m.d.comb + width = self.width + intermed = Signal(width, reset_less=True) + + + # first propagate MSB down until the nearest partition gate + comb += intermed[-1].eq(self.results_in[-1]) # start at MSB + for i in range(width-2, -1, -1): + cur = Mux(self.gates[i], self.results_in[i], intermed[i+1]) + comb += intermed[i].eq(cur) + + # now only select those bits where the mask starts + out = [intermed[0]] # LSB of first part always set + for i in range(width-1): # length of partition gates + out.append(self.gates[i] & intermed[i+1]) + comb += self.output.eq(Cat(*out)) + + return m + + +if __name__ == "__main__": + # python3 ieee754/part_cmp/ripple.py generate -t il > ripple.il + # then check with yosys "read_ilang ripple.il; show top" + alu = MoveMSBDown(width=4) + main(alu, ports=[alu.results_in, alu.gates, alu.output]) + -- 2.30.2