22import os
33import re
44import pickle
5+ import itertools
56import numpy as np
67import json
78import argparse
@@ -60,6 +61,13 @@ def infovaluemap(infovalue, start=2):
6061 "SSTL33_II" : "SSTL33_I" ,
6162 "LVTTL33" : "LVCMOS33" ,
6263 }
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+
6371_banks = {}
6472_sides = "AB"
6573def place (db , tilemap , bels , cst , args ):
@@ -98,7 +106,7 @@ def place(db, tilemap, bels, cst, args):
98106 # XXX skip power
99107 if not cellname .startswith ('\$PACKER' ):
100108 cst .cells [cellname ] = (row , col , int (num ) // 2 , _sides [int (num ) % 2 ])
101- elif typ == "IOB" :
109+ elif typ [: 3 ] == "IOB" :
102110 edge = 'T'
103111 idx = col ;
104112 if row == db .rows :
@@ -124,7 +132,7 @@ def place(db, tilemap, bels, cst, args):
124132 pinless_io = False
125133 try :
126134 bank = chipdb .loc2bank (db , row - 1 , col - 1 )
127- iostd = _banks .setdefault (bank , None )
135+ iostd = _banks .setdefault (bank , BankDesc ( None , True , [])). iostd
128136 except KeyError :
129137 if not args .allow_pinless_io :
130138 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):
148156 if not iostd :
149157 iostd = "LVCMOS18"
150158 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
152164
153165 cst .attrs .setdefault (cellname , {}).update ({"IO_TYPE" : iostd })
154166 # collect flag bits
155167 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' ])
156172 for flag in attrs .keys ():
157173 flag_name_val = flag .split ("=" )
158174 if len (flag_name_val ) < 2 :
@@ -161,6 +177,10 @@ def place(db, tilemap, bels, cst, args):
161177 continue
162178 if flag_name_val [0 ] == chipdb .mode_attr_sep + "IO_TYPE" :
163179 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
164184 # set flag
165185 mode_desc = iob .iob_flags [iostd ][mode ]
166186 try :
@@ -191,7 +211,14 @@ def place(db, tilemap, bels, cst, args):
191211 bits |= bank_bel .bank_flags [iostd ]
192212 for row , col in bits :
193213 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
195222
196223def route (db , tilemap , pips ):
197224 for row , col , src , dest in pips :
0 commit comments