From 68899988c80fe042b693db554833256ab79ca541 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Thu, 25 Jul 2024 15:32:45 +1000 Subject: [PATCH] HCLK. Add interbank wires An interesting mechanism for transmitting signals between HCLK banks (or otherwise parties) has been discovered. We have two points, each of which can receive a signal from any HCLK and transmit it to any other HCLK. No complex signals can be transmitted here - the input lines are limited by HCLK_INx, and we also need to see which components can use the output from these two points, but so far the tests are encouraging: it is possible to transmit a signal from the clock pin from one side of the chip to the opposite and feed CLKDIV2 there using just a couple wires! Signed-off-by: YRabbit --- apycula/chipdb.py | 90 ++++++++++++++++++++++++++----------------- apycula/gowin_pack.py | 18 ++++++++- apycula/wirenames.py | 16 +++++++- 3 files changed, 85 insertions(+), 39 deletions(-) diff --git a/apycula/chipdb.py b/apycula/chipdb.py index 9c846c38..03969b9f 100644 --- a/apycula/chipdb.py +++ b/apycula/chipdb.py @@ -1023,12 +1023,19 @@ def fse_create_hclk_nodes(dev, device, fse, dat: Datfile): row, col = hclk_loc ttyp = fse['header']['grid'][61][row][col] dev.hclk_pips[(row, col)] = fse_pips(fse, ttyp, table = 48, wn = hclknames) + for dst in dev.hclk_pips[(row, col)].keys(): + # from HCLK to interbank MUX + if dst in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}: + add_node(dev, f'HCLK{"TBLR".index(side)}_BANK_OUT{dst[-1]}', "GLOBAL_CLK", row, col, dst) # connect local wires like PCLKT0 etc to the global nodes for srcs in dev.hclk_pips[(row, col)].values(): for src in srcs.keys(): for pfx in _global_wire_prefixes: if src.startswith(pfx): add_node(dev, src, "HCLK", row, col, src) + # from interbank MUX to HCLK + if src in {'HCLK_BANK_IN0', 'HCLK_BANK_IN1'}: + add_node(dev, f'HCLKMUX{src[-1]}', "GLOBAL_CLK", row, col, src) # strange GW1N-9C input-input aliases for i in {0, 2}: dev.nodes.setdefault(f'X{col}Y{row}/HCLK9-{i}', ('HCLK', {(row, col, f'HCLK_IN{i}')}))[1].add((row, col, f'HCLK_9IN{i}')) @@ -1069,53 +1076,54 @@ def fse_create_hclk_nodes(dev, device, fse, dat: Datfile): # DHCEN (as I imagine) is an additional control input of the HCLK input # multiplexer. We have four input multiplexers - HCLK_IN0, HCLK_IN1, HCLK_IN2, # HCLK_IN3 (GW1N-9C with its additional four multiplexers stands separately, -# but we will deal with it separately). +# but we will deal with it later) and two interbank inputs. # Creating images using IDE where we use the maximum allowable number of DHCEN, # the CE port of which is connected to the IO ports, then we trace the route # from IO to the final wire, which will be the CE port of the DHCEN primitive. # We are not interested in the CLKIN and CLKOUT ports because we are supposed # to simply disable/enable one of the input multiplexers. # Let's summarize the experimental data in a table. -# There are 4 multiplexers on each side of the chip (sides: Right Bottom Left Top). +# There are 4 multiplexers and interbank inputs on each side of the chip +# (sides: Right Bottom Left Top). _dhcen_ce = { 'GW1N-1': - {'B' : [( 0, 19, 'D5'), ( 0, 19, 'D3'), ( 0, 19, 'D4'), ( 0, 19, 'D2')]}, + {'B' : [(10, 19, 'D5'), (10, 19, 'D3'), (10, 19, 'D4'), (10, 19, 'D2'), (10, 0, 'C0'), (10, 0, 'C1')]}, 'GW1NZ-1': - {'R' : [( 0, 19, 'A2'), ( 0, 19, 'A4'), ( 0, 19, 'A3'), ( 0, 19, 'A5')], - 'T' : [(10, 19, 'A2'), (10, 19, 'A4'), (10, 19, 'A3'), (10, 19, 'A5')]}, + {'R' : [( 0, 19, 'A2'), ( 0, 19, 'A4'), ( 0, 19, 'A3'), ( 0, 19, 'A5'), ( 0, 18, 'C6'), ( 0, 18, 'C7')], + 'T' : [(10, 19, 'A2'), (10, 19, 'A4'), (10, 19, 'A3'), (10, 19, 'A5'), (10, 19, 'C6'), (10, 19, 'C7')]}, 'GW1NS-2': - {'R' : [(10, 19, 'A4'), (10, 19, 'A6'), (10, 19, 'A5'), (10, 19, 'A7')], - 'B' : [(11, 19, 'A4'), (11, 19, 'A6'), (11, 19, 'A5'), (11, 19, 'A7')], - 'L' : [( 9, 0, 'A0'), ( 9, 0, 'A2'), ( 9, 0, 'A1'), ( 9, 0, 'A3')], - 'T' : [( 0, 19, 'D5'), ( 0, 19, 'D3'), ( 0, 19, 'D4'), ( 0, 19, 'D2')]}, + {'R' : [(10, 19, 'A4'), (10, 19, 'A6'), (10, 19, 'A5'), (10, 19, 'A7'), (10, 19, 'C4'), (10, 19, 'C5')], + 'B' : [(11, 19, 'A4'), (11, 19, 'A6'), (11, 19, 'A5'), (11, 19, 'A7'), (11, 19, 'C4'), (11, 19, 'C5')], + 'L' : [( 9, 0, 'A0'), ( 9, 0, 'A2'), ( 9, 0, 'A1'), ( 9, 0, 'A3'), ( 9, 0, 'C0'), ( 9, 0, 'C1')], + 'T' : [( 0, 19, 'D5'), ( 0, 19, 'D3'), ( 0, 19, 'D4'), ( 0, 19, 'D2'), ( 0, 0, 'B1'), ( 0, 0, 'B0')]}, 'GW1N-4': - {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6')], - 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5')], - 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6')]}, + {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')], + 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (19, 0, 'A4'), ( 0, 0, 'B1')]}, 'GW1NS-4': - {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6')], - 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5')], - 'T' : [( 1, 0, 'B6'), ( 1, 0, 'A0'), ( 1, 0, 'B7'), ( 1, 0, 'A1')]}, + {'R' : [(18, 37, 'C6'), (18, 37, 'D7'), (18, 37, 'C7'), (18, 37, 'D6'), ( 0, 37, 'D7'), ( 0, 37, 'D6')], + 'B' : [(19, 37, 'A2'), (19, 37, 'A4'), (19, 37, 'A3'), (19, 37, 'A5'), (19, 0, 'B2'), (19, 0, 'B3')], + 'T' : [( 1, 0, 'B6'), ( 1, 0, 'A0'), ( 1, 0, 'B7'), ( 1, 0, 'A1'), ( 1, 0, 'C4'), ( 1, 0, 'C3')]}, + 'GW1N-9': + {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')], + 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')], + 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]}, 'GW1N-9C': - {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6')], - 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5')], - 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6')], - 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6')]}, - 'GW1N-9C': - {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6')], - 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5')], - 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6')], - 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6')]}, + {'R' : [(18, 46, 'C6'), (18, 46, 'D7'), (18, 46, 'C7'), (18, 46, 'D6'), (18, 46, 'B6'), (18, 46, 'B7')], + 'B' : [(28, 46, 'A2'), (28, 46, 'A4'), (28, 46, 'A3'), (28, 46, 'A5'), (28, 0, 'B2'), (28, 0, 'B3')], + 'L' : [(18, 0, 'C6'), (18, 0, 'D7'), (18, 0, 'C7'), (18, 0, 'D6'), (18, 0, 'B6'), (18, 0, 'B7')], + 'T' : [( 9, 0, 'C6'), ( 9, 0, 'D7'), ( 9, 0, 'C7'), ( 9, 0, 'D6'), ( 9, 0, 'B6'), ( 9, 0, 'B7')]}, 'GW2A-18': - {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3')], - 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3')], - 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3')], - 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3')]}, + {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')], + 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')], + 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')], + 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]}, 'GW2A-18C': - {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3')], - 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3')], - 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3')], - 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3')]}, + {'R' : [(27, 55, 'A2'), (27, 55, 'A3'), (27, 55, 'D2'), (27, 55, 'D3'), (27, 55, 'D0'), (27, 55, 'D1')], + 'B' : [(54, 27, 'A2'), (54, 27, 'A3'), (54, 27, 'D2'), (54, 27, 'D3'), (54, 27, 'D0'), (54, 27, 'D1')], + 'L' : [(27, 0, 'A2'), (27, 0, 'A3'), (27, 0, 'D2'), (27, 0, 'D3'), (27, 0, 'D0'), (27, 0, 'D1')], + 'T' : [( 0, 27, 'A2'), ( 0, 27, 'A3'), ( 0, 27, 'D2'), ( 0, 27, 'D3'), ( 0,27, 'D0'), ( 0, 27, 'D1')]}, } def fse_create_dhcen(dev, device, fse, dat: Datfile): if device not in _dhcen_ce: @@ -1128,8 +1136,13 @@ def fse_create_dhcen(dev, device, fse, dat: Datfile): dhcen = extra.setdefault('dhcen', []) # use db.hclk_pips in order to find HCLK_IN cells for hclk_loc in _hclk_to_fclk[device][side]['hclk']: - if f'HCLK_IN{idx}' in dev.hclk_pips[hclk_loc]: - hclkin = {'hclkin' : [f'X{hclk_loc[1]}Y{hclk_loc[0]}', f'HCLK_IN{idx}', side]} + if idx < 4: + if f'HCLK_IN{idx}' in dev.hclk_pips[hclk_loc]: + hclkin = {'wire' : [f'X{hclk_loc[1]}Y{hclk_loc[0]}', f'HCLK_IN{idx}', side]} + else: + if f'HCLK_BANK_OUT{idx - 4}' in dev.hclk_pips[hclk_loc]: + hclkin = {'wire' : [f'X{hclk_loc[1]}Y{hclk_loc[0]}', f'HCLK_BANK_OUT{idx - 4}', side]} + hclkin.update({ 'ce' : wire}) dhcen.append(hclkin) @@ -1386,16 +1399,23 @@ def fse_create_clocks(dev, device, dat: Datfile, fse): spines = {f'SPINE{i}' for i in range(32)} + hclk_srcs = {f'HCLK{i}_BANK_OUT{j}' for i in range(4) for j in range(2)} for row, rd in enumerate(dev.grid): for col, rc in enumerate(rd): for dest, srcs in rc.pure_clock_pips.items(): for src in srcs.keys(): if src in spines and not dest.startswith('GT'): add_node(dev, src, "GLOBAL_CLK", row, col, src) - if dest in spines: + if dest in spines or dest in dcs_inputs: add_node(dev, dest, "GLOBAL_CLK", row, col, dest) for src in { wire for wire in srcs.keys() if wire not in {'VCC', 'VSS'}}: add_node(dev, src, "GLOBAL_CLK", row, col, src) + elif dest in {'HCLKMUX0', 'HCLKMUX1'}: + # this interbank communication between HCLKs + add_node(dev, dest, "GLOBAL_CLK", row, col, dest) + for src in {wire for wire in srcs.keys() if wire in hclk_srcs}: + add_node(dev, src, "GLOBAL_CLK", row, col, src) + # GBx0 <- GBOx for spine_pair in range(4): # GB00/GB40, GB10/GB50, GB20/GB60, GB30/GB70 tap_start = _clock_data[device]['tap_start'][0] diff --git a/apycula/gowin_pack.py b/apycula/gowin_pack.py index 3e9e5282..6d089022 100644 --- a/apycula/gowin_pack.py +++ b/apycula/gowin_pack.py @@ -1973,6 +1973,8 @@ def set_osc_attrs(db, typ, params): 'HCLK_IN1': ('HSB1MUX0_HSTOP', 'HCLKCIBSTOP2'), 'HCLK_IN2': ('HSB0MUX1_HSTOP', 'HCLKCIBSTOP1'), 'HCLK_IN3': ('HSB1MUX1_HSTOP', 'HCLKCIBSTOP3'), + 'HCLK_BANK_OUT0': ('BRGMUX0_BRGSTOP', 'BRGCIBSTOP0'), + 'HCLK_BANK_OUT1': ('BRGMUX1_BRGSTOP', 'BRGCIBSTOP1'), } def find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side): fin_attrs = set() @@ -2467,12 +2469,12 @@ def place(db, tilemap, bels, cst, args): for r, c in bits: cfg_tile[r][c] = 1 elif typ == "DHCEN": - if 'DHCEN_SIDE' not in attrs: + if 'DHCEN_USED' not in attrs: continue # DHCEN as such is just a control wire and does not have a fuse # itself, but HCLK has fuses that allow this control. Here we look # for the corresponding HCLK and set its fuses. - _, wire, side = db.extra_func[row - 1, col -1]['dhcen'][int(num)]['hclkin'] + _, wire, side = db.extra_func[row - 1, col -1]['dhcen'][int(num)]['wire'] hclk_attrs = find_and_set_dhcen_hclk_fuses(db, tilemap, wire, side) else: print("unknown type", typ) @@ -2635,6 +2637,17 @@ def secure_long_wires(db, tilemap, row, col, src, dest): for row, col in bits: tile[row][col] = 1 +# hclk interbank requires to set some non-route fuses +def do_hclk_banks(db, row, col, src, dest): + res = set() + if dest in {'HCLK_BANK_OUT0', 'HCLK_BANK_OUT1'}: + fin_attrs = set() + add_attr_val(db, 'HCLK', fin_attrs, attrids.hclk_attrids[f'BRGMUX{dest[-1]}_BRGOUT'], attrids.hclk_attrvals['ENABLE']) + + ttyp = db.grid[row][col].ttyp + if 'HCLK' in db.shortval[ttyp]: + res = get_shortval_fuses(db, ttyp, fin_attrs, "HCLK") + return res def route(db, tilemap, pips): for row, col, src, dest in pips: @@ -2646,6 +2659,7 @@ def route(db, tilemap, pips): bits = tiledata.clock_pips[dest][src] elif is_himbaechel and (row - 1, col - 1) in db.hclk_pips and dest in db.hclk_pips[row - 1, col - 1]: bits = db.hclk_pips[row - 1, col - 1][dest][src] + bits.update(do_hclk_banks(db, row - 1, col - 1, src, dest)) else: bits = tiledata.pips[dest][src] except KeyError: diff --git a/apycula/wirenames.py b/apycula/wirenames.py index 325f3a6b..6201b815 100644 --- a/apycula/wirenames.py +++ b/apycula/wirenames.py @@ -106,6 +106,18 @@ }) clknames.update({n: f"UNK{n}" for n in range(210, 261)}) + +# HCLK->clock network +# Each HCLK can connect to other HCLKs through two MUXes in the clock system. +# Here we assign numbers to these MUXes and their inputs - two per HCLK +clknames.update({ + 1000: 'HCLKMUX0', 1001: 'HCLKMUX1', + 1002: 'HCLK0_BANK_OUT0', 1003: 'HCLK0_BANK_OUT1', + 1004: 'HCLK1_BANK_OUT0', 1005: 'HCLK1_BANK_OUT1', + 1006: 'HCLK2_BANK_OUT0', 1007: 'HCLK2_BANK_OUT1', + 1008: 'HCLK3_BANK_OUT0', 1009: 'HCLK3_BANK_OUT1', +}) + clknumbers = {v: k for k, v in clknames.items()} # hclk @@ -113,12 +125,12 @@ hclknames.update({n: f"HCLK_UNK{n}" for n in range(26)}) # inputs hclknames.update({ - 2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3' + 2: 'HCLK_IN0', 3: 'HCLK_IN1', 4: 'HCLK_IN2', 5: 'HCLK_IN3', 8: 'HCLK_BANK_IN0', 9: 'HCLK_BANK_IN1' }) # outputs hclknames.update({ - 10: 'HCLK_OUT0', 11: 'HCLK_OUT1', 12: 'HCLK_OUT2', 13: 'HCLK_OUT3' + 6: 'HCLK_BANK_OUT0', 7: 'HCLK_BANK_OUT1', 10: 'HCLK0_SECT0_IN', 11: 'HCLK0_SECT1_IN', 12: 'HCLK1_SECT0_IN', 13: 'HCLK1_SECT1_IN' }) # these work as inputs in GW1N-9c hclknames.update({