Add pin functions to tilegrid.

- Add support to emit PUDC_B pullup if unused (for A7 and Z7 fabrics).

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2019-10-14 16:38:02 -07:00
parent 0dec230397
commit c0b8aef3a9
7 changed files with 121 additions and 8 deletions

View File

@ -49,6 +49,7 @@ build/basicdb/tilegrid.json: generate.py build/tiles/tiles.txt
mkdir -p build/basicdb
cd build && python3 ${FUZDIR}/generate.py \
--tiles $(FUZDIR)/build/tiles/tiles.txt \
--pin_func $(FUZDIR)/build/tiles/pin_func.txt \
--out ${BUILD_DIR}/basicdb/tilegrid.json
clb/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json

View File

@ -32,7 +32,19 @@ def load_tiles(tiles_fn):
return tiles
def make_database(tiles):
def load_pin_functions(pin_func_fn):
pin_functions = {}
with open(pin_func_fn) as f:
for line in f:
site, pin_func = line.split()
assert site not in pin_functions, site
pin_functions[site] = pin_func
return pin_functions
def make_database(tiles, pin_func):
# tile database with X, Y, and list of sites
# tile name as keys
database = dict()
@ -44,17 +56,25 @@ def make_database(tiles):
"grid_x": tile["grid_x"],
"grid_y": tile["grid_y"],
"bits": {},
"pin_functions": {},
}
for site in database[tile["name"]]["sites"]:
if site in pin_func:
database[tile["name"]]["pin_functions"][site] = pin_func[site]
return database
def run(tiles_fn, json_fn, verbose=False):
def run(tiles_fn, pin_func_fn, json_fn, verbose=False):
# Load input files
tiles = load_tiles(tiles_fn)
# Read site map
pin_func = load_pin_functions(pin_func_fn)
# Index input
database = make_database(tiles)
database = make_database(tiles, pin_func)
# Save
xjson.pprint(open(json_fn, 'w'), database)
@ -69,10 +89,15 @@ def main():
parser.add_argument('--verbose', action='store_true', help='')
parser.add_argument('--out', default='/dev/stdout', help='Output JSON')
parser.add_argument(
'--tiles', default='tiles.txt', help='Input tiles.txt tcl output')
'--tiles',
default='tiles.txt',
help='Input tiles.txt tcl output',
required=True)
parser.add_argument(
'--pin_func', help='List of sites with pin functions', required=True)
args = parser.parse_args()
run(args.tiles, args.out, verbose=args.verbose)
run(args.tiles, args.pin_func, args.out, verbose=args.verbose)
if __name__ == '__main__':

View File

@ -6,6 +6,7 @@ proc write_tiles_txt {} {
# Write tiles.txt with site metadata
set fp [open "tiles.txt" w]
set fp_pin [open "pin_func.txt" w]
foreach tile $tiles {
set type [get_property TYPE $tile]
set grid_x [get_property GRID_POINT_X $tile]
@ -17,11 +18,17 @@ proc write_tiles_txt {} {
set site_types [get_property SITE_TYPE $sites]
foreach t $site_types s $sites {
lappend typed_sites $t $s
set package_pin [get_package_pins -of $s -quiet]
if [llength $package_pin] {
puts $fp_pin "$s [get_property PIN_FUNC $package_pin]"
}
}
}
puts $fp "$type $tile $grid_x $grid_y $typed_sites"
}
close $fp_pin
close $fp
}

View File

@ -27,6 +27,11 @@ class FasmAssembler(object):
self.frames = {}
self.frames_line = {}
self.feature_callback = lambda feature: None
def set_feature_callback(self, feature_callback):
self.feature_callback = feature_callback
def get_frames(self, sparse=False):
if not sparse:
frames = self.frames_init()
@ -138,6 +143,8 @@ class FasmAssembler(object):
if not line.set_feature:
return
self.feature_callback(line.set_feature)
line_strs = tuple(fasm.fasm_line_to_string(line))
assert len(line_strs) == 1
line_str = line_strs[0]

View File

@ -50,6 +50,7 @@ class Grid(object):
bits=bits,
sites=tileinfo['sites'],
tile_type=tileinfo['type'],
pin_functions=tileinfo.get('pin_functions', {}),
)
x, y = zip(*self.loc.keys())

View File

@ -11,7 +11,7 @@ class BlockType(enum.Enum):
GridLoc = namedtuple('GridLoc', 'grid_x grid_y')
GridInfo = namedtuple('GridInfo', 'bits sites tile_type')
GridInfo = namedtuple('GridInfo', 'bits sites tile_type pin_functions')
BitAlias = namedtuple('BitAlias', 'tile_type start_offset sites')
Bits = namedtuple('Bits', 'base_address frames offset words alias')
BitsInfo = namedtuple('BitsInfo', 'block_type tile bits')

View File

@ -54,10 +54,56 @@ def dump_frm(f, frames):
'0x%08X ' % addr + ','.join(['0x%08X' % w for w in words]) + '\n')
def run(db_root, filename_in, f_out, sparse=False, roi=None, debug=False):
def find_pudc_b(db):
""" Find PUDC_B pin func in grid, and return the tile and site prefix.
The PUDC_B pin is a special 7-series pin that controls unused pin pullup.
If the PUDC_B is unused, it is configured as an input with a PULLUP.
"""
grid = db.grid()
pudc_b_tile_site = None
for tile in grid.tiles():
gridinfo = grid.gridinfo_at_tilename(tile)
for site, pin_function in gridinfo.pin_functions.items():
if 'PUDC_B' in pin_function:
assert pudc_b_tile_site == None, (
pudc_b_tile_site, (tile, site))
iob_y = int(site[-1]) % 2
pudc_b_tile_site = (tile, 'IOB_Y{}'.format(iob_y))
return pudc_b_tile_site
def run(
db_root,
filename_in,
f_out,
sparse=False,
roi=None,
debug=False,
emit_pudc_b_pullup=False):
db = Database(db_root)
assembler = fasm_assembler.FasmAssembler(db)
if emit_pudc_b_pullup:
pudc_b_in_use = False
pudc_b_tile_site = find_pudc_b(db)
def check_for_pudc_b(set_feature):
parts = set_feature.feature.split('.')
if parts[0] == pudc_b_tile_site[0] and parts[
1] == pudc_b_tile_site[1]:
nonlocal pudc_b_in_use
pudc_b_in_use = True
assembler.set_feature_callback(check_for_pudc_b)
extra_features = []
if roi:
with open(roi) as f:
@ -74,6 +120,27 @@ def run(db_root, filename_in, f_out, sparse=False, roi=None, debug=False):
'\n'.join(roi_j['required_features']))
assembler.parse_fasm_filename(filename_in, extra_features=extra_features)
if emit_pudc_b_pullup and not pudc_b_in_use:
# Enable IN-only and PULLUP on PUDC_B IOB.
#
# TODO: The following FASM string only works on Artix 50T and Zynq 10
# fabrics. It is known to be wrong for the K70T fabric, but it is
# unclear how to know which IOSTANDARD to use.
missing_features = []
for line in fasm.parse_fasm_string("""
{tile}.{site}.LVCMOS12_LVCMOS15_LVCMOS18_LVCMOS25_LVCMOS33_LVTTL_SSTL135.IN_ONLY
{tile}.{site}.LVCMOS25_LVCMOS33_LVTTL.IN
{tile}.{site}.PULLTYPE.PULLUP
""".format(
tile=pudc_b_tile_site[0],
site=pudc_b_tile_site[1],
)):
assembler.add_fasm_line(line, missing_features)
if missing_features:
raise fasm_assembler.FasmLookupError('\n'.join(missing_features))
frames = assembler.get_frames(sparse=sparse)
if debug:
@ -103,6 +170,10 @@ def main():
parser.add_argument(
'--roi',
help="ROI design.json file defining which tiles are within the ROI.")
parser.add_argument(
'--emit_pudc_b_pullup',
help="Emit an IBUF and PULLUP on the PUDC_B pin if unused",
action='store_true')
parser.add_argument(
'--debug', action='store_true', help="Print debug dump")
parser.add_argument('fn_in', help='Input FPGA assembly (.fasm) file')
@ -119,7 +190,8 @@ def main():
f_out=open(args.fn_out, 'w'),
sparse=args.sparse,
roi=args.roi,
debug=args.debug)
debug=args.debug,
emit_pudc_b_pullup=args.emit_pudc_b_pullup)
if __name__ == '__main__':