mirror of https://github.com/openXC7/prjxray.git
Merge pull request #503 from antmicro/propagate-int-ps7
005-tilegrid/generate_full: propagating INT_L base addrs
This commit is contained in:
commit
a24e75d63c
|
|
@ -1,9 +1,11 @@
|
|||
FUZDIR=$(shell pwd)
|
||||
BUILD_DIR=$(FUZDIR)/build
|
||||
TILEGRID_TDB_DEPENDENCIES=iob/build/segbits_tilegrid.tdb mmcm/build/segbits_tilegrid.tdb pll/build/segbits_tilegrid.tdb
|
||||
GENERATE_FULL_ARGS=
|
||||
|
||||
ifeq (${XRAY_DATABASE}, zynq7)
|
||||
TILEGRID_TDB_DEPENDENCIES += ps7_int/build/segbits_tilegrid.tdb
|
||||
GENERATE_FULL_ARGS += --int-tdb $(FUZDIR)/ps7_int/build/segbits_tilegrid.tdb
|
||||
endif
|
||||
|
||||
database: build/tilegrid.json
|
||||
|
|
@ -49,8 +51,7 @@ monitor/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
|
|||
build/tilegrid.json: generate_full.py build/tilegrid_tdb.json build/clb/deltas build/bram/deltas
|
||||
cd build && python3 ${FUZDIR}/generate_full.py \
|
||||
--json-in tilegrid_tdb.json --json-out ${BUILD_DIR}/tilegrid.json \
|
||||
--tiles $(FUZDIR)/build/tiles/tiles.txt clb/design_*.delta bram/design_*.delta
|
||||
|
||||
--tiles $(FUZDIR)/build/tiles/tiles.txt clb/design_*.delta bram/design_*.delta ${GENERATE_FULL_ARGS}
|
||||
run:
|
||||
$(MAKE) clean
|
||||
$(MAKE) database
|
||||
|
|
|
|||
|
|
@ -3,60 +3,7 @@
|
|||
from prjxray import util
|
||||
import json
|
||||
import os
|
||||
|
||||
|
||||
# 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 check_frames(frames):
|
||||
baseaddr = set()
|
||||
for frame in frames:
|
||||
baseaddr.add(frame // 128)
|
||||
assert len(baseaddr) == 1, "Multiple base addresses for the same tag"
|
||||
import util as localutil
|
||||
|
||||
|
||||
def load_db(fn):
|
||||
|
|
@ -67,13 +14,9 @@ def load_db(fn):
|
|||
parts = l.split(' ')
|
||||
tagstr = parts[0]
|
||||
addrlist = parts[1:]
|
||||
frames = list()
|
||||
for addrstr in addrlist:
|
||||
frame, wordidx, bitidx = parse_addr(addrstr)
|
||||
frames.append(frame)
|
||||
check_frames(frames)
|
||||
localutil.check_frames(addrlist)
|
||||
# Take the first address in the list
|
||||
frame, wordidx, bitidx = parse_addr(addrlist[0])
|
||||
frame, wordidx, bitidx = localutil.parse_addr(addrlist[0])
|
||||
|
||||
bitidx_up = False
|
||||
|
||||
|
|
@ -120,8 +63,6 @@ def run(fn_in, fn_out, verbose=False):
|
|||
if os.path.exists("monitor/build/segbits_tilegrid.tdb"):
|
||||
# FIXME: height
|
||||
tdb_fns.append(("monitor/build/segbits_tilegrid.tdb", 30, 101))
|
||||
if os.path.exists("ps7_int/build/segbits_tilegrid.tdb"):
|
||||
tdb_fns.append(("ps7_int/build/segbits_tilegrid.tdb", 36, 2))
|
||||
|
||||
for (tdb_fn, frames, words) in tdb_fns:
|
||||
for (tile, frame, wordidx) in load_db(tdb_fn):
|
||||
|
|
@ -129,7 +70,7 @@ def run(fn_in, fn_out, verbose=False):
|
|||
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)
|
||||
localutil.add_tile_bits(tile, tilej, frame, wordidx, frames, words)
|
||||
|
||||
# Save
|
||||
json.dump(
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ A post processing step verifies that two tiles don't reference the same bitstrea
|
|||
|
||||
from generate import load_tiles
|
||||
from prjxray import util
|
||||
import util as localutil
|
||||
|
||||
|
||||
def nolr(tile_type):
|
||||
|
|
@ -43,10 +44,29 @@ def load_baseaddrs(deltas_fns):
|
|||
return site_baseaddr
|
||||
|
||||
|
||||
def load_tdb_baseaddr(database, int_tdb, verbose=False):
|
||||
tdb_tile_baseaddrs = dict()
|
||||
for line in open(int_tdb, 'r'):
|
||||
line = line.strip()
|
||||
parts = line.split(' ')
|
||||
# INT_L_X0Y50.DWORD:0.DBIT:17.DFRAME:14
|
||||
tagstr = parts[0]
|
||||
# 00000914_000_17 00000918_000_17 ...
|
||||
addrlist = parts[1:]
|
||||
localutil.check_frames(addrlist)
|
||||
frame = localutil.parse_addr(addrlist[0], get_base_frame=True)
|
||||
tparts = tagstr.split('.')
|
||||
# INT_L_X0Y50
|
||||
tile = tparts[0]
|
||||
assert tile in database.keys(), "Tile not in Database"
|
||||
localutil.add_baseaddr(tdb_tile_baseaddrs, tile, frame, verbose)
|
||||
|
||||
return tdb_tile_baseaddrs
|
||||
|
||||
|
||||
def make_tile_baseaddrs(tiles, site_baseaddr, verbose=False):
|
||||
# Look up a base address by tile name
|
||||
tile_baseaddrs = dict()
|
||||
|
||||
verbose and print('')
|
||||
verbose and print('%u tiles' % len(tiles))
|
||||
verbose and print("%u baseaddrs" % len(site_baseaddr))
|
||||
|
|
@ -56,17 +76,8 @@ def make_tile_baseaddrs(tiles, site_baseaddr, verbose=False):
|
|||
if site_name not in site_baseaddr:
|
||||
continue
|
||||
framebaseaddr = site_baseaddr[site_name]
|
||||
bt = util.addr2btype(framebaseaddr)
|
||||
tile_baseaddr = tile_baseaddrs.setdefault(tile["name"], {})
|
||||
if bt in tile_baseaddr:
|
||||
# actually lets just fail these, better to remove at tcl level to speed up processing
|
||||
assert 0, 'duplicate base address'
|
||||
assert tile_baseaddr[bt] == [framebaseaddr, 0]
|
||||
else:
|
||||
tile_baseaddr[bt] = [framebaseaddr, 0]
|
||||
verbose and print(
|
||||
"baseaddr: %s.%s @ %s.0x%08x" %
|
||||
(tile["name"], site_name, bt, framebaseaddr))
|
||||
localutil.add_baseaddr(
|
||||
tile_baseaddrs, tile["name"], framebaseaddr, verbose)
|
||||
added += 1
|
||||
|
||||
assert added, "Failed to add any base addresses"
|
||||
|
|
@ -118,7 +129,7 @@ def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False):
|
|||
grid_x = tile_data["grid_x"]
|
||||
grid_y = tile_data["grid_y"]
|
||||
|
||||
def add_segment(name, tiles, segtype, baseaddr=None):
|
||||
def add_segment(tiles, segtype, name=None, baseaddr=None):
|
||||
assert name not in segments
|
||||
segment = segments.setdefault(name, {})
|
||||
segment["tiles"] = tiles
|
||||
|
|
@ -285,7 +296,6 @@ def create_segment_for_int_lr(
|
|||
adjacent_tile = tiles_by_grid[(grid_x, grid_y)]
|
||||
else:
|
||||
assert False, database[tile]["type"]
|
||||
|
||||
if (database[adjacent_tile]['type'].startswith('INT_INTERFACE_') or
|
||||
database[adjacent_tile]['type'].startswith('PCIE_INT_INTERFACE_')
|
||||
or
|
||||
|
|
@ -408,26 +418,15 @@ def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False):
|
|||
grid_x = database[inttile]["grid_x"]
|
||||
grid_y = database[inttile]["grid_y"]
|
||||
|
||||
for i in range(50):
|
||||
grid_y -= 1
|
||||
loc = (grid_x, grid_y)
|
||||
|
||||
if loc not in tiles_by_grid:
|
||||
continue
|
||||
|
||||
dst_tile = database[tiles_by_grid[loc]]
|
||||
|
||||
if 'segment' not in dst_tile:
|
||||
continue
|
||||
#assert 'segment' in dst_tile, ((grid_x, grid_y), dst_tile, tiles_by_grid[(grid_x, grid_y)])
|
||||
|
||||
if wordbase == 50:
|
||||
wordbase += 1
|
||||
else:
|
||||
wordbase += 2
|
||||
for dst_tile, wordbase in localutil.propagate_up_INT(
|
||||
grid_x, grid_y, database, tiles_by_grid, wordbase):
|
||||
assert 'segment' in dst_tile, (
|
||||
(grid_x, grid_y), dst_tile,
|
||||
tiles_by_grid[(grid_x, grid_y)])
|
||||
|
||||
#verbose and print(' dst_tile', dst_tile)
|
||||
dst_segment_name = dst_tile["segment"]
|
||||
if 'segment' in dst_tile:
|
||||
dst_segment_name = dst_tile["segment"]
|
||||
#verbose and print('up_INT: %s => %s' % (src_segment_name, dst_segment_name))
|
||||
segments[dst_segment_name].setdefault(
|
||||
"baseaddr",
|
||||
|
|
@ -489,43 +488,6 @@ def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False):
|
|||
wordbase)
|
||||
|
||||
|
||||
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 db_add_bits(database, segments):
|
||||
'''Transfer segment data into tiles'''
|
||||
for segment_name in segments.keys():
|
||||
|
|
@ -536,44 +498,9 @@ def db_add_bits(database, segments):
|
|||
offset) in segments[segment_name]["baseaddr"].items():
|
||||
for tile_name in segments[segment_name]["tiles"]:
|
||||
tile_type = database[tile_name]["type"]
|
||||
"""
|
||||
FIXME: review IOB
|
||||
# IOB
|
||||
# design_IOB_X0Y100.delta:+bit_00020027_000_29
|
||||
# design_IOB_X0Y104.delta:+bit_00020027_008_29
|
||||
# design_IOB_X0Y112.delta:+bit_00020027_024_29
|
||||
# design_IOB_X0Y120.delta:+bit_00020027_040_29
|
||||
# design_IOB_X0Y128.delta:+bit_00020027_057_29
|
||||
# design_IOB_X0Y136.delta:+bit_00020027_073_29
|
||||
# design_IOB_X0Y144.delta:+bit_00020027_089_29
|
||||
# $XRAY_BLOCKWIDTH design_IOB_X0Y100.bit |grep 00020000
|
||||
# 0x00020000: 0x2A (42)
|
||||
("RIOI3", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_TBYTESRC", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_TBYTESRC", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_TBYTETERM", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_TBYTETERM", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOB33_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
"""
|
||||
entry = {
|
||||
# (tile_type, block_type): (frames, words, height)
|
||||
("CLBLL", "CLB_IO_CLK"): (36, 2, 2),
|
||||
("CLBLM", "CLB_IO_CLK"): (36, 2, 2),
|
||||
("HCLK", "CLB_IO_CLK"): (26, 1, 1),
|
||||
("INT", "CLB_IO_CLK"): (28, 2, 2),
|
||||
("BRAM", "CLB_IO_CLK"): (28, 10, None),
|
||||
("BRAM", "BLOCK_RAM"): (128, 10, None),
|
||||
("DSP", "CLB_IO_CLK"): (28, 2, 10),
|
||||
("INT_INTERFACE", "CLB_IO_CLK"): (28, 2, None),
|
||||
("BRAM_INT_INTERFACE", "CLB_IO_CLK"): (28, 2, None),
|
||||
}.get((nolr(tile_type), block_type), None)
|
||||
|
||||
entry = localutil.get_entry(nolr(tile_type), block_type)
|
||||
|
||||
if entry is None:
|
||||
# Other types are rare, not expected to have these
|
||||
if block_type == "CLB_IO_CLK":
|
||||
|
|
@ -584,9 +511,9 @@ def db_add_bits(database, segments):
|
|||
if frames:
|
||||
# if we have a width, we should have a height
|
||||
assert frames and words
|
||||
add_tile_bits(
|
||||
database[tile_name], baseaddr, offset, frames, words,
|
||||
height)
|
||||
localutil.add_tile_bits(
|
||||
tile_name, database[tile_name], baseaddr, offset,
|
||||
frames, words, height)
|
||||
|
||||
|
||||
def db_add_segments(database, segments):
|
||||
|
|
@ -600,11 +527,36 @@ def db_add_segments(database, segments):
|
|||
tiledata["segment_type"] = segments[segment]["type"]
|
||||
|
||||
|
||||
def run(json_in_fn, json_out_fn, tiles_fn, deltas_fns, verbose=False):
|
||||
def db_int_fixup(database, tiles, tiles_by_grid):
|
||||
for tile_name in tiles.keys():
|
||||
tiles_to_add = dict()
|
||||
|
||||
tile = database[tile_name]
|
||||
grid_x = tile["grid_x"]
|
||||
grid_y = tile["grid_y"]
|
||||
|
||||
tile_type = tile["type"]
|
||||
|
||||
block_type, (baseaddr, offset) = sorted(tiles[tile_name].items())[0]
|
||||
|
||||
frames, words, height = localutil.get_entry(
|
||||
nolr(tile_type), block_type)
|
||||
# Adding first bottom INT tile
|
||||
localutil.add_tile_bits(
|
||||
tile_name, tile, baseaddr, offset, frames, words, height)
|
||||
|
||||
for tile, offset in localutil.propagate_up_INT(
|
||||
grid_x, grid_y, database, tiles_by_grid, offset):
|
||||
localutil.add_tile_bits(
|
||||
tile_name, tile, baseaddr, offset, frames, words, height)
|
||||
|
||||
|
||||
def run(
|
||||
json_in_fn, json_out_fn, tiles_fn, deltas_fns, int_tdb=None,
|
||||
verbose=False):
|
||||
# Load input files
|
||||
tiles = load_tiles(tiles_fn)
|
||||
site_baseaddr = load_baseaddrs(deltas_fns)
|
||||
|
||||
database = json.load(open(json_in_fn, "r"))
|
||||
|
||||
tile_baseaddrs = make_tile_baseaddrs(tiles, site_baseaddr, verbose=verbose)
|
||||
|
|
@ -620,6 +572,10 @@ def run(json_in_fn, json_out_fn, tiles_fn, deltas_fns, verbose=False):
|
|||
db_add_bits(database, segments)
|
||||
db_add_segments(database, segments)
|
||||
|
||||
if int_tdb is not None:
|
||||
tile_baseaddrs_fixup = load_tdb_baseaddr(database, int_tdb)
|
||||
db_int_fixup(database, tile_baseaddrs_fixup, tiles_by_grid)
|
||||
|
||||
# Save
|
||||
json.dump(
|
||||
database,
|
||||
|
|
@ -647,13 +603,23 @@ def main():
|
|||
'--tiles', default='tiles.txt', help='Input tiles.txt tcl output')
|
||||
parser.add_argument(
|
||||
"deltas", nargs="*", help=".bit diffs to create base addresses from")
|
||||
parser.add_argument(
|
||||
"--int-tdb",
|
||||
default=None,
|
||||
help=".tdb diffs to fill the interconnects without any adjacent CLB")
|
||||
args = parser.parse_args()
|
||||
|
||||
deltas = args.deltas
|
||||
if not args.deltas:
|
||||
deltas = glob.glob("*.delta")
|
||||
|
||||
run(args.json_in, args.json_out, args.tiles, deltas, verbose=args.verbose)
|
||||
run(
|
||||
args.json_in,
|
||||
args.json_out,
|
||||
args.tiles,
|
||||
deltas,
|
||||
args.int_tdb,
|
||||
verbose=args.verbose)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
|
|
@ -0,0 +1,156 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
from prjxray import util
|
||||
'''
|
||||
Local utils script to hold shared code of the 005-tilegrid fuzzer scripts
|
||||
'''
|
||||
|
||||
|
||||
def check_frames(addrlist):
|
||||
frames = set()
|
||||
for addrstr in addrlist:
|
||||
frame = parse_addr(addrstr, get_base_frame=True)
|
||||
frames.add(frame)
|
||||
assert len(frames) == 1, "More than one base address"
|
||||
|
||||
|
||||
def parse_addr(line, only_frame=False, get_base_frame=False):
|
||||
# 00020027_003_03
|
||||
line = line.split("_")
|
||||
frame = int(line[0], 16)
|
||||
wordidx = int(line[1], 10)
|
||||
bitidx = int(line[2], 10)
|
||||
|
||||
if get_base_frame:
|
||||
delta = frame % 128
|
||||
frame -= delta
|
||||
return frame
|
||||
|
||||
return frame, wordidx, bitidx
|
||||
|
||||
|
||||
def propagate_up_INT(grid_x, grid_y, database, tiles_by_grid, wordbase):
|
||||
for i in range(50):
|
||||
grid_y -= 1
|
||||
loc = (grid_x, grid_y)
|
||||
if loc not in tiles_by_grid:
|
||||
continue
|
||||
|
||||
tile = database[tiles_by_grid[loc]]
|
||||
|
||||
if wordbase == 50:
|
||||
wordbase += 1
|
||||
else:
|
||||
wordbase += 2
|
||||
yield tile, wordbase
|
||||
|
||||
|
||||
def add_baseaddr(tile_baseaddrs, tile_name, baseaddr, verbose=False):
|
||||
bt = util.addr2btype(baseaddr)
|
||||
tile_baseaddr = tile_baseaddrs.setdefault(tile_name, {})
|
||||
if bt in tile_baseaddr:
|
||||
# actually lets just fail these, better to remove at tcl level to speed up processing
|
||||
assert 0, 'duplicate base address'
|
||||
assert tile_baseaddr[bt] == [baseaddr, 0]
|
||||
else:
|
||||
tile_baseaddr[bt] = [baseaddr, 0]
|
||||
verbose and print(
|
||||
"baseaddr: %s.%s @ %s.0x%08x" %
|
||||
(tile["name"], site_name, bt, baseaddr))
|
||||
|
||||
|
||||
def get_entry(tile_type, block_type):
|
||||
"""
|
||||
FIXME: review IOB
|
||||
# IOB
|
||||
# design_IOB_X0Y100.delta:+bit_00020027_000_29
|
||||
# design_IOB_X0Y104.delta:+bit_00020027_008_29
|
||||
# design_IOB_X0Y112.delta:+bit_00020027_024_29
|
||||
# design_IOB_X0Y120.delta:+bit_00020027_040_29
|
||||
# design_IOB_X0Y128.delta:+bit_00020027_057_29
|
||||
# design_IOB_X0Y136.delta:+bit_00020027_073_29
|
||||
# design_IOB_X0Y144.delta:+bit_00020027_089_29
|
||||
# $XRAY_BLOCKWIDTH design_IOB_X0Y100.bit |grep 00020000
|
||||
# 0x00020000: 0x2A (42)
|
||||
("RIOI3", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_TBYTESRC", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_TBYTESRC", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOI3_TBYTETERM", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOI3_TBYTETERM", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("RIOB33_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
("LIOB33_SING", "CLB_IO_CLK"): (42, 2, 4),
|
||||
"""
|
||||
return {
|
||||
# (tile_type, block_type): (frames, words, height)
|
||||
("CLBLL", "CLB_IO_CLK"): (36, 2, 2),
|
||||
("CLBLM", "CLB_IO_CLK"): (36, 2, 2),
|
||||
("HCLK", "CLB_IO_CLK"): (26, 1, 1),
|
||||
("INT", "CLB_IO_CLK"): (28, 2, 2),
|
||||
("BRAM", "CLB_IO_CLK"): (28, 10, None),
|
||||
("BRAM", "BLOCK_RAM"): (128, 10, None),
|
||||
("DSP", "CLB_IO_CLK"): (28, 2, 10),
|
||||
("INT_INTERFACE", "CLB_IO_CLK"): (28, 2, None),
|
||||
("BRAM_INT_INTERFACE", "CLB_IO_CLK"): (28, 2, None),
|
||||
}.get((tile_type, block_type), None)
|
||||
|
||||
|
||||
def add_tile_bits(
|
||||
tile_name,
|
||||
tile_db,
|
||||
baseaddr,
|
||||
offset,
|
||||
frames,
|
||||
words,
|
||||
height=None,
|
||||
verbose=False):
|
||||
'''
|
||||
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 offset <= 100, (tile_name, offset)
|
||||
# Few rare cases at X=0 for double width tiles split in half => small negative offset
|
||||
assert offset >= 0 or "IOB" in tile_name, (tile_name, offset)
|
||||
assert 1 <= words <= 101
|
||||
assert offset + words <= 101, (
|
||||
tile_name, offset + words, offset, words, block_type)
|
||||
|
||||
baseaddr_str = '0x%08X' % baseaddr
|
||||
block = bits.get(block_type, None)
|
||||
if block is not None:
|
||||
verbose and print(
|
||||
"%s: existing defintion for %s" % (tile_name, block_type))
|
||||
assert block["baseaddr"] == baseaddr_str
|
||||
assert block["frames"] == frames
|
||||
assert block["offset"] == offset, "%s; orig offset %s, new %s" % (
|
||||
tile_name, block["offset"], offset)
|
||||
assert block["words"] == words
|
||||
return
|
||||
block = bits.setdefault(block_type, {})
|
||||
|
||||
# FDRI address
|
||||
block["baseaddr"] = baseaddr_str
|
||||
# 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
|
||||
Loading…
Reference in New Issue