Add back INT propagation.

All INT tiles are now populated for artix7 and the INT propagation
sanity checks output of fuzzers to ensure consistency.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2019-01-27 16:17:31 -08:00
parent 3a4fc5eedc
commit da08dfb99f
8 changed files with 152 additions and 312 deletions

View File

@ -13,6 +13,7 @@ TILEGRID_TDB_DEPENDENCIES += clb/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += clb_int/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += dsp/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += dsp_int/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += fifo_int/build/segbits_tilegrid.tdb
GENERATE_FULL_ARGS=
ifeq (${XRAY_DATABASE}, zynq7)
@ -73,6 +74,9 @@ dsp/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
dsp_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd dsp_int && $(MAKE)
fifo_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd fifo_int && $(MAKE)
build/tilegrid_tdb.json: add_tdb.py $(TILEGRID_TDB_DEPENDENCIES)
python3 add_tdb.py \
--fn-in build/basicdb/tilegrid.json \
@ -102,6 +106,7 @@ clean:
cd bram_int && $(MAKE) clean
cd dsp && $(MAKE) clean
cd dsp_int && $(MAKE) clean
cd fifo_int && $(MAKE) clean
cd monitor && $(MAKE) clean
.PHONY: database pushdb clean run

View File

@ -66,6 +66,7 @@ def run(fn_in, fn_out, verbose=False):
("iob_int/build/segbits_tilegrid.tdb", int_frames, int_words),
("bram_int/build/segbits_tilegrid.tdb", int_frames, int_words),
("dsp_int/build/segbits_tilegrid.tdb", int_frames, int_words),
("fifo_int/build/segbits_tilegrid.tdb", int_frames, int_words),
]
for (tdb_fn, frames, words) in tdb_fns:

View File

@ -1,4 +1,4 @@
N ?= 16
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 1 --dframe 15"
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 0 --dframe 15"
include ../fuzzaddr/common.mk

View File

@ -23,15 +23,14 @@ def gen_fifos():
int_tile_type = 'INT_R'
int_tile_locs = [
(int_grid_x, loc.grid_y+idx-5) for idx in range(12)
]
(int_grid_x, loc.grid_y + idx - 5) for idx in range(12)
]
int_tiles = []
for int_tile_loc in int_tile_locs:
int_gridinfo = grid.gridinfo_at_loc(int_tile_loc)
assert int_gridinfo.tile_type == int_tile_type, (
int_tile_loc,
int_gridinfo.tile_type, int_tile_type)
int_tile_loc, int_gridinfo.tile_type, int_tile_type)
int_tiles.append(grid.tilename_at_loc(int_tile_loc))
@ -68,11 +67,11 @@ module top();
#
# INT[idx].IMUX_L40 = IN.D{idx}[1]
# INT[idx].IMUX_L42 = IN.D{idx}[3]
CHANNEL = [0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9]
CHANNEL = [0, 1, 2, 3, 4, 5, 5, 6, 6, 7, 8, 9]
HOLD_BIT_0 = [1, 1, 1, 1, 1, 1, 5, 5, 1, 1, 1, 1]
TOGGLE_BIT = [3, 3, 3, 3, 3, 3, 7, 7, 3, 3, 3, 3]
# 0 1 2 3 4 5 6 7 8 9
WIDTH = [4, 4, 4, 4, 4, 8, 8, 4, 4, 4]
WIDTH = [4, 4, 4, 4, 4, 8, 8, 4, 4, 4]
bits_set = set()
@ -81,29 +80,33 @@ module top();
bits_set.add((CHANNEL[idx], TOGGLE_BIT[idx]))
assigns.append(' // {}'.format(int_tile))
assigns.append(' assign {site}_in_d{channel}[{bit}] = 0;'.format(
site=site,
channel=CHANNEL[idx],
bit=HOLD_BIT_0[idx],
assigns.append(
' assign {site}_in_d{channel}[{bit}] = 0;'.format(
site=site,
channel=CHANNEL[idx],
bit=HOLD_BIT_0[idx],
))
assigns.append(' assign {site}_in_d{channel}[{bit}] = {toggle_bit};'.format(
site=site,
channel=CHANNEL[idx],
bit=TOGGLE_BIT[idx],
toggle_bit=bit,
assigns.append(
' assign {site}_in_d{channel}[{bit}] = {toggle_bit};'
.format(
site=site,
channel=CHANNEL[idx],
bit=TOGGLE_BIT[idx],
toggle_bit=bit,
))
params[int_tile] = (bit,)
params[int_tile] = (bit, )
assigns.append('')
for channel, width in enumerate(WIDTH):
for bit in range(width):
if (channel, bit) not in bits_set:
assigns.append(' assign {site}_in_d{channel}[{bit}] = 1;'.format(
site=site,
channel=channel,
bit=bit,
assigns.append(
' assign {site}_in_d{channel}[{bit}] = 1;'.
format(
site=site,
channel=channel,
bit=bit,
))
print(

View File

@ -1,6 +1,6 @@
#!/usr/bin/env python3
from __future__ import print_function
import sys, json
import json
from utils import xjson
'''
Historically we grouped data into "segments"
@ -12,7 +12,6 @@ Decoding was then shifted to instead describe how each title is encoded
A post processing step verifies that two tiles don't reference the same bitstream area
'''
from generate import load_tiles
import util as localutil
@ -60,109 +59,10 @@ def make_tiles_by_grid(database):
return tiles_by_grid
def add_int_bits(database, tile, baseaddr, offset):
"""
Add INT bits for given tile.
"""
if database[tile]['type'] not in ["INT_L", "INT_R"]:
return
localutil.add_tile_bits(
tile, database[tile], baseaddr, offset, frames=28, words=2, height=2)
def add_adjacent_int_tiles(database, tiles_by_grid, verbose=False):
'''
Attaches INT tiles adjacent to tiles.
'''
def add_int_tile(inttile, parent_tile):
if not database[parent_tile]['bits']:
return
grid_x = database[inttile]["grid_x"]
grid_y = database[inttile]["grid_y"]
framebase = int(
database[parent_tile]['bits']['CLB_IO_CLK']['baseaddr'], 0)
parent_wordbase = database[parent_tile]['bits']['CLB_IO_CLK']['offset']
for dst_tile, wordbase in localutil.propagate_up_INT(
grid_x, grid_y, database, tiles_by_grid, parent_wordbase):
dst_x = dst_tile['grid_x']
dst_y = dst_tile['grid_y']
add_int_bits(
database, tiles_by_grid[(dst_x, dst_y)], framebase, wordbase)
verbose and print('')
for tile_name, tile_data in database.items():
tile_type = tile_data["type"]
grid_x = tile_data["grid_x"]
grid_y = tile_data["grid_y"]
def process_clb():
if tile_type in ["CLBLL_L", "CLBLM_L"]:
int_tile_name = tiles_by_grid[(grid_x + 1, grid_y)]
else:
int_tile_name = tiles_by_grid[(grid_x - 1, grid_y)]
add_int_tile(int_tile_name, tile_name)
def process_iob():
if tile_type.startswith('LIOB'):
# Two INT_L's
#add_int_tile(tiles_by_grid[(grid_x + 4, grid_y)], tile_name)
#add_int_tile(tiles_by_grid[(grid_x + 4, grid_y - 1)], tile_name)
pass
else:
# Two INT_R's
#add_int_tile(tiles_by_grid[(grid_x - 4, grid_y)], tile_name)
#add_int_tile(tiles_by_grid[(grid_x - 4, grid_y - 1)], tile_name)
pass
def process_iob_sing():
if tile_type.startswith('LIOB'):
add_int_tile(tiles_by_grid[(grid_x + 4, grid_y)], tile_name)
else:
add_int_tile(tiles_by_grid[(grid_x - 4, grid_y)], tile_name)
def process_bram_dsp():
for k in range(5):
if tile_type in ["BRAM_L", "DSP_L"]:
int_tile_name = tiles_by_grid[(grid_x + 2, grid_y - k)]
elif tile_type in ["BRAM_R", "DSP_R"]:
int_tile_name = tiles_by_grid[(grid_x - 2, grid_y - k)]
else:
assert 0
add_int_tile(int_tile_name, tile_name)
def process_default():
verbose and nolr(tile_type) not in (
'VBRK', 'INT', 'NULL') and print(
'make_segment: drop %s' % (tile_type, ))
pass
{
"CLBLL": process_clb,
"CLBLM": process_clb,
"HCLK": lambda: None,
"BRAM": lambda: None,
"DSP": lambda: None,
"RIOB33": process_iob,
"LIOB33": process_iob,
"RIOB33_SING": process_iob_sing,
"LIOB33_SING": process_iob_sing,
}.get(nolr(tile_type), process_default)()
def seg_base_addr_lr_INT(database, tiles_by_grid, verbose=False):
def propagate_INT_lr_bits(database, tiles_by_grid, verbose=False):
'''Populate segment base addresses: L/R along INT column'''
'''
Create BRAM base addresses based on nearby CLBs
ie if we have a BRAM_L, compute as nearby CLB_R base address + offset
'''
int_frames, int_words, _ = localutil.get_entry('INT', 'CLB_IO_CLK')
verbose and print('')
for tile in database:
@ -174,17 +74,17 @@ def seg_base_addr_lr_INT(database, tiles_by_grid, verbose=False):
grid_x = database[tile]["grid_x"]
grid_y = database[tile]["grid_y"]
framebase = int(database[tile]["bits"]["CLB_IO_CLK"]["baseaddr"], 0)
wordbase = database[tile]["bits"]["CLB_IO_CLK"]["offset"]
baseaddr = int(database[tile]["bits"]["CLB_IO_CLK"]["baseaddr"], 0)
offset = database[tile]["bits"]["CLB_IO_CLK"]["offset"]
if database[tile]["type"] == "INT_L":
grid_x += 1
framebase = framebase + 0x80
baseaddr = baseaddr + 0x80
elif database[tile]["type"] == "INT_R":
grid_x -= 1
framebase = framebase - 0x80
baseaddr = baseaddr - 0x80
else:
assert 0
assert 0, database[tile]["type"]
# ROI at edge?
if (grid_x, grid_y) not in tiles_by_grid:
@ -200,203 +100,125 @@ def seg_base_addr_lr_INT(database, tiles_by_grid, verbose=False):
else:
assert 0
add_int_bits(database, other_tile, framebase, wordbase)
localutil.add_tile_bits(
other_tile, database[other_tile], baseaddr, offset,
int_frames, int_words)
def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False):
'''Populate segment base addresses: Up along INT/HCLK columns'''
def propagate_INT_bits_in_column(database, tiles_by_grid):
""" Propigate INT offsets up and down INT columns.
verbose and print('')
# Copy the initial list containing only base addresses
# and soon to have derived addresses
src_segment_names = list()
for segment_name in segments.keys():
if "baseaddr" in segments[segment_name]:
src_segment_names.append(segment_name)
verbose and print('up_INT: %u base addresses' % len(src_segment_names))
for src_segment_name in sorted(src_segment_names):
src_segment = segments[src_segment_name]
for block_type, (framebase,
wordbase) in sorted(src_segment["baseaddr"].items()):
verbose and print(
'up_INT: %s: %s.0x%08X:%u' %
(src_segment_name, block_type, framebase, wordbase))
def process_CLB_IO_CLK(wordbase):
'''
Lookup interconnect tile associated with this segment
Use it to locate in the grid, and find other segments related by tile offset
'''
for inttile in list(get_inttile(database, src_segment)) + list(
get_iobtile(database, src_segment)):
verbose and print(
' up_INT CLB_IO_CLK: %s => inttile %s' %
(src_segment_name, inttile),
file=sys.stderr)
grid_x = database[inttile]["grid_x"]
grid_y = database[inttile]["grid_y"]
for dst_tile, wordbase in localutil.propagate_up_INT(
grid_x, grid_y, database, tiles_by_grid, wordbase):
if 'segment' not in dst_tile:
print(
'WARNING: Missing segment for {} ({}, {}) {}'.
format(
tiles_by_grid[(grid_x, grid_y)], grid_x,
grid_y, dst_tile))
continue
#verbose and print(' dst_tile', dst_tile)
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",
{})[block_type] = [framebase, wordbase]
def process_BLOCK_RAM(wordbase):
'''
Lookup BRAM0 tile associated with this segment
Use it to locate in the grid, and find other BRAM0 related by tile offset
From minitest:
build/roi_bramd_bit01.diff (lowest BRAM coordinate)
> bit_00c00000_000_00
build/roi_bramds_bit01.diff
> bit_00c00000_000_00
> bit_00c00000_010_00
> bit_00c00000_020_00
> bit_00c00000_030_00
> bit_00c00000_040_00
> bit_00c00000_051_00
> bit_00c00000_061_00
> bit_00c00000_071_00
> bit_00c00000_081_00
> bit_00c00000_091_00
'''
src_tile_name = get_bramtile(database, src_segment)
verbose and print(
' up_INT BLOCK_RAM: %s => %s' %
(src_segment_name, src_tile_name))
grid_x = database[src_tile_name]["grid_x"]
grid_y = database[src_tile_name]["grid_y"]
for i in range(9):
grid_y -= 5
wordbase += 10
# Skip HCLK
if i == 4:
grid_y -= 1
wordbase += 1
# FIXME: PCIE block cuts out some BRAM
# this messes up algorithm as is and may cause this to fail
if grid_y < 0:
continue
dst_tile_name = tiles_by_grid[(grid_x, grid_y)]
dst_tile = database[dst_tile_name]
assert nolr(dst_tile['type']) == 'BRAM', dst_tile
dst_segment_name = dst_tile["segment"]
verbose and print(
' up_INT BLOCK_RAM: %s => %s' %
(dst_segment_name, dst_tile_name))
assert 'BRAM0' in dst_segment_name
segments[dst_segment_name].setdefault(
"baseaddr", {})[block_type] = [framebase, wordbase]
{
'CLB_IO_CLK': process_CLB_IO_CLK,
'BLOCK_RAM': process_BLOCK_RAM,
}[block_type](
wordbase)
def db_add_bits(database, segments):
'''Transfer segment data into tiles'''
for segment_name in segments.keys():
if 'baseaddr' not in segments[segment_name]:
continue
for block_type, (baseaddr,
offset) in segments[segment_name]["baseaddr"].items():
for tile_name in segments[segment_name]["tiles"]:
tile_type = database[tile_name]["type"]
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":
raise ValueError("Unknown tile type %s" % tile_type)
continue
frames, words, height = entry
if frames:
# if we have a width, we should have a height
assert frames and words
localutil.add_tile_bits(
tile_name, database[tile_name], baseaddr, offset,
frames, words, height)
def add_hclk_bits(database, tiles_by_grid):
""" Propigate HCLK baseaddr and wordbase from INT tiles above and below.
HCLK tiles are located between two INT tiles. The offset seperate between
these two tiles should be 3. The HCLK tile has an offset of 2 from the
lower INT offset and an offset of 1 from the upper INT offset.
INT columns appear to be fairly regular, where starting from offset 0,
INT tiles next to INT tiles increase the word offset by 2. The HCLK tile
is surrounded above and sometimes below by an INT tile. Because the HCLK
tile only useds one word, the offset increase by one at the HCLK.
"""
_, int_words, _ = localutil.get_entry('INT', 'CLB_IO_CLK')
seen_int = set()
int_frames, int_words, _ = localutil.get_entry('INT', 'CLB_IO_CLK')
hclk_frames, hclk_words, _ = localutil.get_entry('HCLK', 'CLB_IO_CLK')
for tile_name in sorted(database.keys()):
tile = database[tile_name]
if tile['type'] not in ['HCLK_L', 'HCLK_R']:
if tile['type'] not in ['INT_L', 'INT_R']:
continue
tile_below = tiles_by_grid[(tile['grid_x'], tile['grid_y'] + 1)]
tile_above = tiles_by_grid[(tile['grid_x'], tile['grid_y'] - 1)]
l_or_r = tile['type'][-1]
expected_tile_type = 'INT_{}'.format(tile['type'][-1])
assert database[tile_below]['type'] == expected_tile_type, (
tile_name, tile_below)
assert database[tile_above]['type'] == expected_tile_type, (
tile_name, tile_above)
if not database[tile_below]['bits']:
continue
if not database[tile_above]['bits']:
if not tile['bits']:
continue
bits_below = database[tile_below]['bits']['CLB_IO_CLK']
bits_above = database[tile_above]['bits']['CLB_IO_CLK']
if tile_name in seen_int:
continue
assert bits_below['baseaddr'] == bits_above['baseaddr'], (
tile_name, bits_below['baseaddr'], bits_above['baseaddr'])
# Walk down INT column
while True:
seen_int.add(tile_name)
offset_below = bits_below['offset']
offset_above = bits_above['offset']
next_tile = tiles_by_grid[(tile['grid_x'], tile['grid_y'] + 1)]
next_tile_type = database[next_tile]['type']
assert offset_above - offset_below == (int_words + hclk_words), (
tile_name, offset_below, offset_above, int_words + hclk_words)
if tile['bits']['CLB_IO_CLK']['offset'] == 0:
assert next_tile_type in ['B_TERM_INT', 'BRKH_INT', 'BRKH_B_TERM_INT'], next_tile_type
break
localutil.add_tile_bits(
tile_name,
database[tile_name],
baseaddr=int(bits_below['baseaddr'], 0),
offset=offset_below + int_words,
frames=hclk_frames,
words=hclk_words)
baseaddr = int(tile['bits']['CLB_IO_CLK']['baseaddr'], 0)
offset = tile['bits']['CLB_IO_CLK']['offset']
if tile['type'].startswith('INT_') and next_tile_type == tile['type']:
# INT next to INT
offset -= int_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
int_frames, int_words)
elif tile['type'].startswith('INT_'):
# INT above HCLK
assert next_tile_type.startswith('HCLK_{}'.format(l_or_r)), next_tile_type
offset -= hclk_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
hclk_frames, hclk_words)
else:
# HCLK above INT
assert tile['type'].startswith('HCLK_{}'.format(l_or_r)), tile['type']
if next_tile_type == 'INT_{}'.format(l_or_r):
offset -= int_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
int_frames, int_words)
else:
# Handle special case column where the PCIE tile is present.
assert next_tile_type in ['PCIE_NULL'], next_tile_type
break
tile_name = next_tile
tile = database[tile_name]
# Walk up INT column
while True:
seen_int.add(tile_name)
next_tile = tiles_by_grid[(tile['grid_x'], tile['grid_y'] - 1)]
next_tile_type = database[next_tile]['type']
if tile['bits']['CLB_IO_CLK']['offset'] == 99:
assert next_tile_type in ['T_TERM_INT', 'BRKH_INT', 'BRKH_TERM_INT'], next_tile_type
break
baseaddr = int(tile['bits']['CLB_IO_CLK']['baseaddr'], 0)
offset = tile['bits']['CLB_IO_CLK']['offset']
if tile['type'].startswith('INT_') and next_tile_type == tile['type']:
# INT next to INT
offset += int_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
int_frames, int_words)
elif tile['type'].startswith('INT_'):
# INT below HCLK
assert next_tile_type.startswith('HCLK_{}'.format(l_or_r)), next_tile_type
offset += int_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
hclk_frames, hclk_words)
else:
# HCLK below INT
assert tile['type'].startswith('HCLK_{}'.format(l_or_r)), tile['type']
assert next_tile_type == 'INT_{}'.format(l_or_r), next_tile_type
offset += hclk_words
localutil.add_tile_bits(
next_tile, database[next_tile], baseaddr, offset,
int_frames, int_words)
tile_name = next_tile
tile = database[tile_name]
def run(json_in_fn, json_out_fn, int_tdb=None, verbose=False):
@ -404,7 +226,8 @@ def run(json_in_fn, json_out_fn, int_tdb=None, verbose=False):
database = json.load(open(json_in_fn, "r"))
tiles_by_grid = make_tiles_by_grid(database)
add_hclk_bits(database, tiles_by_grid)
propagate_INT_lr_bits(database, tiles_by_grid, verbose=verbose)
propagate_INT_bits_in_column(database, tiles_by_grid)
# Save
xjson.pprint(open(json_out_fn, "w"), database)

View File

@ -49,7 +49,6 @@ proc loc_pins {} {
set tile [get_tiles -of_objects $site]
set pin [dict get $io_pin_sites $site]
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port
}
}

View File

@ -8,6 +8,7 @@ import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
import re
def gen_sites():
@ -31,7 +32,9 @@ def gen_sites():
if len(sites) == 0:
continue
sites.sort()
sites_y = [int(re.match('IDELAY_X[0-9]+Y([0-9]+)', site).group(1)) for site in sites]
sites, _ = zip(*sorted(zip(sites, sites_y), key=lambda x: x[1]))
if gridinfo.tile_type[0] == 'L':
int_grid_x = loc.grid_x + 3
@ -47,7 +50,10 @@ def gen_sites():
]
pad_gridinfo = grid.gridinfo_at_loc((pad_grid_x, loc.grid_y))
pad_sites = sorted(pad_gridinfo.sites.keys())
pad_sites = pad_gridinfo.sites.keys()
pad_sites_y = [int(re.match('IOB_X[0-9]+Y([0-9]+)', site).group(1)) for site in pad_sites]
pad_sites, _ = zip(*sorted(zip(pad_sites, pad_sites_y), key=lambda x: x[1]))
if not gridinfo.tile_type.endswith("_SING"):
int_tile_locs.append((int_grid_x, loc.grid_y - 1))

View File

@ -39,6 +39,9 @@ def main():
if 'INT_INTERFACE' in tile_type:
continue
if 'BRKH' in tile_type:
continue
have_bits = 0
for tile_name, gridinfo in tiles:
total_tile_count += 1