|
11 | 11 | from apycula import chipdb
|
12 | 12 | from apycula import fuse_h4x
|
13 | 13 | from apycula import gowin_unpack
|
14 |
| -from apycula.wirenames import wirenames |
| 14 | +from apycula.wirenames import wirenames, clknames, wirenumbers, clknumbers |
15 | 15 |
|
16 | 16 | def dff(mod, cst, row, col, clk=None):
|
17 | 17 | "make a dff with optional clock"
|
@@ -307,6 +307,134 @@ def branch_aliases(quads, clks):
|
307 | 307 |
|
308 | 308 | return aliases
|
309 | 309 |
|
| 310 | +def get_bufs_bits(fse, ttyp, win, wout): |
| 311 | + wi = clknumbers[win] |
| 312 | + wo = clknumbers[wout] |
| 313 | + fuses = [] |
| 314 | + for rec in fse[ttyp]['wire'][38]: |
| 315 | + if rec[0] == wi and rec[1] == wo: |
| 316 | + fuses = chipdb.unpad(rec[2:]) |
| 317 | + break |
| 318 | + return {fuse_h4x.fuse_lookup(fse, ttyp, f) for f in fuses} |
| 319 | + |
| 320 | +# create aliases and pips for long wires |
| 321 | +def make_lw_aliases(fse, dat, db, quads, clks): |
| 322 | + # type 81, 82, 83, 84 tiles have source muxes |
| 323 | + center_row, col82 = dat['center'] |
| 324 | + center_row -= 1 |
| 325 | + last_row = db.rows - 1 |
| 326 | + col82 -= 1 |
| 327 | + col81 = col82 - 1 |
| 328 | + col83 = col82 + 1 |
| 329 | + col84 = col82 + 2 |
| 330 | + # type 91 and 92 tiles activate the quadrants |
| 331 | + # XXX GW1NS-4 have different types |
| 332 | + type91 = fse['header']['grid'][61][0][col82] |
| 333 | + type92 = fse['header']['grid'][61][last_row][col82] |
| 334 | + col91 = col82 |
| 335 | + has_bottom_quadrants = len(quads) > 2 |
| 336 | + |
| 337 | + # quadrants activation bels |
| 338 | + # delete direct pips "long wire->spine" because the artificial bel will be used, |
| 339 | + # which replaces this direct pip |
| 340 | + rows = {(0, 'T', type91)} |
| 341 | + if has_bottom_quadrants: |
| 342 | + rows.update({ (last_row, 'B', type92) }) |
| 343 | + for row, half, ttyp in rows: |
| 344 | + for idx in range(8): |
| 345 | + bel = db.grid[row][col91].bels.setdefault(f'BUFS{idx}', chipdb.Bel()) |
| 346 | + del db.grid[row][col91].clock_pips[f'LWSPINE{half}L{idx}'] |
| 347 | + del db.grid[row][col91].clock_pips[f'LWSPINE{half}R{idx}'] |
| 348 | + src = f'LW{half}{idx}' |
| 349 | + db.grid[row][col91].clock_pips.setdefault(f'LWI{idx}', {})[src] = {} |
| 350 | + db.grid[row][col91].clock_pips.setdefault(f'LWSPINE{half}L{idx}', {})[f'LWO{idx}'] = {} |
| 351 | + bel.flags['L'] = get_bufs_bits(fse, ttyp, f'LW{half}{idx}', f'LWSPINE{half}L{idx}') |
| 352 | + db.grid[row][col91].clock_pips.setdefault(f'LWSPINE{half}R{idx}', {})[f'LWO{idx}'] = {} |
| 353 | + bel.flags['R'] = get_bufs_bits(fse, ttyp, f'LW{half}{idx}', f'LWSPINE{half}R{idx}') |
| 354 | + bel.portmap['I'] = f'LWI{idx}' |
| 355 | + bel.portmap['O'] = f'LWO{idx}' |
| 356 | + # aliases for long wire origins (center muxes) |
| 357 | + # If we have only two quadrants, then do not create aliases in the bottom tile 92, |
| 358 | + # thereby excluding these wires from the candidates for routing |
| 359 | + if half == 'B' and not has_bottom_quadrants: |
| 360 | + continue |
| 361 | + if half == 'T': |
| 362 | + if idx != 7: |
| 363 | + db.aliases.update({(row, col82, src) : (center_row, col82, src)}) |
| 364 | + else: |
| 365 | + db.aliases.update({(row, col82, src) : (center_row, col81, src)}) |
| 366 | + else: |
| 367 | + if idx != 7: |
| 368 | + db.aliases.update({(row, col82, src) : (center_row, col83, src)}) |
| 369 | + else: |
| 370 | + db.aliases.update({(row, col82, src) : (center_row, col84, src)}) |
| 371 | + # branches |
| 372 | + # {lw#: {tap_col: {cols}} |
| 373 | + taps = {} |
| 374 | + lw_taps = [-1, -1, -1, -1] |
| 375 | + any_mux = list(clks.keys())[0] |
| 376 | + for gclk in range(4): |
| 377 | + if gclk not in clks[any_mux].keys(): |
| 378 | + # XXX |
| 379 | + continue |
| 380 | + lw_taps[gclk] = min(clks[any_mux][gclk].keys()) |
| 381 | + |
| 382 | + if -1 in lw_taps: |
| 383 | + # XXX GW1NZ-1 temporary hack |
| 384 | + if lw_taps.count(-1) != 1: |
| 385 | + raise Exception("Inconsistent clock tap columns, something is went wrong with the clock detection.") |
| 386 | + else: |
| 387 | + lw_taps[lw_taps.index(-1)] = 0 + 1 + 2 + 3 - 1 - sum(lw_taps) |
| 388 | + print(" lw_taps = ", lw_taps) |
| 389 | + |
| 390 | + for lw in range(4): |
| 391 | + tap_col = lw_taps[lw] |
| 392 | + for col in range(db.cols): |
| 393 | + if (col > tap_col + 2) and (tap_col + 4 < db.cols): |
| 394 | + tap_col += 4 |
| 395 | + taps.setdefault(lw, {}).setdefault(tap_col, set()).add(col) |
| 396 | + |
| 397 | + for row in range(db.rows): |
| 398 | + for lw, tap_desc in taps.items(): |
| 399 | + for tap_col, cols in tap_desc.items(): |
| 400 | + tap_row = 0 |
| 401 | + if row > (center_row * 2): |
| 402 | + tap_row = last_row |
| 403 | + db.aliases.update({(row, tap_col, 'LT01') : (tap_row, tap_col, 'LT02')}) |
| 404 | + db.aliases.update({(row, tap_col, 'LT04') : (tap_row, tap_col, 'LT13')}) |
| 405 | + for col in cols: |
| 406 | + db.aliases.update({(row, col, f'LB{lw}1') : (row, tap_col, f'LBO0')}) |
| 407 | + db.aliases.update({(row, col, f'LB{lw + 4}1') : (row, tap_col, f'LBO1')}) |
| 408 | + |
| 409 | + # tap sources |
| 410 | + rows = { (0, 'T') } |
| 411 | + if has_bottom_quadrants: |
| 412 | + rows.update({ (last_row, 'B') }) |
| 413 | + for row, qd in rows: |
| 414 | + for lw, tap_desc in taps.items(): |
| 415 | + for tap_col, cols in tap_desc.items(): |
| 416 | + if tap_col <= col91: |
| 417 | + half = 'L' |
| 418 | + else: |
| 419 | + half = 'R' |
| 420 | + db.aliases.update({ (row, tap_col, 'SS00') : (row, col91, f'LWSPINE{qd}{half}{lw}') }) |
| 421 | + db.aliases.update({ (row, tap_col, 'SS40') : (row, col91, f'LWSPINE{qd}{half}{lw + 4}') }) |
| 422 | + # XXX remove all pips except SS00 and SS40 |
| 423 | + pip2keep = {'SS00', 'SS40'} |
| 424 | + for tp in ['LT02', 'LT13']: |
| 425 | + for pip in [p for p in db.grid[row][tap_col].pips[tp] if p not in pip2keep]: |
| 426 | + del db.grid[row][tap_col].pips[tp][pip] |
| 427 | + # logic entries |
| 428 | + srcs = {} |
| 429 | + for i, src in enumerate(dat['UfbIns']): |
| 430 | + row, col, pip = src |
| 431 | + if pip == 126: # CLK2 |
| 432 | + db.aliases.update({ (center_row, col82, f'UNK{i + 104}'): (row - 1, col -1, 'CLK2')}) |
| 433 | + db.aliases.update({ (center_row, col81, f'UNK{i + 104}'): (row - 1, col -1, 'CLK2')}) |
| 434 | + if has_bottom_quadrants: |
| 435 | + db.aliases.update({ (center_row, col83, f'UNK{i + 104}'): (row - 1, col -1, 'CLK2')}) |
| 436 | + db.aliases.update({ (center_row, col84, f'UNK{i + 104}'): (row - 1, col -1, 'CLK2')}) |
| 437 | + |
310 | 438 | if __name__ == "__main__":
|
311 | 439 | quads = quadrants()
|
312 | 440 |
|
@@ -343,6 +471,10 @@ def branch_aliases(quads, clks):
|
343 | 471 | db.aliases.update(ta)
|
344 | 472 | db.aliases.update(ba)
|
345 | 473 |
|
| 474 | + # long wires |
| 475 | + make_lw_aliases(fse, dat, db, quads, clks) |
| 476 | + |
| 477 | + |
346 | 478 | with open(f"{tiled_fuzzer.device}_stage2.pickle", 'wb') as f:
|
347 | 479 | pickle.dump(db, f)
|
348 | 480 |
|
0 commit comments