prjxray/fuzzers/005-tilegrid/add_tdb.py

136 lines
4.0 KiB
Python

#!/usr/bin/env python3
from prjxray import util
import json
# Copied from generate_full.py
def add_tile_bits(tile_db, baseaddr, offset, frames, words, height=None):
'''
Record data structure geometry for the given tile baseaddr
For most tiles there is only one baseaddr, but some like BRAM have multiple
Notes on multiple block types:
https://github.com/SymbiFlow/prjxray/issues/145
'''
bits = tile_db['bits']
block_type = util.addr2btype(baseaddr)
assert 0 <= offset <= 100, offset
assert 1 <= words <= 101
assert offset + words <= 101, (
tile_db, offset + words, offset, words, block_type)
assert block_type not in bits
block = bits.setdefault(block_type, {})
# FDRI address
block["baseaddr"] = '0x%08X' % baseaddr
# Number of frames this entry is sretched across
# that is the following FDRI addresses are used: range(baseaddr, baseaddr + frames)
block["frames"] = frames
# Index of first word used within each frame
block["offset"] = offset
# related to words...
# deprecated field? Don't worry about for now
# DSP has some differences between height and words
block["words"] = words
if height is None:
height = words
block["height"] = height
def parse_addr(line):
# 00020027_003_03
line = line.split("_")
frame = int(line[0], 16)
wordidx = int(line[1], 10)
bitidx = int(line[2], 10)
return frame, wordidx, bitidx
def load_db(fn):
for l in open(fn, "r"):
l = l.strip()
# FIXME: add offset to name
# IOB_X0Y101.DFRAME:27.DWORD:3.DBIT:3 00020027_003_03
parts = l.split(' ')
assert len(parts) == 2, "Unresolved bit: %s" % l
tagstr, addrstr = parts
frame, wordidx, bitidx = parse_addr(addrstr)
bitidx_up = False
tparts = tagstr.split('.')
tile = tparts[0]
for part in tparts[1:]:
k, v = part.split(':')
if k == "DFRAME":
frame -= int(v, 16)
elif k == "DWORD":
wordidx -= int(v, 10)
elif k == "DBIT":
bitidx -= int(v, 10)
bitidx_up = True
else:
assert 0, (l, part)
# XXX: maybe just ignore bitidx and always set to 0 instead of allowing explicit
# or detect the first delta auto and assert they are all the same
if not bitidx_up:
bitidx = 0
assert bitidx == 0, l
assert frame % 0x80 == 0, "Unaligned frame at 0x%08X" % frame
yield (tile, frame, wordidx)
def run(fn_in, fn_out, verbose=False):
database = json.load(open(fn_in, "r"))
# Load a map of sites to base addresses
# Need to figure out the
# FIXME: generate frames from part file (or equivilent)
# See https://github.com/SymbiFlow/prjxray/issues/327
# FIXME: generate words from pitch
tdb_fns = [
("iob/build/segbits_tilegrid.tdb", 42, 4),
# FIXME: height
("mmcm/build/segbits_tilegrid.tdb", 30, 101),
# FIXME: height
("pll/build/segbits_tilegrid.tdb", 30, 101),
]
for (tdb_fn, frames, words) in tdb_fns:
for (tile, frame, wordidx) in load_db(tdb_fn):
tilej = database[tile]
bitsj = tilej['bits']
bt = util.addr2btype(frame)
verbose and print("Add %s %08X_%03u" % (tile, frame, wordidx))
add_tile_bits(tilej, frame, wordidx, frames, words)
# Save
json.dump(
database,
open(fn_out, "w"),
sort_keys=True,
indent=4,
separators=(",", ": "))
def main():
import argparse
parser = argparse.ArgumentParser(
description="Annotate tilegrid addresses using solved base addresses")
parser.add_argument("--verbose", action="store_true", help="")
parser.add_argument("--fn-in", required=True, help="")
parser.add_argument("--fn-out", required=True, help="")
args = parser.parse_args()
run(args.fn_in, args.fn_out, verbose=args.verbose)
if __name__ == "__main__":
main()