From: Luke Kenneth Casson Leighton Date: Sun, 9 Feb 2020 18:11:57 +0000 (+0000) Subject: add MoveMSBDown class to be used in carry-out X-Git-Tag: ls180-24jan2020~219 X-Git-Url: https://git.libre-soc.org/?p=ieee754fpu.git;a=commitdiff_plain;h=6d1ec116f84926a48ffc232f125717bd110d5f0e add MoveMSBDown class to be used in carry-out --- 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]) +