another code-morph working towards getting the predicate-skipping
[openpower-isa.git] / src / openpower / decoder / isa / dct_butterfly_svg.py
1 #!/usr/bin/env python
2 # SPDX: LGPLv3+
3 # Program for generating DCT butterfly diagrams from yield REMAP schedules
4 # avoids the need to mess about drawing diagrams by hand, getting them wrong,
5 # introducing mistakes (common in academic published papers, sigh)
6
7 from copy import deepcopy
8 from collections import OrderedDict
9 from math import pi
10 import os
11 import base64
12 import math
13
14 from openpower.decoder.isa.remap_dct_yield import (reverse_bits, halfrev2,
15 iterate_dct_inner_butterfly_indices,
16 iterate_dct_outer_butterfly_indices,
17 )
18
19 cwd = os.path.split(os.path.abspath(__file__))[0]
20
21 def linescale(l1, l2, scale):
22 diffx = l2[0] - l1[0]
23 diffy = l2[1] - l1[1]
24 return l1[0] - diffx*scale, l1[1] + diffy*scale
25
26 def lineoffs(l2, scale):
27 return l2[0] - abs(scale), l2[1] + scale
28
29
30 def create_idct(fname, n, redir=True):
31 """unsophisticated drawer of an SVG
32 """
33
34 try:
35 import svgwrite
36 except ImportError:
37 print ("WARNING, no SVG image, not producing image %s" % fname)
38 return
39
40 # Initialization
41 vec = range(n)
42 print ()
43 print ("transform2", n)
44 levels = n.bit_length() - 1
45
46 # set up dims
47 xdim = n
48
49 # reference (read/write) the in-place data in *reverse-bit-order*
50 ri = list(range(n))
51 ri = [ri[reverse_bits(i, levels)] for i in range(n)]
52
53 # pretend we LDed data in half-swapped *and* bit-reversed order as well
54 # TODO: merge these two
55 vec = [vec[ri[i]] for i in range(n)]
56 vec = halfrev2(vec, True)
57
58 width = 800
59 height = 600
60 scale = 15
61
62 dwg = svgwrite.Drawing(fname, profile='full',
63 size=(width, height))
64
65 # outer QFP rect
66 dwg.add(dwg.rect((0, 0), (width, height),
67 fill='white',
68 stroke=svgwrite.rgb(0, 128, 0, '%'),
69 stroke_width=scale/5.0))
70
71 # x start layer
72 xstep = width / 10.0
73 x = xstep / 2
74 ystep = height/(n+1.0)
75 y = ystep
76
77 # start data
78 for i in range(n):
79 # flat lines
80 startline = (x-scale, y+i*ystep+scale/2)
81 dwg.add(dwg.text("%d" % vec[i],
82 startline,
83 fill='black'))
84
85 # set up an SVSHAPE
86 class SVSHAPE:
87 pass
88
89 # ####
90 # outer
91 # ####
92
93 # j schedule
94 SVSHAPE0 = SVSHAPE()
95 SVSHAPE0.lims = [xdim, 0b0000010, 0]
96 SVSHAPE0.submode2 = 0b11
97 SVSHAPE0.mode = 0b11
98 SVSHAPE0.skip = 0b00
99 SVSHAPE0.offset = 0 # experiment with different offset, here
100 SVSHAPE0.invxyz = [1,0,1] # inversion if desired
101 # j+halfstep schedule
102 SVSHAPE1 = SVSHAPE()
103 SVSHAPE1.lims = [xdim, 0b0000010, 0]
104 SVSHAPE1.mode = 0b11
105 SVSHAPE1.submode2 = 0b11
106 SVSHAPE1.skip = 0b01
107 SVSHAPE1.offset = 0 # experiment with different offset, here
108 SVSHAPE1.invxyz = [1,0,1] # inversion if desired
109
110 # enumerate over the iterator function, getting new indices
111 i0 = iterate_dct_outer_butterfly_indices(SVSHAPE0)
112 i1 = iterate_dct_outer_butterfly_indices(SVSHAPE1)
113 for k, ((jl, jle), (jh, jhe)) in enumerate(zip(i0, i1)):
114 print ("itersum jr", jl, jh,
115 "end", bin(jle), bin(jhe))
116 if redir:
117 jl = vec[jl]
118 jh = vec[jh]
119 # jh to jl
120 startline = (x, y+jh*ystep)
121 endline = (x+xstep, y+jl*ystep)
122 dwg.add(dwg.line(startline,
123 endline,
124 stroke=svgwrite.rgb(255, 16, 16, '%'),
125 stroke_width=scale/10.0))
126 # plus sign
127 dwg.add(dwg.text("+",
128 lineoffs(endline, scale*0.9),
129 fill='black'))
130 if (jle & 0b010):
131 for i in range(n):
132 # flat lines
133 startline = (x, y+i*ystep)
134 endline = (x+xstep, y+i*ystep)
135 dwg.add(dwg.line(startline,
136 endline,
137 stroke=svgwrite.rgb(16, 255, 16, '%'),
138 stroke_width=scale/15.0))
139 x += xstep * 1.2
140 if jle == 0b111: # all loops end
141 break
142
143 # break point
144 for i in range(n):
145 # flat lines
146 startline = (x, y+i*ystep)
147 endline = (x+xstep, y+i*ystep)
148 dwg.add(dwg.line(startline,
149 endline,
150 stroke=svgwrite.rgb(16, 255, 16, '%'),
151 stroke_width=scale/15.0))
152 x += xstep * 0.2
153
154 ################
155 # INNER butterfly
156 ################
157
158 # j schedule
159 SVSHAPE0 = SVSHAPE()
160 SVSHAPE0.lims = [xdim, 0b000001, 0]
161 SVSHAPE0.mode = 0b11
162 SVSHAPE0.submode2 = 0b11
163 SVSHAPE0.skip = 0b00
164 SVSHAPE0.offset = 0 # experiment with different offset, here
165 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
166 # j+halfstep schedule
167 SVSHAPE1 = SVSHAPE()
168 SVSHAPE1.lims = [xdim, 0b000001, 0]
169 SVSHAPE1.mode = 0b11
170 SVSHAPE1.submode2 = 0b11
171 SVSHAPE1.skip = 0b01
172 SVSHAPE1.offset = 0 # experiment with different offset, here
173 SVSHAPE1.invxyz = [0,0,0] # inversion if desired
174 # ci schedule
175 SVSHAPE2 = SVSHAPE()
176 SVSHAPE2.lims = [xdim, 0b000001, 0]
177 SVSHAPE2.mode = 0b11
178 SVSHAPE2.submode2 = 0b11
179 SVSHAPE2.skip = 0b10
180 SVSHAPE2.offset = 0 # experiment with different offset, here
181 SVSHAPE2.invxyz = [0,0,0] # inversion if desired
182 # size schedule
183 SVSHAPE3 = SVSHAPE()
184 SVSHAPE3.lims = [xdim, 0b000001, 0]
185 SVSHAPE3.mode = 0b11
186 SVSHAPE3.submode2 = 0b11
187 SVSHAPE3.skip = 0b11
188 SVSHAPE3.offset = 0 # experiment with different offset, here
189 SVSHAPE3.invxyz = [0,0,0] # inversion if desired
190
191 # enumerate over the iterator function, getting new indices
192 i0 = iterate_dct_inner_butterfly_indices(SVSHAPE0)
193 i1 = iterate_dct_inner_butterfly_indices(SVSHAPE1)
194 i2 = iterate_dct_inner_butterfly_indices(SVSHAPE2)
195 i3 = iterate_dct_inner_butterfly_indices(SVSHAPE3)
196 for k, ((jl, jle), (jh, jhe), (ci, cie), (size, sze)) in \
197 enumerate(zip(i0, i1, i2, i3)):
198 if redir:
199 jl = vec[jl]
200 jh = vec[jh]
201 print ("xform2", jl, jh, ci, size)
202 # jl to jh
203 startline = (x, y+jl*ystep)
204 endline = (x+xstep, y+jh*ystep)
205 dwg.add(dwg.line(startline,
206 endline,
207 stroke=svgwrite.rgb(255, 16, 16, '%'),
208 stroke_width=scale/10.0))
209 # plus sign
210 dwg.add(dwg.text("+",
211 lineoffs(endline, scale*0.9),
212 fill='black'))
213 # jh to jl
214 startline = (x, y+jh*ystep)
215 endline = (x+xstep, y+jl*ystep)
216 dwg.add(dwg.line(startline,
217 endline,
218 stroke=svgwrite.rgb(255, 16, 16, '%'),
219 stroke_width=scale/10.0))
220 # times sign
221 dwg.add(dwg.text("x",
222 lineoffs(endline, scale*0.9),
223 fill='black'))
224
225 if (jle & 0b010):
226 for i in range(n):
227 # flat lines
228 startline = (x, y+i*ystep)
229 endline = (x+xstep, y+i*ystep)
230 dwg.add(dwg.line(startline,
231 endline,
232 stroke=svgwrite.rgb(16, 255, 16, '%'),
233 stroke_width=scale/15.0))
234 x += xstep * 1.2
235 if jle == 0b111: # all loops end
236 break
237
238 print("transform2 result", vec)
239
240 dwg.save()
241
242
243 def create_dct(fname, n, redir=True):
244 """unsophisticated drawer of an SVG
245 """
246
247 try:
248 import svgwrite
249 except ImportError:
250 print ("WARNING, no SVG image, not producing image %s" % fname)
251 return
252
253 # Initialization
254 vec = range(n)
255 print ()
256 print ("transform2", n)
257 levels = n.bit_length() - 1
258
259 # set up dims
260 xdim = n
261
262 # reference (read/write) the in-place data in *reverse-bit-order*
263 ri = list(range(n))
264 ri = [ri[reverse_bits(i, levels)] for i in range(n)]
265
266 # and pretend we LDed data in half-swapped *and* bit-reversed order as well
267 # TODO: merge these two
268 vec = halfrev2(vec, False)
269 vec = [vec[ri[i]] for i in range(n)]
270
271 width = 800
272 height = 600
273 scale = 15
274
275 dwg = svgwrite.Drawing(fname, profile='full',
276 size=(width, height))
277
278 # outer QFP rect
279 dwg.add(dwg.rect((0, 0), (width, height),
280 fill='white',
281 stroke=svgwrite.rgb(0, 128, 0, '%'),
282 stroke_width=scale/5.0))
283
284 # set up an SVSHAPE
285 class SVSHAPE:
286 pass
287
288 ################
289 # INNER butterfly
290 ################
291
292 # j schedule
293 SVSHAPE0 = SVSHAPE()
294 SVSHAPE0.lims = [xdim, 0b000001, 0]
295 SVSHAPE0.mode = 0b01
296 SVSHAPE0.submode2 = 0b01
297 SVSHAPE0.skip = 0b00
298 SVSHAPE0.offset = 0 # experiment with different offset, here
299 SVSHAPE0.invxyz = [1,0,0] # inversion if desired
300 # j+halfstep schedule
301 SVSHAPE1 = SVSHAPE()
302 SVSHAPE1.lims = [xdim, 0b000001, 0]
303 SVSHAPE1.mode = 0b01
304 SVSHAPE1.submode2 = 0b01
305 SVSHAPE1.skip = 0b01
306 SVSHAPE1.offset = 0 # experiment with different offset, here
307 SVSHAPE1.invxyz = [1,0,0] # inversion if desired
308 # ci schedule
309 SVSHAPE2 = SVSHAPE()
310 SVSHAPE2.lims = [xdim, 0b000001, 0]
311 SVSHAPE2.mode = 0b01
312 SVSHAPE2.submode2 = 0b01
313 SVSHAPE2.skip = 0b10
314 SVSHAPE2.offset = 0 # experiment with different offset, here
315 SVSHAPE2.invxyz = [1,0,0] # inversion if desired
316 # size schedule
317 SVSHAPE3 = SVSHAPE()
318 SVSHAPE3.lims = [xdim, 0b000001, 0]
319 SVSHAPE3.mode = 0b01
320 SVSHAPE3.submode2 = 0b01
321 SVSHAPE3.skip = 0b11
322 SVSHAPE3.offset = 0 # experiment with different offset, here
323 SVSHAPE3.invxyz = [1,0,0] # inversion if desired
324
325 # x start layer
326 xstep = width / 10.0
327 x = xstep / 2
328 ystep = height/(n+1.0)
329 y = ystep
330
331 # start data
332 for i in range(n):
333 # flat lines
334 startline = (x-scale, y+i*ystep+scale/2)
335 dwg.add(dwg.text("%d" % vec[i],
336 startline,
337 fill='black'))
338
339 # enumerate over the iterator function, getting new indices
340 i0 = iterate_dct_inner_butterfly_indices(SVSHAPE0)
341 i1 = iterate_dct_inner_butterfly_indices(SVSHAPE1)
342 i2 = iterate_dct_inner_butterfly_indices(SVSHAPE2)
343 i3 = iterate_dct_inner_butterfly_indices(SVSHAPE3)
344 for k, ((jl, jle), (jh, jhe), (ci, cie), (size, sze)) in \
345 enumerate(zip(i0, i1, i2, i3)):
346 if redir:
347 jl = vec[jl]
348 jh = vec[jh]
349 print ("xform2", jl, jh, ci, size)
350 coeff = (math.cos((ci + 0.5) * math.pi / size) * 2.0)
351 # jl to jh
352 startline = (x, y+jl*ystep)
353 endline = (x+xstep, y+jh*ystep)
354 dwg.add(dwg.line(startline,
355 endline,
356 stroke=svgwrite.rgb(255, 16, 16, '%'),
357 stroke_width=scale/10.0))
358 # plus sign
359 dwg.add(dwg.text("+",
360 lineoffs(endline, scale*0.9),
361 fill='black'))
362 # jh to jl
363 startline = (x, y+jh*ystep)
364 endline = (x+xstep, y+jl*ystep)
365 dwg.add(dwg.line(startline,
366 endline,
367 stroke=svgwrite.rgb(255, 16, 16, '%'),
368 stroke_width=scale/10.0))
369 # times sign
370 dwg.add(dwg.text("x",
371 lineoffs(endline, scale*0.9),
372 fill='black'))
373
374 if (jle & 0b010):
375 for i in range(n):
376 # flat lines
377 startline = (x, y+i*ystep)
378 endline = (x+xstep, y+i*ystep)
379 dwg.add(dwg.line(startline,
380 endline,
381 stroke=svgwrite.rgb(16, 255, 16, '%'),
382 stroke_width=scale/15.0))
383 x += xstep * 1.2
384 if jle == 0b111: # all loops end
385 break
386
387 # break point
388 for i in range(n):
389 # flat lines
390 startline = (x, y+i*ystep)
391 endline = (x+xstep, y+i*ystep)
392 dwg.add(dwg.line(startline,
393 endline,
394 stroke=svgwrite.rgb(16, 255, 16, '%'),
395 stroke_width=scale/15.0))
396 x += xstep * 0.2
397
398 # ####
399 # outer
400 # ####
401
402 # j schedule
403 SVSHAPE0 = SVSHAPE()
404 SVSHAPE0.lims = [xdim, 0b0000010, 0]
405 SVSHAPE0.submode2 = 0b100
406 SVSHAPE0.mode = 0b01
407 SVSHAPE0.skip = 0b00
408 SVSHAPE0.offset = 0 # experiment with different offset, here
409 SVSHAPE0.invxyz = [0,0,0] # inversion if desired
410 # j+halfstep schedule
411 SVSHAPE1 = SVSHAPE()
412 SVSHAPE1.lims = [xdim, 0b0000010, 0]
413 SVSHAPE1.mode = 0b01
414 SVSHAPE1.submode2 = 0b100
415 SVSHAPE1.skip = 0b01
416 SVSHAPE1.offset = 0 # experiment with different offset, here
417 SVSHAPE1.invxyz = [0,0,0] # inversion if desired
418
419 # enumerate over the iterator function, getting new indices
420 i0 = iterate_dct_outer_butterfly_indices(SVSHAPE0)
421 i1 = iterate_dct_outer_butterfly_indices(SVSHAPE1)
422 for k, ((jl, jle), (jh, jhe)) in enumerate(zip(i0, i1)):
423 if redir:
424 jl = vec[jl]
425 jh = vec[jh]
426 print ("itersum jr", jl, jh,
427 "end", bin(jle), bin(jhe))
428 # jh to jl
429 startline = (x, y+jh*ystep)
430 endline = (x+xstep, y+jl*ystep)
431 dwg.add(dwg.line(startline,
432 endline,
433 stroke=svgwrite.rgb(255, 16, 16, '%'),
434 stroke_width=scale/10.0))
435 # plus sign
436 dwg.add(dwg.text("+",
437 lineoffs(endline, scale*0.9),
438 fill='black'))
439 if (jle & 0b010):
440 for i in range(n):
441 # flat lines
442 startline = (x, y+i*ystep)
443 endline = (x+xstep, y+i*ystep)
444 dwg.add(dwg.line(startline,
445 endline,
446 stroke=svgwrite.rgb(16, 255, 16, '%'),
447 stroke_width=scale/15.0))
448 x += xstep * 1.2
449 if jle == 0b111: # all loops end
450 break
451
452 print("transform2 result", vec)
453
454 dwg.save()
455
456
457 if __name__ == '__main__':
458 create_dct("dct_butterfly_8.svg", 8)
459 create_idct("idct_butterfly_8.svg", 8)
460 create_dct("dct_butterfly_16.svg", 16)
461 create_idct("idct_butterfly_16.svg", 16)