@@ -113,6 +113,7 @@ class Device:
113
113
# - OSER16/IDES16
114
114
# - ref to hclk_pips
115
115
# - disabled blocks
116
+ # - BUF(G)
116
117
extra_func : Dict [Tuple [int , int ], Dict [str , Any ]] = field (default_factory = dict )
117
118
118
119
@property
@@ -154,6 +155,40 @@ def bank_tiles(self):
154
155
res .update ({ bel [4 :] : pos })
155
156
return res
156
157
158
+ # XXX GW1N-4 and GW1NS-4 have next data in dat['CmuxIns']:
159
+ # 62 [11, 1, 126]
160
+ # 63 [11, 1, 126]
161
+ # this means that the same wire (11, 1, 126) is connected implicitly to two
162
+ # other logical wires. Let's remember such connections.
163
+ # If suddenly a command is given to assign an already used wire to another
164
+ # node, then all the contents of this node are combined with the existing one,
165
+ # and the node itself is destroyed. only for HCLK and clock nets for now
166
+ wire2node = {}
167
+ def add_node (dev , node_name , wire_type , row , col , wire ):
168
+ if (row , col , wire ) not in wire2node :
169
+ wire2node [row , col , wire ] = node_name
170
+ dev .nodes .setdefault (node_name , (wire_type , set ()))[1 ].add ((row , col , wire ))
171
+ else :
172
+ if node_name != wire2node [row , col , wire ] and node_name in dev .nodes :
173
+ #print(f'{node_name} -> {wire2node[row, col, wire]} share ({row}, {col}, {wire})')
174
+ dev .nodes [wire2node [row , col , wire ]][1 ].update (dev .nodes [node_name ][1 ])
175
+ del dev .nodes [node_name ]
176
+
177
+ # create bels for entry potints to the global clock nets
178
+ def add_buf_bel (dev , row , col , wire , buf_type = 'BUFG' ):
179
+ # clock pins
180
+ if not wire .startswith ('CLK' ):
181
+ return
182
+ extra_func = dev .extra_func .setdefault ((row , col ), {})
183
+ if 'buf' not in extra_func or buf_type not in extra_func ['buf' ]:
184
+ extra_func .update ({'buf' : {buf_type : [wire ]}})
185
+ else :
186
+ # dups not allowed for now
187
+ if wire in extra_func ['buf' ][buf_type ]:
188
+ #print(f'extra buf dup ({row}, {col}) {buf_type}/{wire}')
189
+ return
190
+ extra_func ['buf' ][buf_type ].append (wire )
191
+
157
192
def unpad (fuses , pad = - 1 ):
158
193
try :
159
194
return fuses [:fuses .index (pad )]
@@ -962,7 +997,10 @@ def fse_create_hclk_nodes(dev, device, fse, dat):
962
997
# entries to the HCLK from logic
963
998
for hclk_idx , row , col , wire_idx in {(i , dat ['CmuxIns' ][str (i - 80 )][0 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][1 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][2 ]) for i in range (hclknumbers ['TBDHCLK0' ], hclknumbers ['RBDHCLK3' ] + 1 )}:
964
999
if row != - 2 :
965
- dev .nodes .setdefault (hclknames [hclk_idx ], ("HCLK" , set ()))[1 ].add ((row , col , wirenames [wire_idx ]))
1000
+ add_node (dev , hclknames [hclk_idx ], "HCLK" , row , col , wirenames [wire_idx ])
1001
+ # XXX clock router is doing fine with HCLK w/o any buffering
1002
+ # may be placement suffers a bit
1003
+ #add_buf_bel(dev, row, col, wirenames[wire_idx], buf_type = 'BUFH')
966
1004
967
1005
if 'hclk' in hclk_info [side ]:
968
1006
# create HCLK cells pips
@@ -975,7 +1013,7 @@ def fse_create_hclk_nodes(dev, device, fse, dat):
975
1013
for src in srcs .keys ():
976
1014
for pfx in _global_wire_prefixes :
977
1015
if src .startswith (pfx ):
978
- dev . nodes . setdefault ( src , ( ' HCLK' , set ()))[ 1 ]. add (( row , col , src ) )
1016
+ add_node ( dev , src , " HCLK" , row , col , src )
979
1017
# strange GW1N-9C input-input aliases
980
1018
for i in {0 , 2 }:
981
1019
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 } ' ))
@@ -1249,19 +1287,20 @@ def fse_create_clocks(dev, device, dat, fse):
1249
1287
# find center muxes
1250
1288
for clk_idx , row , col , wire_idx in {(i , dat ['CmuxIns' ][str (i - 80 )][0 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][1 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][2 ]) for i in range (clknumbers ['PCLKT0' ], clknumbers ['PCLKR1' ] + 1 )}:
1251
1289
if row != - 2 :
1252
- dev .nodes .setdefault (clknames [clk_idx ], ("GLOBAL_CLK" , set ()))[1 ].add ((row , col , wirenames [wire_idx ]))
1290
+ add_node (dev , clknames [clk_idx ], "GLOBAL_CLK" , row , col , wirenames [wire_idx ])
1291
+ add_buf_bel (dev , row , col , wirenames [wire_idx ])
1253
1292
1254
1293
spines = {f'SPINE{ i } ' for i in range (32 )}
1255
1294
for row , rd in enumerate (dev .grid ):
1256
1295
for col , rc in enumerate (rd ):
1257
1296
for dest , srcs in rc .pure_clock_pips .items ():
1258
1297
for src in srcs .keys ():
1259
1298
if src in spines and not dest .startswith ('GT' ):
1260
- dev . nodes . setdefault ( src , ( "GLOBAL_CLK" , set ()))[ 1 ]. add (( row , col , src ) )
1299
+ add_node ( dev , src , "GLOBAL_CLK" , row , col , src )
1261
1300
if dest in spines :
1262
- dev . nodes . setdefault ( dest , ( "GLOBAL_CLK" , set ()))[ 1 ]. add (( row , col , dest ) )
1301
+ add_node ( dev , dest , "GLOBAL_CLK" , row , col , dest )
1263
1302
for src in { wire for wire in srcs .keys () if wire not in {'VCC' , 'VSS' }}:
1264
- dev . nodes . setdefault ( src , ( "GLOBAL_CLK" , set ()))[ 1 ]. add (( row , col , src ) )
1303
+ add_node ( dev , src , "GLOBAL_CLK" , row , col , src )
1265
1304
# GBx0 <- GBOx
1266
1305
for spine_pair in range (4 ): # GB00/GB40, GB10/GB50, GB20/GB60, GB30/GB70
1267
1306
tap_start = _clock_data [device ]['tap_start' ][0 ]
@@ -1428,6 +1467,46 @@ def fse_create_io16(dev, device):
1428
1467
('OSCW' , 'GW2AN-18' ): ({'OSCOUT' : 'Q4' }, {}),
1429
1468
}
1430
1469
1470
+ # from logic to global clocks. An interesting piece of dat['CmuxIns'], it was
1471
+ # found out experimentally that this range is responsible for the wires
1472
+ # 129: 'TRBDCLK0' - 152: 'TRMDCLK1'. Again we have a shift of 80 from the wire number
1473
+ # (see create clock aliases).
1474
+ # 124-126 equal CLK0-CLK2 so these are clearly inputs to the clock system
1475
+ # (GW1N-1 data)
1476
+ # 49 [1, 11, 124]
1477
+ # 50 [1, 11, 125]
1478
+ # 51 [6, 20, 124]
1479
+ # 52 [6, 20, 125]
1480
+ # 53 [1, 10, 125]
1481
+ # 54 [6, 1, 124]
1482
+ # 55 [6, 1, 125]
1483
+ # 56 [1, 10, 124]
1484
+ # 57 [11, 11, 124]
1485
+ # 58 [11, 11, 125]
1486
+ # 59 [7, 20, 126]
1487
+ # 60 [8, 20, 126]
1488
+ # 61 [11, 10, 125]
1489
+ # 62 [7, 1, 126]
1490
+ # 63 [8, 1, 126]
1491
+ # 64 [11, 10, 124]
1492
+ # 65 [-1, -1, -1]
1493
+ # 66 [-1, -1, -1]
1494
+ # 67 [-1, -1, -1]
1495
+ # 68 [-1, -1, -1]
1496
+ # 69 [-1, -1, -1]
1497
+ # 70 [-1, -1, -1]
1498
+ # 71 [6, 10, 126]
1499
+ # 72 [6, 11, 126]
1500
+ # We don't need to worry about routing TRBDCLK0 and the family - this was
1501
+ # already done when we created pure clock pips. But what we need to do is
1502
+ # indicate that these CLKs at these coordinates are TRBDCLK0, etc. Therefore,
1503
+ # we create Himbaechel nodes.
1504
+ def fse_create_logic2clk (dev , device , dat ):
1505
+ for clkwire_idx , row , col , wire_idx in {(i , dat ['CmuxIns' ][str (i - 80 )][0 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][1 ] - 1 , dat ['CmuxIns' ][str (i - 80 )][2 ]) for i in range (clknumbers ['TRBDCLK0' ], clknumbers ['TRMDCLK1' ] + 1 )}:
1506
+ if row != - 2 :
1507
+ add_node (dev , clknames [clkwire_idx ], "GLOBAL_CLK" , row , col , wirenames [wire_idx ])
1508
+ add_buf_bel (dev , row , col , wirenames [wire_idx ])
1509
+
1431
1510
def fse_create_osc (dev , device , fse ):
1432
1511
for row , rd in enumerate (dev .grid ):
1433
1512
for col , rc in enumerate (rd ):
@@ -1503,6 +1582,7 @@ def from_fse(device, fse, dat):
1503
1582
fse_create_io16 (dev , device )
1504
1583
fse_create_osc (dev , device , fse )
1505
1584
fse_create_gsr (dev , device )
1585
+ fse_create_logic2clk (dev , device , dat )
1506
1586
disable_plls (dev , device )
1507
1587
sync_extra_func (dev )
1508
1588
return dev
0 commit comments