2
2
import os
3
3
import re
4
4
import pickle
5
+ import itertools
5
6
import numpy as np
6
7
import json
7
8
import argparse
@@ -60,6 +61,13 @@ def infovaluemap(infovalue, start=2):
60
61
"SSTL33_II" : "SSTL33_I" ,
61
62
"LVTTL33" : "LVCMOS33" ,
62
63
}
64
+ # For each bank, remember the Bels used, mark whether Outs were among them and the standard.
65
+ class BankDesc :
66
+ def __init__ (self , iostd , inputs_only , bels_tiles ):
67
+ self .iostd = iostd
68
+ self .inputs_only = inputs_only
69
+ self .bels_tiles = bels_tiles
70
+
63
71
_banks = {}
64
72
_sides = "AB"
65
73
def place (db , tilemap , bels , cst , args ):
@@ -98,7 +106,7 @@ def place(db, tilemap, bels, cst, args):
98
106
# XXX skip power
99
107
if not cellname .startswith ('\$PACKER' ):
100
108
cst .cells [cellname ] = (row , col , int (num ) // 2 , _sides [int (num ) % 2 ])
101
- elif typ == "IOB" :
109
+ elif typ [: 3 ] == "IOB" :
102
110
edge = 'T'
103
111
idx = col ;
104
112
if row == db .rows :
@@ -124,7 +132,7 @@ def place(db, tilemap, bels, cst, args):
124
132
pinless_io = False
125
133
try :
126
134
bank = chipdb .loc2bank (db , row - 1 , col - 1 )
127
- iostd = _banks .setdefault (bank , None )
135
+ iostd = _banks .setdefault (bank , BankDesc ( None , True , [])). iostd
128
136
except KeyError :
129
137
if not args .allow_pinless_io :
130
138
raise Exception (f"IO{ edge } { idx } { num } is not allowed for a given package" )
@@ -148,11 +156,19 @@ def place(db, tilemap, bels, cst, args):
148
156
if not iostd :
149
157
iostd = "LVCMOS18"
150
158
if not pinless_io :
151
- _banks [bank ] = iostd
159
+ _banks [bank ].iostd = iostd
160
+ if mode == 'IBUF' :
161
+ _banks [bank ].bels_tiles .append ((iob , tile ))
162
+ else :
163
+ _banks [bank ].inputs_only = False
152
164
153
165
cst .attrs .setdefault (cellname , {}).update ({"IO_TYPE" : iostd })
154
166
# collect flag bits
155
167
bits = iob .iob_flags [iostd ][mode ].encode_bits .copy ()
168
+ # XXX OPEN_DRAIN must be after DRIVE
169
+ attrs_keys = attrs .keys ()
170
+ if 'OPEN_DRAIN=ON' in attrs_keys :
171
+ attrs_keys = itertools .chain (attrs_keys , ['OPEN_DRAIN=ON' ])
156
172
for flag in attrs .keys ():
157
173
flag_name_val = flag .split ("=" )
158
174
if len (flag_name_val ) < 2 :
@@ -161,6 +177,10 @@ def place(db, tilemap, bels, cst, args):
161
177
continue
162
178
if flag_name_val [0 ] == chipdb .mode_attr_sep + "IO_TYPE" :
163
179
continue
180
+ # skip OPEN_DRAIN=OFF can't clear by mask and OFF is the default
181
+ if flag_name_val [0 ] == chipdb .mode_attr_sep + "OPEN_DRAIN" \
182
+ and flag_name_val [1 ] == 'OFF' :
183
+ continue
164
184
# set flag
165
185
mode_desc = iob .iob_flags [iostd ][mode ]
166
186
try :
@@ -191,7 +211,14 @@ def place(db, tilemap, bels, cst, args):
191
211
bits |= bank_bel .bank_flags [iostd ]
192
212
for row , col in bits :
193
213
tile [row ][col ] = 1
194
-
214
+ # If the entire bank has only inputs, the LVCMOS12/15/18 bit is set
215
+ # in each IBUF regardless of the actual I/O standard.
216
+ for _ , bank_desc in _banks .items ():
217
+ if bank_desc .inputs_only :
218
+ if bank_desc .iostd in {'LVCMOS33' , 'LVCMOS25' }:
219
+ for bel , tile in bank_desc .bels_tiles :
220
+ for row , col in bel .lvcmos121518_bits :
221
+ tile [row ][col ] = 1
195
222
196
223
def route (db , tilemap , pips ):
197
224
for row , col , src , dest in pips :
0 commit comments