From 9d2cacebdf7ccaef9307903e9cba9780d766cf5f Mon Sep 17 00:00:00 2001 From: Luke Kenneth Casson Leighton Date: Sun, 10 Oct 2021 16:22:20 +0100 Subject: [PATCH] add option to do fixed-width layout https://bugs.libre-soc.org/show_bug.cgi?id=713#c22 currently failing, answer is *backwards* (bit-inverted) which makes no sense --- src/ieee754/part/layout_experiment.py | 54 ++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 6 deletions(-) diff --git a/src/ieee754/part/layout_experiment.py b/src/ieee754/part/layout_experiment.py index 1b2f6f0a..91cd4c46 100644 --- a/src/ieee754/part/layout_experiment.py +++ b/src/ieee754/part/layout_experiment.py @@ -22,17 +22,27 @@ from ieee754.part_mul_add.partpoints import PartitionPoints # main fn -def layout(elwid, signed, part_counts, lane_shapes): +def layout(elwid, signed, part_counts, lane_shapes, fixed_width=None): # identify if the lane_shapes is a mapping (dict, etc.) # if not, then assume that it is an integer (width) that # needs to be requested across all partitions if not isinstance(lane_shapes, Mapping): lane_shapes = {i: lane_shapes for i in part_counts} # compute a set of partition widths - part_wid = -min(-lane_shapes[i] // c for i, c in part_counts.items()) + cpart_wid = -min(-lane_shapes[i] // c for i, c in part_counts.items()) part_count = max(part_counts.values()) # calculate the minumum width required - width = part_wid * part_count + width = cpart_wid * part_count + if fixed_width is not None: # override the width and part_wid + assert width < fixed_width, "not enough space to fit partitions" + part_wid = fixed_width // part_count + assert part_wid * part_count == fixed_width, \ + "calculated width not aligned multiples" + width = fixed_width + print ("part_wid", part_wid, "count", part_count) + else: + # go with computed width + part_wid = cpart_wid # create the breakpoints dictionary. # do multi-stage version https://bugs.libre-soc.org/show_bug.cgi?id=713#c34 # https://stackoverflow.com/questions/26367812/ @@ -46,16 +56,18 @@ def layout(elwid, signed, part_counts, lane_shapes): # do not need the breakpoints at the very start or the very end dpoints.pop(0, None) dpoints.pop(width, None) + plist = list(dpoints.keys()) + plist.sort() + print ("dpoints") + pprint(dict(dpoints)) # second stage, add (map to) the elwidth==i expressions points = {} - for p in dpoints.keys(): + for p in plist: points[p] = map(lambda i: elwid == i, dpoints[p]) points[p] = reduce(operator.or_, points[p]) # third stage, create the binary values which *if* elwidth is set to i # *would* result in the mask at that elwidth being set to this value # these can easily be double-checked through Assertion - plist = list(points.keys()) - plist.sort() bitp = {} for i in part_counts.keys(): bitp[i] = 0 @@ -107,3 +119,33 @@ if __name__ == '__main__': sim = Simulator(m) sim.add_process(process) sim.run() + + # set the width fixed + # https://bugs.libre-soc.org/show_bug.cgi?id=713#c22 + elwid = Signal(2) + pp,bitp,b,c,d,e = layout(elwid, False, part_counts, l, fixed_width=64) + pprint ((pp,b,c,d,e)) + for k, v in bitp.items(): + print ("bitp elwidth=%d" % k, bin(v)) + + m = Module() + def process(): + for i in range(4): + yield elwid.eq(i) + yield Settle() + ppt = [] + for pval in list(pp.values()): + val = yield pval # get nmigen to evaluate pp + ppt.append(val) + print ("test elwidth=%d" % i) + pprint((i, (ppt,b,c,d,e))) + # check the results against bitp static-expected partition points + # https://bugs.libre-soc.org/show_bug.cgi?id=713#c47 + # https://stackoverflow.com/a/27165694 + ival = int(''.join(map(str, map(int, ppt))), 2) + assert ival == bitp[i], "ival %s actual %s" % (bin(ival), + bin(bitp[i])) + + sim = Simulator(m) + sim.add_process(process) + sim.run() -- 2.30.2