1b2f6f0aca22001451b8f3864984f3c0dc0cda37
2 # SPDX-License-Identifier: LGPL-3-or-later
3 # See Notices.txt for copyright information
6 * https://libre-soc.org/3d_gpu/architecture/dynamic_simd/shape/
7 * https://bugs.libre-soc.org/show_bug.cgi?id=713#c20
8 * https://bugs.libre-soc.org/show_bug.cgi?id=713#c30
11 from nmigen
import Signal
, Module
, Elaboratable
, Mux
, Cat
, Shape
, Repl
12 from nmigen
.back
.pysim
import Simulator
, Delay
, Settle
13 from nmigen
.cli
import rtlil
15 from collections
.abc
import Mapping
16 from functools
import reduce
18 from collections
import defaultdict
19 from pprint
import pprint
21 from ieee754
.part_mul_add
.partpoints
import PartitionPoints
25 def layout(elwid
, signed
, part_counts
, lane_shapes
):
26 # identify if the lane_shapes is a mapping (dict, etc.)
27 # if not, then assume that it is an integer (width) that
28 # needs to be requested across all partitions
29 if not isinstance(lane_shapes
, Mapping
):
30 lane_shapes
= {i
: lane_shapes
for i
in part_counts
}
31 # compute a set of partition widths
32 part_wid
= -min(-lane_shapes
[i
] // c
for i
, c
in part_counts
.items())
33 part_count
= max(part_counts
.values())
34 # calculate the minumum width required
35 width
= part_wid
* part_count
36 # create the breakpoints dictionary.
37 # do multi-stage version https://bugs.libre-soc.org/show_bug.cgi?id=713#c34
38 # https://stackoverflow.com/questions/26367812/
39 dpoints
= defaultdict(list) # if empty key, create a (empty) list
40 for i
, c
in part_counts
.items():
42 dpoints
[p
].append(i
) # auto-creates list if key non-existent
43 for start
in range(0, part_count
, c
):
44 add_p(start
* part_wid
) # start of lane
45 add_p(start
* part_wid
+ lane_shapes
[i
]) # start of padding
46 # do not need the breakpoints at the very start or the very end
48 dpoints
.pop(width
, None)
49 # second stage, add (map to) the elwidth==i expressions
51 for p
in dpoints
.keys():
52 points
[p
] = map(lambda i
: elwid
== i
, dpoints
[p
])
53 points
[p
] = reduce(operator
.or_
, points
[p
])
54 # third stage, create the binary values which *if* elwidth is set to i
55 # *would* result in the mask at that elwidth being set to this value
56 # these can easily be double-checked through Assertion
57 plist
= list(points
.keys())
60 for i
in part_counts
.keys():
62 for p
, elwidths
in dpoints
.items():
64 bitpos
= plist
.index(p
)
66 return (PartitionPoints(points
), bitp
, width
, lane_shapes
,
69 if __name__
== '__main__':
78 pprint((i
, layout(i
, True, part_counts
, 3)))
80 l
= {0: 5, 1: 6, 2: 12, 3: 24}
82 pprint((i
, layout(i
, False, part_counts
, l
)))
84 # https://bugs.libre-soc.org/show_bug.cgi?id=713#c30
86 pp
,bitp
,b
,c
,d
,e
= layout(elwid
, False, part_counts
, l
)
88 for k
, v
in bitp
.items():
89 print ("bitp elwidth=%d" % k
, bin(v
))
97 for pval
in list(pp
.values()):
98 val
= yield pval
# get nmigen to evaluate pp
100 pprint((i
, (ppt
,b
,c
,d
,e
)))
101 # check the results against bitp static-expected partition points
102 # https://bugs.libre-soc.org/show_bug.cgi?id=713#c47
103 # https://stackoverflow.com/a/27165694
104 ival
= int(''.join(map(str, map(int, ppt
))), 2)
105 assert ival
== bitp
[i
]
108 sim
.add_process(process
)