mirror of https://github.com/openXC7/prjxray.git
Merge pull request #562 from litghost/expand_tilegrid_to_full_grid
Expand tilegrid to entire grid.
This commit is contained in:
commit
015b04ce90
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dword 2 --dframe 1B"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dword 0 --dframe 0"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 1 --dframe 15"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dword 0 --dframe 0"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 1 --dframe 15"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 30
|
||||
GENERATE_ARGS?="--oneval 1 --design params.csv --dword 0 --dframe 1B"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 10
|
||||
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 1 --dframe 15"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
N ?= 16
|
||||
GENERATE_ARGS?="--oneval 0 --design params.csv --dword 0 --dframe 15"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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__":
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
N ?= 15
|
||||
N ?= 35
|
||||
GENERATE_ARGS?="--oneval KEEPER --dframe 27 --dword 3 --dbit 3"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
N ?= 35
|
||||
GENERATE_ARGS?="--oneval 0 --design params.csv --dframe 14 --dword 1"
|
||||
include ../fuzzaddr/common.mk
|
||||
|
|
@ -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
|
||||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 } {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
module top (input i, output o);
|
||||
assign o = i;
|
||||
endmodule
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue