Merge pull request #562 from litghost/expand_tilegrid_to_full_grid

Expand tilegrid to entire grid.
This commit is contained in:
litghost 2019-01-28 16:17:44 -08:00 committed by GitHub
commit 015b04ce90
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
52 changed files with 1748 additions and 992 deletions

View File

@ -1,16 +1,36 @@
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
TILEGRID_TDB_DEPENDENCIES=
TILEGRID_TDB_DEPENDENCIES += iob/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += iob_int/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += monitor/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += bram/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += bram_block/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += bram_int/build/segbits_tilegrid.tdb
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 += fifo_int/build/segbits_tilegrid.tdb
GENERATE_FULL_ARGS=
ifeq (${XRAY_DATABASE}, zynq7)
# Zynq7 only
TILEGRID_TDB_DEPENDENCIES += ps7_int/build/segbits_tilegrid.tdb
GENERATE_FULL_ARGS += --int-tdb $(FUZDIR)/ps7_int/build/segbits_tilegrid.tdb
else
# Artix7/Kintex7 only
TILEGRID_TDB_DEPENDENCIES += pll/build/segbits_tilegrid.tdb
TILEGRID_TDB_DEPENDENCIES += mmcm/build/segbits_tilegrid.tdb
endif
ifeq (${XRAY_DATABASE}, kintex7)
else
# Disable DSP INT fuzzer on kintex7. It doesn't work, and isn't required.
TILEGRID_TDB_DEPENDENCIES += dsp_int/build/segbits_tilegrid.tdb
endif
database: build/tilegrid.json
pushdb:
pushdb: build/tilegrid.json
cp build/tilegrid.json ${XRAY_DATABASE_DIR}/$(XRAY_DATABASE)/tilegrid.json
build/tiles/tiles.txt:
@ -18,23 +38,22 @@ build/tiles/tiles.txt:
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 --out ${BUILD_DIR}/basicdb/tilegrid.json
cd build && python3 ${FUZDIR}/generate.py \
--tiles $(FUZDIR)/build/tiles/tiles.txt \
--out ${BUILD_DIR}/basicdb/tilegrid.json
build/clb/deltas:
bash generate.sh build/clb clb
clb/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd clb && $(MAKE)
build/bram/deltas:
bash generate.sh build/bram bram
build/iob/deltas:
bash generate.sh build/iob iob
build/tilegrid_tdb.json: add_tdb.py $(TILEGRID_TDB_DEPENDENCIES)
python3 add_tdb.py --fn-in build/basicdb/tilegrid.json --fn-out build/tilegrid_tdb.json
clb_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd clb_int && $(MAKE)
iob/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd iob && $(MAKE)
iob_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd iob_int && $(MAKE)
mmcm/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd mmcm && $(MAKE)
@ -44,14 +63,35 @@ pll/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
ps7_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd ps7_int && $(MAKE)
# FIXME: add monitor to ROI
monitor/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd monitor && $(MAKE)
build/tilegrid.json: generate_full.py build/tilegrid_tdb.json build/clb/deltas build/bram/deltas
bram/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd bram && $(MAKE)
bram_block/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd bram_block && $(MAKE)
bram_int/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd bram_int && $(MAKE)
dsp/build/segbits_tilegrid.tdb: build/basicdb/tilegrid.json
cd dsp && $(MAKE)
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 \
--fn-out build/tilegrid_tdb.json
build/tilegrid.json: generate_full.py build/tilegrid_tdb.json
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 ${GENERATE_FULL_ARGS}
--json-in tilegrid_tdb.json --json-out ${BUILD_DIR}/tilegrid.json
run:
$(MAKE) clean
$(MAKE) database
@ -60,10 +100,20 @@ run:
clean:
rm -rf build run.ok
cd clb && $(MAKE) clean
cd clb_int && $(MAKE) clean
cd iob && $(MAKE) clean
cd iob_int && $(MAKE) clean
cd mmcm && $(MAKE) clean
cd pll && $(MAKE) clean
cd ps7_int && $(MAKE) clean
cd bram && $(MAKE) clean
cd bram_block && $(MAKE) 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

@ -1,9 +1,32 @@
#!/usr/bin/env python3
from prjxray import util
import json
import os
import util as localutil
import os.path
def check_frames(tagstr, 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".format(tagstr), map(hex, frames))
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 load_db(fn):
@ -14,9 +37,9 @@ def load_db(fn):
parts = l.split(' ')
tagstr = parts[0]
addrlist = parts[1:]
localutil.check_frames(addrlist)
check_frames(tagstr, addrlist)
# Take the first address in the list
frame, wordidx, bitidx = localutil.parse_addr(addrlist[0])
frame, wordidx, bitidx = parse_addr(addrlist[0])
bitidx_up = False
@ -51,24 +74,31 @@ def run(fn_in, fn_out, verbose=False):
# FIXME: generate frames from part file (or equivilent)
# See https://github.com/SymbiFlow/prjxray/issues/327
# FIXME: generate words from pitch
int_frames, int_words = localutil.get_int_params()
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),
("monitor/build/segbits_tilegrid.tdb", 30, 101),
("bram/build/segbits_tilegrid.tdb", 28, 10),
("bram_block/build/segbits_tilegrid.tdb", 128, 10),
("clb/build/segbits_tilegrid.tdb", 36, 2),
("dsp/build/segbits_tilegrid.tdb", 28, 10),
("clb_int/build/segbits_tilegrid.tdb", int_frames, int_words),
("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),
("ps7_int/build/segbits_tilegrid.tdb", int_frames, int_words),
]
# FIXME: support XADC in ROI
if os.path.exists("monitor/build/segbits_tilegrid.tdb"):
# FIXME: height
tdb_fns.append(("monitor/build/segbits_tilegrid.tdb", 30, 101))
for (tdb_fn, frames, words) in tdb_fns:
if not os.path.exists(tdb_fn):
verbose and print('Skipping {}, file not found!'.format(tdb_fn))
continue
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))
localutil.add_tile_bits(tile, tilej, frame, wordidx, frames, words)

View File

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

View File

@ -0,0 +1,26 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,94 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
for site_name, site_type in gridinfo.sites.items():
if site_type in ['FIFO18E1']:
yield tile_name, site_name
def write_params(params):
pinstr = 'tile,val,site\n'
for tile, (site, val) in sorted(params.items()):
pinstr += '%s,%s,%s\n' % (tile, val, site)
open('params.csv', 'w').write(pinstr)
def run():
print(
'''
module top(input clk, stb, di, output do);
localparam integer DIN_N = 8;
localparam integer DOUT_N = 8;
reg [DIN_N-1:0] din;
wire [DOUT_N-1:0] dout;
reg [DIN_N-1:0] din_shr;
reg [DOUT_N-1:0] dout_shr;
always @(posedge clk) begin
din_shr <= {din_shr, di};
dout_shr <= {dout_shr, din_shr[DIN_N-1]};
if (stb) begin
din <= din_shr;
dout_shr <= dout;
end
end
assign do = dout_shr[DOUT_N-1];
''')
params = {}
sites = list(gen_sites())
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
params[tile_name] = (site_name, isone)
print(
'''
(* KEEP, DONT_TOUCH, LOC = "%s" *)
RAMB18E1 #(
.DOA_REG(%u)
) bram_%s (
.CLKARDCLK(),
.CLKBWRCLK(),
.ENARDEN(),
.ENBWREN(),
.REGCEAREGCE(),
.REGCEB(),
.RSTRAMARSTRAM(),
.RSTRAMB(),
.RSTREGARSTREG(),
.RSTREGB(),
.ADDRARDADDR(),
.ADDRBWRADDR(),
.DIADI(),
.DIBDI(),
.DIPADIP(),
.DIPBDIP(),
.WEA(),
.WEBWE(),
.DOADO(),
.DOBDO(),
.DOPADOP(),
.DOPBDOP());
''' % (site_name, isone, site_name))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,26 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,94 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
for site_name, site_type in gridinfo.sites.items():
if site_type in ['RAMBFIFO36E1']:
yield tile_name, site_name
def write_params(params):
pinstr = 'tile,val,site\n'
for tile, (site, val) in sorted(params.items()):
pinstr += '%s,%s,%s\n' % (tile, val, site)
open('params.csv', 'w').write(pinstr)
def run():
print(
'''
module top(input clk, stb, di, output do);
localparam integer DIN_N = 8;
localparam integer DOUT_N = 8;
reg [DIN_N-1:0] din;
wire [DOUT_N-1:0] dout;
reg [DIN_N-1:0] din_shr;
reg [DOUT_N-1:0] dout_shr;
always @(posedge clk) begin
din_shr <= {din_shr, di};
dout_shr <= {dout_shr, din_shr[DIN_N-1]};
if (stb) begin
din <= din_shr;
dout_shr <= dout;
end
end
assign do = dout_shr[DOUT_N-1];
''')
params = {}
sites = list(gen_sites())
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
params[tile_name] = (site_name, isone)
print(
'''
(* KEEP, DONT_TOUCH, LOC = "%s" *)
RAMB36E1 #(
.INIT_00(256'b%u)
) bram_%s (
.CLKARDCLK(),
.CLKBWRCLK(),
.ENARDEN(),
.ENBWREN(),
.REGCEAREGCE(),
.REGCEB(),
.RSTRAMARSTRAM(),
.RSTRAMB(),
.RSTREGARSTREG(),
.RSTREGB(),
.ADDRARDADDR(),
.ADDRBWRADDR(),
.DIADI(),
.DIBDI(),
.DIPADIP(),
.DIPBDIP(),
.WEA(),
.WEBWE(),
.DOADO(),
.DOBDO(),
.DOPADOP(),
.DOPBDOP());
''' % (site_name, isone, site_name))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,19 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,185 @@
import os
import random
import itertools
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_brams():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
sites = []
for site_name, site_type in gridinfo.sites.items():
if site_type in ['RAMB18E1', 'FIFO18E1']:
sites.append(site_name)
sites.sort()
if len(sites) == 0:
continue
if gridinfo.tile_type[-1] == 'L':
int_grid_x = loc.grid_x + 2
int_tile_type = 'INT_L'
else:
int_grid_x = loc.grid_x - 2
int_tile_type = 'INT_R'
int_tile_locs = [
(int_grid_x, loc.grid_y),
(int_grid_x, loc.grid_y - 1),
(int_grid_x, loc.grid_y - 2),
(int_grid_x, loc.grid_y - 3),
(int_grid_x, loc.grid_y - 4),
]
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_gridinfo.tile_type, int_tile_type)
int_tiles.append(grid.tilename_at_loc(int_tile_loc))
yield tile_name, sites, int_tiles
def write_params(params):
pinstr = 'tile,val\n'
for tile, (val, ) in sorted(params.items()):
pinstr += '%s,%s\n' % (tile, val)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
params = {}
sites = list(gen_brams())
fuzz_iter = iter(util.gen_fuzz_states(len(sites) * 5))
for tile_name, bram_sites, int_tiles in sites:
# Each BRAM tile has 5 INT tiles.
# The following feature is used to toggle a one PIP in each INT tile
#
# For BRAM_L_X6Y0, there are the following INT tiles and the feature
# to toggle
#
# - INT_L_X6Y0, tie bram_sites[0].DIADI[2] = 0, toggle bram_sites[0].DIADI[3]
# - INT_L_X6Y1, tie bram_sites[1].ADDRBWRADDR[7] = 0, toggle bram_sites[1].ADDRBWRADDR[10]
# - INT_L_X6Y2, tie bram_sites[1].ADDRARDADDR[9] = 0, toggle bram_sites[1].ADDRBWRADDR[9]
# - INT_L_X6Y3, tie bram_sites[1].ADDRBWRADDR[4] = 0, toggle bram_sites[1].ADDRBWRADDR[13]
# - INT_L_X6Y4, tie bram_sites[1].DIBDI[15] = 0, toggle bram_sites[1].DIADI[7]
(b0_diadi3, b1_wraddr10, b1_wraddr9, b1_wraddr13,
b1_diadi7) = itertools.islice(fuzz_iter, 5)
params[int_tiles[0]] = (b0_diadi3, )
params[int_tiles[1]] = (b1_wraddr10, )
params[int_tiles[2]] = (b1_wraddr9, )
params[int_tiles[3]] = (b1_wraddr13, )
params[int_tiles[4]] = (b1_diadi7, )
print(
'''
wire [15:0] {bram_site0}_diadi;
wire [15:0] {bram_site0}_dibdi;
wire [13:0] {bram_site0}_wraddr;
wire [15:0] {bram_site1}_diadi;
wire [15:0] {bram_site1}_dibdi;
wire [7:0] {bram_site1}_webwe;
wire [13:0] {bram_site1}_rdaddr;
wire [13:0] {bram_site1}_wraddr;
// INT 0
assign {bram_site0}_diadi[2] = 0;
assign {bram_site0}_diadi[3] = {b0_diadi3};
// INT 1
assign {bram_site1}_wraddr[7] = 0;
assign {bram_site1}_wraddr[10] = {b1_wraddr10};
// INT 2
assign {bram_site1}_rdaddr[9] = 0;
assign {bram_site1}_wraddr[9] = {b1_wraddr9};
// INT 3
assign {bram_site1}_wraddr[4] = 0;
assign {bram_site1}_wraddr[13] = {b1_wraddr13};
// INT 4
assign {bram_site1}_dibdi[15] = 0;
assign {bram_site1}_diadi[7] = {b1_diadi7};
(* KEEP, DONT_TOUCH, LOC = "{bram_site0}" *)
RAMB18E1 #(
) bram_{bram_site0} (
.CLKARDCLK(),
.CLKBWRCLK(),
.ENARDEN(),
.ENBWREN(),
.REGCEAREGCE(),
.REGCEB(),
.RSTRAMARSTRAM(),
.RSTRAMB(),
.RSTREGARSTREG(),
.RSTREGB(),
.ADDRARDADDR(),
.ADDRBWRADDR({bram_site0}_wraddr),
.DIADI({bram_site0}_diadi),
.DIBDI({bram_site0}_dibdi),
.DIPADIP(),
.DIPBDIP(),
.WEA(),
.WEBWE(),
.DOADO(),
.DOBDO(),
.DOPADOP(),
.DOPBDOP());
(* KEEP, DONT_TOUCH, LOC = "{bram_site1}" *)
RAMB18E1 #(
) bram_{bram_site1} (
.CLKARDCLK(),
.CLKBWRCLK(),
.ENARDEN(),
.ENBWREN(),
.REGCEAREGCE(),
.REGCEB(),
.RSTRAMARSTRAM(),
.RSTRAMB(),
.RSTREGARSTREG(),
.RSTREGB(),
.ADDRARDADDR({bram_site1}_rdaddr),
.ADDRBWRADDR({bram_site1}_wraddr),
.DIADI({bram_site1}_diadi),
.DIBDI({bram_site1}_dibdi),
.DIPADIP(),
.DIPBDIP(),
.WEA(),
.WEBWE({bram_site1}_webwe),
.DOADO(),
.DOBDO(),
.DOPADOP(),
.DOPBDOP());
'''.format(
bram_site0=bram_sites[0],
bram_site1=bram_sites[1],
b0_diadi3=b0_diadi3,
b1_wraddr10=b1_wraddr10,
b1_wraddr9=b1_wraddr9,
b1_wraddr13=b1_wraddr13,
b1_diadi7=b1_diadi7))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,26 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports clk]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports stb]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports do]
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,70 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
if gridinfo.tile_type in ['CLBLL_L', 'CLBLL_R', 'CLBLM_L', 'CLBLM_R']:
site_name = sorted(gridinfo.sites.keys())[0]
yield tile_name, site_name
def write_params(params):
pinstr = 'tile,val,site\n'
for tile, (site, val) in sorted(params.items()):
pinstr += '%s,%s,%s\n' % (tile, val, site)
open('params.csv', 'w').write(pinstr)
def run():
print(
'''
module top(input clk, stb, di, output do);
localparam integer DIN_N = 8;
localparam integer DOUT_N = 8;
reg [DIN_N-1:0] din;
wire [DOUT_N-1:0] dout;
reg [DIN_N-1:0] din_shr;
reg [DOUT_N-1:0] dout_shr;
always @(posedge clk) begin
din_shr <= {din_shr, di};
dout_shr <= {dout_shr, din_shr[DIN_N-1]};
if (stb) begin
din <= din_shr;
dout_shr <= dout;
end
end
assign do = dout_shr[DOUT_N-1];
''')
params = {}
sites = list(gen_sites())
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
params[tile_name] = (site_name, isone)
print(
'''
(* KEEP, DONT_TOUCH, LOC = "%s" *)
CARRY4 carry4_%s (
.CYINIT(%u));
''' % (site_name, site_name, isone))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,19 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,81 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
if gridinfo.tile_type in ['CLBLL_L', 'CLBLL_R', 'CLBLM_L', 'CLBLM_R']:
site_name = sorted(gridinfo.sites.keys())[0]
if gridinfo.tile_type[-1] == 'L':
int_tile_loc = (loc.grid_x + 1, loc.grid_y)
else:
int_tile_loc = (loc.grid_x - 1, loc.grid_y)
int_tile_name = grid.tilename_at_loc(int_tile_loc)
if not int_tile_name.startswith('INT_'):
continue
yield int_tile_name, site_name
def write_params(params):
pinstr = 'tile,val\n'
for tile, (site, val) in sorted(params.items()):
pinstr += '%s,%s,%s\n' % (tile, val, site)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
params = {}
sites = sorted(list(gen_sites()))
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
params[tile_name] = (site_name, isone)
# Force HARD0 -> GFAN1 with I2 = 0
# Toggle 1 pip with I1 = ?
print(
'''
wire lut_to_f7_{0}, f7_to_f8_{0};
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
LUT6_L #(
.INIT(0)
) lut_rom_{0} (
.I0(1),
.I1({1}),
.I2(0),
.I3(1),
.I4(1),
.I5(1),
.LO(lut_to_f7_{0})
);
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
MUXF7_L f7_{0} (
.I0(lut_to_f7_{0}),
.LO(f7_to_f8_{0})
);
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
MUXF8 f8_{0} (
.I0(f7_to_f8_{0})
);
'''.format(site_name, isone))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,19 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,52 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
if gridinfo.tile_type in ['DSP_L', 'DSP_R']:
site_name = sorted(gridinfo.sites.keys())[0]
yield tile_name, site_name
def write_params(params):
pinstr = 'tile,val,site\n'
for tile, (site, val) in sorted(params.items()):
pinstr += '%s,%s,%s\n' % (tile, val, site)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
params = {}
sites = list(gen_sites())
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
params[tile_name] = (site_name, isone)
print(
'''
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
DSP48E1 #(
.MASK({1})
) dsp_{0} (
);
'''.format(site_name, isone))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,21 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {DSPS-3}]
set_property IS_ENABLED 0 [get_drc_checks {DSPS-5}]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,168 @@
import os
import random
import itertools
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_dsps():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
sites = []
for site_name, site_type in gridinfo.sites.items():
if site_type in ['DSP48E1']:
sites.append(site_name)
sites.sort()
if len(sites) == 0:
continue
if gridinfo.tile_type[-1] == 'L':
int_grid_x = loc.grid_x + 2
int_tile_type = 'INT_L'
else:
int_grid_x = loc.grid_x - 2
int_tile_type = 'INT_R'
int_tile_locs = [
(int_grid_x, loc.grid_y),
(int_grid_x, loc.grid_y - 1),
(int_grid_x, loc.grid_y - 2),
(int_grid_x, loc.grid_y - 3),
(int_grid_x, loc.grid_y - 4),
]
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_gridinfo.tile_type, int_tile_type)
int_tiles.append(grid.tilename_at_loc(int_tile_loc))
yield tile_name, sites, int_tiles
def write_params(params):
pinstr = 'tile,val\n'
for tile, (val, ) in sorted(params.items()):
pinstr += '%s,%s\n' % (tile, val)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
params = {}
sites = list(gen_dsps())
fuzz_iter = iter(util.gen_fuzz_states(len(sites) * 5))
for tile_name, dsp_sites, int_tiles in sites:
int_tiles.reverse()
# Each DSP tile has 5 INT tiles.
# The following feature is used to toggle a one PIP in each INT tile
#
# For a DSP, there are the following INT tiles and the feature
# to toggle
#
# INT_L_X34Y89/INT_L.GFAN1->>IMUX_L30 :: D1.C36 = 0
# INT_L_X34Y89/INT_L.GFAN1->>IMUX_L28 :: D1.CARRYINSEL1 = toggle
#
# INT_L_X34Y88/INT_L.GFAN1->>IMUX_L30 :: D0.CARRYINSEL0 = toggle
#
# INT_L_X34Y87/INT_L.GFAN1->>IMUX_L5 :: D1.A29 = 0
# INT_L_X34Y87/INT_L.GFAN1->>IMUX_L14 :: D1.B8 = toggle
#
# INT_L_X34Y86/INT_L.GFAN1->>IMUX_L30 :: D1.B4 = 0
# INT_L_X34Y86/INT_L.GFAN1->>IMUX_L28 :: D1.B6 = toggle
#
# INT_L_X34Y85/INT_L.GFAN1->>IMUX_L30 :: Dark Green :: D1.C20 = 0
# INT_L_X34Y85/INT_L.GFAN1->>IMUX_L28 :: Color 10 :: D1.B2 = toggle
(d1_carryinsel1, d0_carryinsel0, d1_b8, d1_b6,
d1_b2) = itertools.islice(fuzz_iter, 5)
params[int_tiles[0]] = (d1_carryinsel1, )
params[int_tiles[1]] = (d0_carryinsel0, )
params[int_tiles[2]] = (d1_b8, )
params[int_tiles[3]] = (d1_b6, )
params[int_tiles[4]] = (d1_b2, )
print(
'''
wire [6:0] {dsp_site0}_opmode;
wire [2:0] {dsp_site0}_carryinsel;
wire [29:0] {dsp_site1}_a;
wire [17:0] {dsp_site1}_b;
wire [47:0] {dsp_site1}_c;
wire [6:0] {dsp_site1}_opmode;
wire [2:0] {dsp_site1}_carryinsel;
// INT 0, {int0}
assign {dsp_site1}_c[36] = 0;
assign {dsp_site1}_carryinsel[1] = {d1_carryinsel1};
// INT 1, {int1}
assign {dsp_site0}_carryinsel[0] = {d0_carryinsel0};
// INT 2, {int2}
assign {dsp_site1}_a[29] = 0;
assign {dsp_site1}_b[8] = {d1_b8};
// INT 3, {int3}
assign {dsp_site1}_b[4] = 0;
assign {dsp_site1}_b[6] = {d1_b6};
// INT 4, {int4}
assign {dsp_site1}_c[20] = 0;
assign {dsp_site1}_b[2] = {d1_b2};
(* KEEP, DONT_TOUCH, LOC = "{dsp_site0}" *)
DSP48E1 #(
.OPMODEREG(0),
.CREG(0)
) dsp_{dsp_site0} (
.OPMODE({dsp_site0}_opmode),
.CARRYINSEL({dsp_site0}_carryinsel)
);
(* KEEP, DONT_TOUCH, LOC = "{dsp_site1}" *)
DSP48E1 #(
.OPMODEREG(0),
.CREG(0)
) dsp_{dsp_site1} (
.OPMODE({dsp_site1}_opmode),
.CARRYINSEL({dsp_site1}_carryinsel),
.A({dsp_site1}_a),
.B({dsp_site1}_b),
.C({dsp_site1}_c)
);
'''.format(
dsp_site0=dsp_sites[0],
dsp_site1=dsp_sites[1],
d1_carryinsel1=d1_carryinsel1,
d0_carryinsel0=d0_carryinsel0,
d1_b8=d1_b8,
d1_b6=d1_b6,
d1_b2=d1_b2,
int0=int_tiles[0],
int1=int_tiles[1],
int2=int_tiles[2],
int3=int_tiles[3],
int4=int_tiles[4],
))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

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

View File

@ -0,0 +1,19 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,150 @@
import os
import random
import itertools
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_fifos():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
for site_name, site_type in gridinfo.sites.items():
if site_type in ['IN_FIFO']:
if gridinfo.tile_type[-1] == 'L':
int_grid_x = loc.grid_x + 2
int_tile_type = 'INT_L'
else:
int_grid_x = loc.grid_x - 2
int_tile_type = 'INT_R'
int_tile_locs = [
(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_tiles.append(grid.tilename_at_loc(int_tile_loc))
yield site_name, int_tiles
def write_params(params):
pinstr = 'tile,val\n'
for tile, (val, ) in sorted(params.items()):
pinstr += '%s,%s\n' % (tile, val)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
params = {}
sites = list(gen_fifos())
N_INT = 12
fuzz_iter = iter(util.gen_fuzz_states(len(sites) * N_INT))
for site, int_tiles in sites:
assert len(int_tiles) == N_INT
int_tiles.reverse()
bits = itertools.islice(fuzz_iter, N_INT)
assigns = []
# CMT_FIFO mux usage is regular with IMUX_L40 and IMUX_L42.
#
# 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]
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]
bits_set = set()
for idx, (int_tile, bit) in enumerate(zip(int_tiles, bits)):
bits_set.add((CHANNEL[idx], HOLD_BIT_0[idx]))
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}] = {toggle_bit};'
.format(
site=site,
channel=CHANNEL[idx],
bit=TOGGLE_BIT[idx],
toggle_bit=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,
))
print(
'''
wire [3:0] {site}_in_d0;
wire [3:0] {site}_in_d1;
wire [3:0] {site}_in_d2;
wire [3:0] {site}_in_d3;
wire [3:0] {site}_in_d4;
wire [7:0] {site}_in_d5;
wire [7:0] {site}_in_d6;
wire [3:0] {site}_in_d7;
wire [3:0] {site}_in_d8;
wire [3:0] {site}_in_d9;
{assign_statements}
(* KEEP, DONT_TOUCH, LOC = "{site}" *)
IN_FIFO fifo_{site} (
.D0({site}_in_d0),
.D1({site}_in_d1),
.D2({site}_in_d2),
.D3({site}_in_d3),
.D4({site}_in_d4),
.D5({site}_in_d5),
.D6({site}_in_d6),
.D7({site}_in_d7),
.D8({site}_in_d8),
.D9({site}_in_d9)
);
'''.format(
site=site,
assign_statements='\n'.join(assigns),
))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

@ -1,7 +1,5 @@
#!/usr/bin/env python3
import os, sys, json, re
from utils import xjson
@ -64,7 +62,6 @@ def run(tiles_fn, json_fn, verbose=False):
def main():
import argparse
import glob
parser = argparse.ArgumentParser(
description='Generate tilegrid.json from bitstream deltas')

View File

@ -1,55 +0,0 @@
source "$::env(FUZDIR)/util.tcl"
# Return a list of sites containing BRAMs
# sites are better than bels because site type may change and invalidate the bel
proc loc_brams {} {
# BRAM have multiple mutually exclusive sites
# They can be cycled by setting the site type
# Ex:
# - RAMB36_X0Y10/RAMBFIFO36E1
# - RAMB36_X0Y10/RAMB36E1
# Default is RAMBFIFO36E1?
# Work primarily on sites, not bels,
# to avoid issues when switching site type during PnR
set bram_sites [get_sites -of_objects [get_pblocks roi] -filter {SITE_TYPE =~ RAMBFIFO36E1*}]
set bram_bels [get_bels -of_objects $bram_sites]
set bram_columns [group_dut_cols $bram_bels 10]
# Output site, not bel, to avoid reference issues after PnR
return [loc_dut_col_sites $bram_columns {roi/brams[} {].bram}]
}
proc write_brams { selected_brams_sites } {
puts "write_brams: [llength $selected_brams_sites] BRAMs"
puts ""
# Toggle one bit in each selected BRAM to generate base addresses
for {set i 0} {$i < [llength $selected_brams_sites]} {incr i} {
puts ""
set cell [get_cells roi/brams[$i].bram]
puts "BRAM $cell"
set orig_init [get_property INIT_00 $cell]
# Flip a bit by changing MSB 0 => 1
set new_init [regsub "h8" $orig_init "h0"]
puts "INIT_00 $orig_init => $new_init"
set_property INIT_00 $new_init $cell
set site [lindex $selected_brams_sites $i]
if {"$site" == ""} {error "Bad site $site"}
write_bitstream -force design_$site.bit
set_property INIT_00 $orig_init $cell
}
}
proc run {} {
make_project
set selected_brams_sites [loc_brams]
puts "Selected BRAMs: [llength $selected_brams_sites]"
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
write_brams $selected_brams_sites
}
run

View File

@ -1,61 +0,0 @@
source "$::env(FUZDIR)/util.tcl"
proc group_lut_cols { lut_bels } {
# LOC one LUT (a "selected_lut") into each CLB segment configuration column (ie 50 per CMT column)
set lut_columns ""
foreach lut $lut_bels {
regexp "SLICE_X([0-9]+)Y([0-9]+)/" $lut match slice_x slice_y
# Only even SLICEs should be used as column bases.
if { $slice_x % 2 != 0 } {
continue
}
# 50 per column => 0, 50, 100, 150, etc
# ex: SLICE_X2Y50/A6LUT
# Only take one of the CLBs within a slice
set y_column [expr ($slice_y / 50) * 50]
dict append lut_columns "X${slice_x}Y${y_column}" "$lut "
}
return $lut_columns
}
proc loc_luts {} {
set lut_bels [get_bels -of_objects [get_sites -of_objects [get_pblocks roi]] -filter {TYPE =~ LUT*} */A6LUT]
set lut_columns [group_lut_cols $lut_bels]
return [loc_dut_col_bels $lut_columns {roi/luts[} {].lut}]
}
proc write_clbs { selected_luts } {
puts "write_brams: [llength $selected_luts] LUTs"
puts ""
# Toggle one bit in each selected LUT to generate base addresses
for {set i 0} {$i < [llength $selected_luts]} {incr i} {
puts ""
set cell [get_cells roi/luts[$i].lut]
puts "LUT $cell"
set orig_init [get_property INIT $cell]
# Flip a bit by changing MSB 0 => 1
set new_init [regsub "h8" $orig_init "h0"]
puts "INIT $orig_init => $new_init"
set_property INIT $new_init $cell
set site [get_sites -of_objects [lindex $selected_luts $i]]
write_bitstream -force design_$site.bit
set_property INIT $orig_init $cell
}
}
proc run {} {
make_project
set selected_luts [loc_luts]
puts "Selected LUTs: [llength $selected_luts]"
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
write_clbs $selected_luts
}
run

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
import os, sys, json, re
import json
from utils import xjson
'''
Historically we grouped data into "segments"
These were a region of the bitstream that encoded one or more tiles
@ -10,8 +11,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
from prjxray import util
import util as localutil
@ -28,566 +27,203 @@ def nolr(tile_type):
return tile_type
def load_baseaddrs(deltas_fns):
site_baseaddr = dict()
for arg in deltas_fns:
with open(arg) as f:
line = f.read().strip()
# clb/design_SLICE_X10Y100.delta
# site = arg[7:-6]
site = re.match(r".*/design_(.*).delta", arg).group(1)
# +bit_00400026_100_02
_, frame_str, _, _ = line.split('_')
frame = int(frame_str, 16)
site_baseaddr[site] = frame & ~0x7f
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))
added = 0
for tile in tiles:
for site_name in tile["sites"].keys():
if site_name not in site_baseaddr:
continue
framebaseaddr = site_baseaddr[site_name]
localutil.add_baseaddr(
tile_baseaddrs, tile["name"], framebaseaddr, verbose)
added += 1
assert added, "Failed to add any base addresses"
assert added == len(site_baseaddr)
return tile_baseaddrs
def make_tiles_by_grid(tiles):
def make_tiles_by_grid(database):
# lookup tile names by (X, Y)
tiles_by_grid = dict()
for tile in tiles:
tiles_by_grid[(tile["grid_x"], tile["grid_y"])] = tile["name"]
for tile_name in database:
tile = database[tile_name]
tiles_by_grid[(tile["grid_x"], tile["grid_y"])] = tile_name
return tiles_by_grid
def add_segment(
database, segments, name, tiles, segtype, verbose, baseaddr=None):
assert name not in segments
segment = segments.setdefault(name, {})
segment["tiles"] = tiles
segment["type"] = segtype
if baseaddr:
verbose and print('make_segment: %s baseaddr %s' % (
name,
baseaddr,
))
segment["baseaddr"] = baseaddr
for tile_name in tiles:
database[tile_name]["segment"] = name
def make_segments(database, tiles_by_grid, tile_baseaddrs, verbose=False):
'''
Create segments data structure
Indicates how tiles are related to bitstream locations
Also modify database to annotate which segment the tiles belong to
segments key examples:
SEG_CLBLM_R_X13Y72
SEG_BRAM3_L_X6Y85
'''
segments = dict()
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 add_segment(tiles, segtype, name=None, baseaddr=None):
assert name not in segments
segment = segments.setdefault(name, {})
segment["tiles"] = tiles
segment["type"] = segtype
if baseaddr:
verbose and print(
'make_segment: %s baseaddr %s' % (
name,
baseaddr,
))
segment["baseaddr"] = baseaddr
for tile_name in tiles:
database[tile_name]["segment"] = name
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_segment(
name="SEG_" + tile_name,
tiles=[tile_name, int_tile_name],
segtype=tile_type.lower(),
baseaddr=tile_baseaddrs.get(tile_name, None))
def process_hclk():
add_segment(
name="SEG_" + tile_name,
tiles=[tile_name],
segtype=tile_type.lower())
def process_iob():
tiles = [tile_name]
# FIXME mcmaster: removing INT for now
# Geometry doesn't line up with CLB, unclear if they are included
if tile_type.startswith('LIOB'):
# Two INT_L's
# tiles.append(tiles_by_grid[(grid_x + 4, grid_y)])
# tiles.append(tiles_by_grid[(grid_x + 4, grid_y - 1)])
# One IO interface tile
tiles.append(tiles_by_grid[(grid_x + 1, grid_y)])
else:
# Two INT_R's
# tiles.append(tiles_by_grid[(grid_x - 4, grid_y)])
# tiles.append(tiles_by_grid[(grid_x - 4, grid_y - 1)])
# One IO interface tile
tiles.append(tiles_by_grid[(grid_x - 1, grid_y)])
add_segment(
name="SEG_" + tile_name,
tiles=tiles,
segtype=tile_type.lower(),
baseaddr=tile_baseaddrs.get(tile_name, None))
def process_iob_sing():
# FIXME mcmaster: removing INT for now
# Geometry doesn't line up with CLB, unclear if they are included
tiles = [tile_name]
if tile_type.startswith('LIOB'):
tiles.append(tiles_by_grid[(grid_x + 1, grid_y)])
# tiles.append(tiles_by_grid[(grid_x + 4, grid_y)])
else:
tiles.append(tiles_by_grid[(grid_x - 1, grid_y)])
# tiles.append(tiles_by_grid[(grid_x - 4, grid_y)])
add_segment(
name="SEG_" + tile_name,
tiles=tiles,
segtype=tile_type.lower(),
baseaddr=tile_baseaddrs.get(tile_name, None))
def process_bram_dsp():
for k in range(5):
if tile_type in ["BRAM_L", "DSP_L"]:
interface_tile_name = tiles_by_grid[(
grid_x + 1, grid_y - k)]
int_tile_name = tiles_by_grid[(grid_x + 2, grid_y - k)]
elif tile_type in ["BRAM_R", "DSP_R"]:
interface_tile_name = tiles_by_grid[(
grid_x - 1, grid_y - k)]
int_tile_name = tiles_by_grid[(grid_x - 2, grid_y - k)]
else:
assert 0
'''
BRAM/DSP itself is at the base y address
There is one huge switchbox on the right for the 5 tiles
These fan into 5 BRAM_INT_INTERFACE tiles each which feed into their own CENTER_INTER (just like a CLB has)
'''
if k == 0:
tiles = [tile_name, interface_tile_name, int_tile_name]
baseaddr = tile_baseaddrs.get(tile_name, None)
else:
tiles = [interface_tile_name, int_tile_name]
baseaddr = None
add_segment(
# BRAM_L_X6Y70 => SEG_BRAM4_L_X6Y70
name="SEG_" + tile_name.replace("_", "%d_" % k, 1),
tiles=tiles,
# BRAM_L => bram4_l
segtype=tile_type.lower().replace("_", "%d_" % k, 1),
baseaddr=baseaddr)
def process_default():
verbose and nolr(tile_type) not in (
'VBRK', 'INT', 'NULL') and print(
'make_segment: drop %s' % (tile_type, ))
pass
"""
FIXME: review IOB
"RIOB33": process_iob,
"LIOB33": process_iob,
"RIOB33_SING": process_iob_sing,
"LIOB33_SING": process_iob_sing,
"""
{
"CLBLL": process_clb,
"CLBLM": process_clb,
"HCLK": process_hclk,
"BRAM": process_bram_dsp,
"DSP": process_bram_dsp,
}.get(nolr(tile_type), process_default)()
return segments
def get_inttile(database, segment):
'''Return interconnect tile for given segment'''
return (
tile for tile in segment["tiles"]
if database[tile]["type"] in ["INT_L", "INT_R"])
def get_iobtile(database, segment):
'''Return IOB tile for given segment'''
return (
tile for tile in segment["tiles"]
if database[tile]["type"] in ["LIOB33_SING", "LIOB33"])
def get_bramtile(database, segment):
inttiles = [
tile for tile in segment["tiles"]
if database[tile]["type"] in ["BRAM_L", "BRAM_R"]
]
assert len(inttiles) == 1
return inttiles[0]
def create_segment_for_int_lr(
database, segments, tile, tiles_by_grid, verbose):
""" Creates INT_[LR] segment for interconnect's without direct connectivity. """
# Some INT_[LR] tiles have no adjacent connectivity, create a segment.
grid_x = database[tile]["grid_x"]
grid_y = database[tile]["grid_y"]
if database[tile]["type"] == "INT_L":
grid_x -= 1
adjacent_tile = tiles_by_grid[(grid_x, grid_y)]
elif database[tile]["type"] == "INT_R":
grid_x += 1
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
database[adjacent_tile]['type'].startswith('GTP_INT_INTERFACE')):
# This INT_[LR] tile has no adjacent connectivity,
# create a segment.
add_segment(
database=database,
segments=segments,
name='SEG_' + tile,
tiles=[tile],
segtype=database[tile]["type"],
verbose=verbose,
)
else:
assert False, database[adjacent_tile]['type']
def seg_base_addr_lr_INT(database, segments, 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 segment_name in sorted(segments.keys()):
segment = segments[segment_name]
baseaddrs = segment.get("baseaddr", None)
if not baseaddrs:
for tile in database:
if database[tile]["type"] not in ["INT_L", "INT_R"]:
continue
for block_type, (framebase, wordbase) in sorted(baseaddrs.items()):
verbose and print(
'lr_INT: %s: %s.0x%08X:%u' %
(segment_name, block_type, framebase, wordbase))
if block_type != 'CLB_IO_CLK':
verbose and print(' Skip non CLB')
continue
for inttile in get_inttile(database, segment):
grid_x = database[inttile]["grid_x"]
grid_y = database[inttile]["grid_y"]
if database[inttile]["type"] == "INT_L":
grid_x += 1
framebase = framebase + 0x80
elif database[inttile]["type"] == "INT_R":
grid_x -= 1
framebase = framebase - 0x80
else:
assert 0
# ROI at edge?
if (grid_x, grid_y) not in tiles_by_grid:
verbose and print(' Skip edge')
continue
tile = tiles_by_grid[(grid_x, grid_y)]
if database[inttile]["type"] == "INT_L":
assert database[tile]["type"] == "INT_R"
elif database[inttile]["type"] == "INT_R":
assert database[tile]["type"] == "INT_L"
else:
assert 0
if "segment" not in database[tile]:
continue
seg = database[tile]["segment"]
seg_baseaddrs = segments[seg].setdefault("baseaddr", {})
# At least one duplicate when we re-compute the entry for the base address
# should give the same address
if block_type in seg_baseaddrs:
assert seg_baseaddrs[block_type] == [
framebase, wordbase
], (seg_baseaddrs[block_type], [framebase, wordbase])
verbose and print(' Existing OK')
else:
seg_baseaddrs[block_type] = [framebase, wordbase]
verbose and print(' Add new')
def seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=False):
'''Populate segment base addresses: Up along INT/HCLK 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 CLK_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):
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)
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
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]:
if not database[tile]["bits"]:
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"]
grid_x = database[tile]["grid_x"]
grid_y = database[tile]["grid_y"]
baseaddr = int(database[tile]["bits"]["CLB_IO_CLK"]["baseaddr"], 0)
offset = database[tile]["bits"]["CLB_IO_CLK"]["offset"]
entry = localutil.get_entry(nolr(tile_type), block_type)
if database[tile]["type"] == "INT_L":
grid_x += 1
baseaddr = baseaddr + 0x80
elif database[tile]["type"] == "INT_R":
grid_x -= 1
baseaddr = baseaddr - 0x80
else:
assert 0, database[tile]["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
# ROI at edge?
if (grid_x, grid_y) not in tiles_by_grid:
verbose and print(' Skip edge')
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)
other_tile = tiles_by_grid[(grid_x, grid_y)]
if database[tile]["type"] == "INT_L":
assert database[other_tile]["type"] == "INT_R"
elif database[tile]["type"] == "INT_R":
assert database[other_tile]["type"] == "INT_L"
else:
assert 0
def db_add_segments(database, segments):
# TODO: Migrate to new tilegrid format via library. This data is added for
# compability with unconverted tools. Update tools then remove this data from
# tilegrid.json.
# looks like only htmlgen is using this?
for tiledata in database.values():
if "segment" in tiledata:
segment = tiledata["segment"]
tiledata["segment_type"] = segments[segment]["type"]
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)
other_tile, database[other_tile], baseaddr, offset, int_frames,
int_words)
def run(
json_in_fn, json_out_fn, tiles_fn, deltas_fns, int_tdb=None,
verbose=False):
def propagate_INT_bits_in_column(database, tiles_by_grid):
""" Propigate INT offsets up and down INT columns.
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.
"""
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 ['INT_L', 'INT_R']:
continue
l_or_r = tile['type'][-1]
if not tile['bits']:
continue
if tile_name in seen_int:
continue
# Walk down 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'] == 0:
assert next_tile_type in [
'B_TERM_INT', 'BRKH_INT', 'BRKH_B_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 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, verbose=False):
# Load input files
tiles = load_tiles(tiles_fn)
site_baseaddr = load_baseaddrs(deltas_fns)
database = json.load(open(json_in_fn, "r"))
tiles_by_grid = make_tiles_by_grid(database)
tile_baseaddrs = make_tile_baseaddrs(tiles, site_baseaddr, verbose=verbose)
tiles_by_grid = make_tiles_by_grid(tiles)
segments = make_segments(
database, tiles_by_grid, tile_baseaddrs, verbose=verbose)
# Reference adjacent CLBs to locate adjacent tiles by known offsets
seg_base_addr_lr_INT(database, segments, tiles_by_grid, verbose=verbose)
seg_base_addr_up_INT(database, segments, tiles_by_grid, verbose=verbose)
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)
propagate_INT_lr_bits(database, tiles_by_grid, verbose=verbose)
propagate_INT_bits_in_column(database, tiles_by_grid)
# Save
json.dump(
database,
open(json_out_fn, "w"),
sort_keys=True,
indent=4,
separators=(",", ": "))
xjson.pprint(open(json_out_fn, "w"), database)
def main():
import argparse
import glob
parser = argparse.ArgumentParser(
description="Generate tilegrid.json from bitstream deltas")
@ -599,27 +235,9 @@ def main():
help="Input .json without addresses")
parser.add_argument(
"--json-out", default="tilegrid.json", help="Output JSON")
parser.add_argument(
'--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,
args.int_tdb,
verbose=args.verbose)
run(args.json_in, args.json_out, verbose=args.verbose)
if __name__ == "__main__":

View File

@ -1,42 +0,0 @@
source "$::env(FUZDIR)/util.tcl"
proc loc_iob {} {
# Some pads are output only (ex: OPAD_X0Y0/PAD) => filt IOB_*
# XXX: GTX bank missing, deal with that later
set roi_sites [get_sites -of_objects [get_pblocks roi]]
set duts [get_bels -of_objects $roi_sites -filter {TYPE =~ PAD && NAME =~ IOB_*}]
# Sort them into CMT columns
set dut_columns [group_dut_cols $duts 50]
# Assign one from each
return [loc_dut_col_sites $dut_columns {di_bufs[} {].ibuf} ]
}
proc write_iob { sel_iob_sites } {
foreach site $sel_iob_sites {
puts ""
set port [get_ports -of_objects $site]
set tile [get_tiles -of_objects $site]
set pin [get_property PACKAGE_PIN $port]
puts "IOB $port $site $tile $pin"
set orig_init [get_property PULLTYPE $port]
set_property PULLTYPE PULLUP $port
write_bitstream -force design_$site.bit
set_property PULLTYPE "$orig_init" $port
}
}
proc run {} {
make_project
set sel_iob_sites [loc_iob]
puts "Selected IOBs: [llength $sel_iob_sites]"
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
write_iob $sel_iob_sites
}
run

View File

@ -1,3 +1,3 @@
N ?= 15
N ?= 35
GENERATE_ARGS?="--oneval KEEPER --dframe 27 --dword 3 --dbit 3"
include ../fuzzaddr/common.mk

View File

@ -86,7 +86,7 @@ proc run {} {
# Mostly doesn't matter since IOB are special, but add anyway
create_pblock roi
add_cells_to_pblock [get_pblocks roi] [get_cells roi]
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI_TILEGRID)"
loc_pins

View File

@ -7,6 +7,7 @@ import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
from prjxray import verilog
@ -17,11 +18,15 @@ def gen_iobs():
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
Focus on IOB33S to start
'''
for _tile_name, site_name, site_type in util.get_roi().gen_sites(
# ['IOB33', 'IOB33S']):
# FIXME: special cases on IOB33
['IOB33S']):
yield site_name, site_type
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
for site_name, site_type in gridinfo.sites.items():
if site_type in ['IOB33S']:
yield site_name, site_type
def write_params(ports):

View File

@ -0,0 +1,3 @@
N ?= 35
GENERATE_ARGS?="--oneval 0 --design params.csv --dframe 14 --dword 1"
include ../fuzzaddr/common.mk

View File

@ -0,0 +1,75 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
proc make_io_pin_sites {} {
# get all possible IOB pins
foreach pad [get_package_pins -filter "IS_GENERAL_PURPOSE == 1"] {
set site [get_sites -of_objects $pad]
if {[llength $site] == 0} {
continue
}
if [string match IOB33* [get_property SITE_TYPE $site]] {
dict append io_pin_sites $site $pad
}
}
return $io_pin_sites
}
proc load_pin_lines {} {
# IOB_X0Y103 clk input
# IOB_X0Y129 do[0] output
set fp [open "params.csv" r]
set pin_lines {}
for {gets $fp line} {$line != ""} {gets $fp line} {
lappend pin_lines [split $line ","]
}
close $fp
return $pin_lines
}
proc loc_pins {} {
set pin_lines [load_pin_lines]
set io_pin_sites [make_io_pin_sites]
puts "Looping"
for {set idx 0} {$idx < [llength $pin_lines]} {incr idx} {
set line [lindex $pin_lines $idx]
puts "$line"
set site_str [lindex $line 3]
set pin_str [lindex $line 4]
# Have: site
# Want: pin for site
set site [get_sites $site_str]
set pad_bel [get_bels -of_objects $site -filter {TYPE =~ PAD && NAME =~ IOB_*}]
# set port [get_ports -of_objects $site]
set port [get_ports $pin_str]
set tile [get_tiles -of_objects $site]
set pin [dict get $io_pin_sites $site]
set_property -dict "PACKAGE_PIN $pin IOSTANDARD LVCMOS33" $port
}
}
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
loc_pins
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property IS_ENABLED 0 [get_drc_checks {REQP-79}]
place_design
route_design
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
run

View File

@ -0,0 +1,129 @@
'''
Generate a primitive to place at every I/O
Unlike CLB tests, the LFSR for this is inside the ROI, not driving it
'''
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
import re
def gen_sites():
'''
IOB33S: main IOB of a diff pair
IOB33M: secondary IOB of a diff pair
IOB33: not a diff pair. Relatively rare (at least in ROI...2 of them?)
Focus on IOB33S to start
'''
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
sites = []
for site_name, site_type in gridinfo.sites.items():
if site_type == 'IDELAYE2':
sites.append(site_name)
if len(sites) == 0:
continue
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
pad_grid_x = loc.grid_x - 1
int_tile_type = 'INT_L'
else:
int_grid_x = loc.grid_x - 3
pad_grid_x = loc.grid_x + 1
int_tile_type = 'INT_R'
int_tile_locs = [
(int_grid_x, loc.grid_y),
]
pad_gridinfo = grid.gridinfo_at_loc((pad_grid_x, loc.grid_y))
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))
assert len(sites) == len(int_tile_locs), (
tile_name, sites, int_tile_locs)
assert len(sites) == len(pad_sites), (sites, pad_sites)
for site_name, pad_site, int_tile_loc in zip(sites, pad_sites,
int_tile_locs):
int_tile_name = grid.tilename_at_loc(int_tile_loc)
assert int_tile_name.startswith(int_tile_type), (
int_tile_name, site_name, int_tile_loc)
yield int_tile_name, site_name, pad_site
def write_params(params):
pinstr = ''
for tile, (site, val, pad_site_name, pin) in sorted(params.items()):
pinstr += '%s,%s,%s,%s,%s\n' % (tile, val, site, pad_site_name, pin)
open('params.csv', 'w').write(pinstr)
def run():
sites = list(gen_sites())
print(
'''
`define N_DI {}
module top(input wire [`N_DI-1:0] di);
wire [`N_DI-1:0] di_buf;
(* KEEP, DONT_TOUCH, IODELAY_GROUP = "iodelays" *)
IDELAYCTRL idelayctrl (
.REFCLK()
);
'''.format(len(sites)))
params = {}
for idx, ((tile_name, site_name, pad_site_name), isone) in enumerate(zip(
sites, util.gen_fuzz_states(len(sites)))):
params[tile_name] = (site_name, isone, pad_site_name, "di[%u]" % idx)
# Force HARD0 -> GFAN1 with CNTVALUEIN4 = 0
# Toggle 1 pip with CNTVALUEIN3 = ?
print(
'''
// Solving for {3}
(* KEEP, DONT_TOUCH *)
IBUF ibuf_{0}(.I(di[{2}]), .O(di_buf[{2}]));
(* KEEP, DONT_TOUCH, LOC = "{0}", IODELAY_GROUP = "iodelays" *)
IDELAYE2 idelay_{0} (
.CNTVALUEIN(5'b0{1}111),
.IDATAIN(di_buf[{2}])
);
'''.format(site_name, isone, idx, tile_name))
print("endmodule")
write_params(params)
if __name__ == '__main__':
run()

View File

@ -47,7 +47,7 @@ module top(input clk, stb, di, output do);
# FIXME: can't LOC?
# only one for now, worry about later
sites = list(gen_sites())
assert len(sites) == 1
assert len(sites) == 1, len(sites)
for (tile_name, site_name), isone in zip(sites,
util.gen_fuzz_states(len(sites))):
# 0 is invalid

View File

@ -2,13 +2,19 @@ import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
from prjxray.db import Database
def gen_sites():
# yield ("MONITOR_BOT_X46Y79", "XADC_X0Y0")
for tile_name, site_name, _site_type in util.get_roi().gen_sites(['XADC']):
yield tile_name, site_name
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in grid.tiles():
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
for site_name, site_type in gridinfo.sites.items():
if site_type in ['XADC']:
yield tile_name, site_name
def write_params(params):

View File

@ -2,7 +2,6 @@ import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray import verilog
def write_params(params):

View File

@ -6,109 +6,27 @@ 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),
"""
""" Get frames and words for a given tile_type (e.g. CLBLL) and block_type (CLB_IO_CLK, BLOCK_RAM, etc). """
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),
("CLBLL", "CLB_IO_CLK"): (36, 2, None),
("CLBLM", "CLB_IO_CLK"): (36, 2, None),
("HCLK", "CLB_IO_CLK"): (26, 1, None),
("INT", "CLB_IO_CLK"): (28, 2, None),
("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),
("DSP", "CLB_IO_CLK"): (28, 2, None),
}.get((tile_type, block_type), None)
def get_int_params():
int_frames, int_words, _ = get_entry('INT', 'CLB_IO_CLK')
return int_frames, int_words
def add_tile_bits(
tile_name,
tile_db,
baseaddr,
offset,
frames,
words,
height=None,
verbose=False):
tile_name, tile_db, baseaddr, offset, frames, words, 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
@ -120,8 +38,9 @@ def add_tile_bits(
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 >= 0 or "IOB" in tile_name, (
tile_name, hex(baseaddr), offset)
assert 1 <= words <= 101, words
assert offset + words <= 101, (
tile_name, offset + words, offset, words, block_type)
@ -131,7 +50,7 @@ def add_tile_bits(
verbose and print(
"%s: existing defintion for %s" % (tile_name, block_type))
assert block["baseaddr"] == baseaddr_str
assert block["frames"] == frames
assert block["frames"] == frames, (block, frames)
assert block["offset"] == offset, "%s; orig offset %s, new %s" % (
tile_name, block["offset"], offset)
assert block["words"] == words
@ -147,10 +66,5 @@ def add_tile_bits(
# 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
# Number of words used by tile.
block["words"] = words
if height is None:
height = words
block["height"] = height

View File

@ -138,7 +138,7 @@ proc assign_iobs {} {
proc make_project {} {
# Generate .bit only over ROI
make_project_roi XRAY_ROI
make_project_roi XRAY_ROI_TILEGRID
}
proc make_project_roi { roi_var } {

View File

@ -1,33 +1,31 @@
N ?= 8
N := 1
SPECIMENS := $(addprefix build/specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
include ../fuzzer.mk
database: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -o build/segbits_dsp_l.db $(addsuffix /segdata_dsp_l_*.txt,$(SPECIMENS))
${XRAY_SEGMATCH} -o build/segbits_dsp_r.db $(addsuffix /segdata_dsp_r_*.txt,$(SPECIMENS))
${XRAY_DBFIXUP} --db-root build --clb-int
${XRAY_MASKMERGE} build/mask_dsp_l.db $(addsuffix /segdata_dsp_l_*.txt,$(SPECIMENS))
${XRAY_MASKMERGE} build/mask_dsp_r.db $(addsuffix /segdata_dsp_r_*.txt,$(SPECIMENS))
database: build/segbits_dsp_l.db build/mask_dsp_r.db build/segbits_dsp_r.db build/mask_dsp_r.db
pushdb:
SEGDATAS_L=$(addsuffix /segdata_dsp_l.txt,$(SPECIMENS))
SEGDATAS_R=$(addsuffix /segdata_dsp_r.txt,$(SPECIMENS))
build/segbits_dsp_l.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -o build/segbits_dsp_l.rdb $(SEGDATAS_L)
build/segbits_dsp_l.db build/mask_dsp_l.db: build/segbits_dsp_l.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_dsp_l.db $(SEGDATAS_L)
build/segbits_dsp_r.rdb: $(SPECIMENS_OK)
${XRAY_SEGMATCH} -o build/segbits_dsp_r.rdb $(SEGDATAS_R)
build/segbits_dsp_r.db build/mask_dsp_r.db: build/segbits_dsp_r.rdb
${XRAY_DBFIXUP} --db-root build --zero-db bits.dbf --seg-fn-in $^ --seg-fn-out $@
${XRAY_MASKMERGE} build/mask_dsp_r.db $(SEGDATAS_R)
pushdb: database
${XRAY_MERGEDB} dsp_l build/segbits_dsp_l.db
${XRAY_MERGEDB} dsp_r build/segbits_dsp_r.db
${XRAY_MERGEDB} mask_dsp_l build/segbits_dsp_l.db
${XRAY_MERGEDB} mask_dsp_r build/segbits_dsp_r.db
$(SPECIMENS_OK):
bash generate.sh $(subst /OK,,$@)
touch $@
run:
$(MAKE) clean
$(MAKE) database
$(MAKE) pushdb
touch run.ok
clean:
rm -rf build run.ok
.PHONY: database pushdb run clean
.PHONY: database pushdb

View File

View File

@ -1,27 +1,23 @@
#!/usr/bin/env python3
import sys
from prjxray.segmaker import Segmaker
import csv
segmk = Segmaker("design_%s.bits" % sys.argv[1])
segmk = Segmaker("design.bits", verbose=True)
pipdata = dict()
ignpip = set()
print("Loading tags")
with open('params.csv', 'r') as f:
for d in csv.DictReader(f):
dsp = "DSP_0" if d['site'][-1] in "02468" else "DSP_1"
print("Loading tags from design.txt.")
with open("design_%s.txt" % sys.argv[1], "r") as f:
for line in f:
tile, loc, mask, pattern = line.split()
dsp = "DSP_0" if loc[-1] in "02468" else "DSP_1"
mask = int(mask.replace("48'h", ""), 16)
pattern = int(pattern.replace("48'h", ""), 16)
mask = int(d['mask'])
pattern = int(d['pattern'])
for i in range(48):
segmk.add_tile_tag(tile, "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1)
segmk.add_tile_tag(
tile, "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1)
segmk.add_site_tag(
d['site'], "%s.MASK[%d]" % (dsp, i), (mask >> i) & 1)
segmk.add_site_tag(
d['site'], "%s.PATTERN[%d]" % (dsp, i), (pattern >> i) & 1)
segmk.compile()
segmk.write(suffix=sys.argv[1])
segmk.write()

View File

@ -1,13 +0,0 @@
#!/bin/bash
set -ex
source ${XRAY_GENHEADER}
${XRAY_VIVADO} -mode batch -source $FUZDIR/generate.tcl
for i in {10..29}; do
${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design_${i}.bits -z -y design_${i}.bit
python3 $FUZDIR/generate.py $i
done

View File

@ -1,71 +1,19 @@
source "$::env(XRAY_DIR)/utils/utils.tcl"
create_project -force -part $::env(XRAY_PART) design design
proc run {} {
create_project -force -part $::env(XRAY_PART) design design
read_verilog top.v
synth_design -top top
read_verilog "$::env(FUZDIR)/top.v"
synth_design -top top
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_00) IOSTANDARD LVCMOS33" [get_ports i]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_01) IOSTANDARD LVCMOS33" [get_ports o]
place_design
route_design
create_pblock roi
resize_pblock [get_pblocks roi] -add "$::env(XRAY_ROI)"
set_property CFGBVS VCCO [current_design]
set_property CONFIG_VOLTAGE 3.3 [current_design]
set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]
set_param tcl.collectionResultDisplayLimit 0
place_design
route_design
write_checkpoint -force design.dcp
set cells [list]
set gnd_net [create_net gnd_net]
set gnd_cell [create_cell -reference GND gnd_cell]
connect_net -net $gnd_net -objects [get_pins $gnd_cell/G]
foreach site [get_sites -of_objects [filter [roi_tiles] -filter {TYPE == "DSP_L" || TYPE == "DSP_R"}] -filter {SITE_TYPE =~ DSP*}] {
set cell [create_cell -reference DSP48E1 ${site}_cell]
lappend cells $cell
set_property LOC $site $cell
foreach pin [get_pins -of_objects $cell -filter {DIRECTION == "IN"}] {
connect_net -net $gnd_net -objects $pin
}
write_checkpoint -force design.dcp
write_bitstream -force design.bit
}
route_design
proc write_txtdata {filename} {
upvar 1 cells cells
puts "Writing $filename."
set fp [open $filename w]
foreach cell $cells {
set loc [get_property LOC $cell]
set mask [get_property MASK $cell]
set pattern [get_property PATTERN $cell]
set tile [get_tiles -of_objects [get_sites -filter "NAME == $loc"]]
puts $fp "$tile $loc $mask $pattern"
}
close $fp
}
proc randhex {len} {
set s ""
for {set i 0} {$i < $len} {incr i} {
set s "$s[format %x [expr {int(rand()*16)}]]"
}
return $s
}
for {set i 10} {$i < 30} {incr i} {
foreach cell $cells {
set_property MASK "48'h[randhex 12]" $cell
set_property PATTERN "48'h[randhex 12]" $cell
}
write_checkpoint -force design_${i}.dcp
write_bitstream -force design_${i}.bit
write_txtdata design_${i}.txt
}
run

View File

@ -0,0 +1,56 @@
import os
import random
random.seed(int(os.getenv("SEED"), 16))
from prjxray import util
from prjxray.db import Database
def gen_sites():
db = Database(util.get_db_root())
grid = db.grid()
for tile_name in sorted(grid.tiles()):
loc = grid.loc_of_tilename(tile_name)
gridinfo = grid.gridinfo_at_loc(loc)
if gridinfo.tile_type in ['DSP_L', 'DSP_R']:
for site in sorted(gridinfo.sites.keys()):
if gridinfo.sites[site] == 'DSP48E1':
yield tile_name, site
def write_params(lines):
pinstr = 'tile,site,mask,pattern\n'
for tile, site, mask, pattern in lines:
pinstr += '%s,%s,%s,%s\n' % (tile, site, mask, pattern)
open('params.csv', 'w').write(pinstr)
def run():
print('''
module top();
''')
lines = []
sites = list(gen_sites())
for (tile_name, site_name) in sites:
mask = random.randint(0, 2**48 - 1)
pattern = random.randint(0, 2**48 - 1)
lines.append((tile_name, site_name, mask, pattern))
print(
'''
(* KEEP, DONT_TOUCH, LOC = "{0}" *)
DSP48E1 #(
.MASK(48'h{1:x}),
.PATTERN(48'h{2:x})
) dsp_{0} (
);
'''.format(site_name, mask, pattern))
print("endmodule")
write_params(lines)
if __name__ == '__main__':
run()

View File

@ -1,3 +0,0 @@
module top (input i, output o);
assign o = i;
endmodule

View File

@ -209,14 +209,13 @@ class Segmaker:
"tags": dict(),
# verify new entries match this
"offset": bitj["offset"],
"height": bitj["height"],
"words": bitj["words"],
"frames": bitj["frames"],
})
base_frame = json_hex2i(bitj["baseaddr"])
for wordidx in range(bitj["offset"],
bitj["offset"] + bitj["height"]):
bitj["offset"] + bitj["words"]):
if base_frame not in self.bits:
continue
if wordidx not in self.bits[base_frame]:
@ -247,7 +246,6 @@ class Segmaker:
else:
segment = segments[segname]
assert segment["offset"] == bitj["offset"]
assert segment["height"] == bitj["height"]
assert segment["words"] == bitj["words"]
assert segment["frames"] == bitj["frames"]
return segment

View File

@ -366,14 +366,14 @@ def mk_segtiles(tiles):
seglets = segtiles.setdefault(ref_tile_name, [])
ref_as = (
ref_block["offset"],
ref_block["offset"] + ref_block["height"] - 1)
ref_block["offset"] + ref_block["words"] - 1)
for cmpi in range(refi + 1, len(values)):
(_cmp_block_offset, cmp_tile_name, cmp_block,
cmp_block_name) = values[cmpi]
cmp_as = (
cmp_block["offset"],
cmp_block["offset"] + cmp_block["height"] - 1)
cmp_block["offset"] + cmp_block["words"] - 1)
if overlap(ref_as, cmp_as):
seglets.append((cmp_tile_name, cmp_block_name))

View File

@ -26,19 +26,26 @@ def main():
total_tile_count = 0
total_have_bits = 0
for tile_type, tiles in sorted(tile_types.items()):
tile_type_info = db.get_tile_type(tile_type)
# Skip empty tiles, as no base address is requied.
if len(tile_type_info.get_pips()) == 0 and len(
tile_type_info.get_sites()) == 0:
continue
for tile_type, tiles in sorted(tile_types.items()):
try:
tile_type_info = db.get_tile_type(tile_type)
# Skip empty tiles, as no base address is requied.
if len(tile_type_info.get_pips()) == 0 and len(
tile_type_info.get_sites()) == 0:
continue
except KeyError:
pass
# INT_INTERFACE tiles likely don't contain configuration? Remove this
# if this ends up false.
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