mirror of https://github.com/openXC7/prjxray.git
Merge pull request #1098 from litghost/add_pin_function_to_tilegrid
Add pin functions to tilegrid.
This commit is contained in:
commit
34db52f8fa
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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__':
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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__':
|
||||
|
|
|
|||
Loading…
Reference in New Issue