Initial cascade pip fuzzer.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2019-01-30 14:51:28 -08:00
parent a8299c84a3
commit 741715851a
14 changed files with 618 additions and 86 deletions

View File

@ -0,0 +1,38 @@
MAKETODO_FLAGS=--re "BRAM_.\.BRAM_(?!LOGIC_OUTS).*"
export FUZDIR=$(shell pwd)
PIPLIST_TCL=$(FUZDIR)/bram_pip_list.tcl
PIP_TYPE?=bram_pips_int
SEG_TYPE?=bram
N = 50
SEGMATCH_FLAGS=-m 20 -M 45
include ../pip_loop.mk
#
# Specimens from current run must complete, but previous iterations may exist
database: $(SPECIMENS_OK)
${XRAY_SEGMATCH} $(SEGMATCH_FLAGS) -o build/segbits_bram_l.rdb $(shell find build -name segdata_bram_l.txt)
${XRAY_SEGMATCH} $(SEGMATCH_FLAGS) -o build/segbits_bram_r.rdb $(shell find build -name segdata_bram_r.txt)
# Keep a copy to track iter progress
# Also is pre-fixup, which drops and converts
cp build/segbits_bram_l.rdb build/$(ITER)/segbits_bram_l.rdb
cp build/segbits_bram_r.rdb build/$(ITER)/segbits_bram_r.rdb
${XRAY_DBFIXUP} --db-root build \
--verbose \
--zero-db bits.dbf \
--seg-fn-in build/segbits_bram_l.rdb \
--seg-fn-out build/segbits_bram_l.db
${XRAY_DBFIXUP} --db-root build \
--verbose \
--zero-db bits.dbf \
--seg-fn-in build/segbits_bram_r.rdb \
--seg-fn-out build/segbits_bram_r.db
# Clobber existing .db to eliminate potential conflicts
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} bram_l build/segbits_bram_l.db
XRAY_DATABASE_DIR=${FUZDIR}/build/database ${XRAY_MERGEDB} bram_r build/segbits_bram_r.db
# Final pushdb to real repo
pushdb: database
${XRAY_MERGEDB} bram_l build/segbits_bram_l.db
${XRAY_MERGEDB} bram_r build/segbits_bram_r.db

View File

@ -0,0 +1,30 @@
26_184 26_185 26_187,BRAM.BRAM_ADDRBWRADDRL7.BRAM_IMUX_ADDRBWRADDRL7
26_88 26_89 26_91 ,BRAM.BRAM_ADDRBWRADDRL8.BRAM_IMUX_ADDRBWRADDRL8
26_197 26_198 26_199,BRAM.BRAM_ADDRARDADDRU3.BRAM_IMUX_ADDRARDADDRU3
26_101 26_102 26_103,BRAM.BRAM_ADDRARDADDRU4.BRAM_IMUX_ADDRARDADDRU4
26_229 26_230 26_231,BRAM.BRAM_ADDRARDADDRU5.BRAM_IMUX_ADDRARDADDRU5
26_165 26_166 26_167,BRAM.BRAM_ADDRARDADDRU6.BRAM_IMUX_ADDRARDADDRU6
26_181 26_182 26_183,BRAM.BRAM_ADDRARDADDRU7.BRAM_IMUX_ADDRARDADDRU7
26_85 26_86 26_87 ,BRAM.BRAM_ADDRARDADDRU8.BRAM_IMUX_ADDRARDADDRU8
26_213 26_214 26_215,BRAM.BRAM_ADDRARDADDRU9.BRAM_IMUX_ADDRARDADDRU9
26_77 26_78 26_79 ,BRAM.BRAM_ADDRBWRADDRU2.BRAM_IMUX_ADDRBWRADDRU2
26_205 26_206 26_207,BRAM.BRAM_ADDRBWRADDRU3.BRAM_IMUX_ADDRBWRADDRU3
26_237 26_238 26_239,BRAM.BRAM_ADDRBWRADDRU5.BRAM_IMUX_ADDRBWRADDRU5
26_173 26_174 26_175,BRAM.BRAM_ADDRBWRADDRU6.BRAM_IMUX_ADDRBWRADDRU6
26_189 26_190 26_191,BRAM.BRAM_ADDRBWRADDRU7.BRAM_IMUX_ADDRBWRADDRU7
26_93 26_94 26_95 ,BRAM.BRAM_ADDRBWRADDRU8.BRAM_IMUX_ADDRBWRADDRU8
26_221 26_222 26_223,BRAM.BRAM_ADDRBWRADDRU9.BRAM_IMUX_ADDRBWRADDRU9
26_176 26_177 26_179,BRAM.BRAM_ADDRARDADDRL7.BRAM_R_IMUX_ADDRARDADDRL7
26_80 26_81 26_83 ,BRAM.BRAM_ADDRARDADDRL8.BRAM_R_IMUX_ADDRARDADDRL8
26_165 26_166 26_167,BRAM.BRAM_ADDRARDADDRU6.BRAM_R_IMUX_ADDRARDADDRU6
26_181 26_182 26_183,BRAM.BRAM_ADDRARDADDRU7.BRAM_R_IMUX_ADDRARDADDRU7
26_85 26_86 26_87 ,BRAM.BRAM_ADDRARDADDRU8.BRAM_R_IMUX_ADDRARDADDRU8
26_88 26_89 26_91 ,BRAM.BRAM_ADDRBWRADDRL8.BRAM_R_IMUX_ADDRBWRADDRL8
26_189 26_190 26_191,BRAM.BRAM_ADDRBWRADDRU7.BRAM_R_IMUX_ADDRBWRADDRU7
26_93 26_94 26_95 ,BRAM.BRAM_ADDRBWRADDRU8.BRAM_R_IMUX_ADDRBWRADDRU8

View File

@ -0,0 +1,20 @@
create_project -force -part $::env(XRAY_PART) design design
set_property design_mode PinPlanning [current_fileset]
open_io_design -name io_1
proc print_tile_pips {tile_type filename} {
set tile [lindex [get_tiles -filter "TYPE == $tile_type"] 0]
puts "Dumping BRAM PIPs for tile $tile ($tile_type) to $filename."
set fp [open $filename w]
foreach pip [lsort [get_pips -filter {IS_DIRECTIONAL} -of_objects [get_tiles $tile]]] {
set src [get_wires -uphill -of_objects $pip]
set dst [get_wires -downhill -of_objects $pip]
if {[llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst]]] != 1} {
puts $fp "$tile_type.[regsub {.*/} $dst ""].[regsub {.*/} $src ""]"
}
}
close $fp
}
print_tile_pips BRAM_L bram_pips_int_l.txt
print_tile_pips BRAM_R bram_pips_int_r.txt

View File

@ -0,0 +1,67 @@
#!/usr/bin/env python3
from prjxray.segmaker import Segmaker
segmk = Segmaker("design.bits")
tiledata = {}
pipdata = {}
ignpip = set()
print("Loading tags from design.txt.")
with open("design.txt", "r") as f:
for line in f:
tile, pip, src, dst, pnum, pdir = line.split()
if not tile.startswith('BRAM_'):
continue
# BRAM_R_X37Y0/BRAM_R.BRAM_IMUX35_1->BRAM_R_IMUX_ADDRBWRADDRL2
pip_prefix, pip = pip.split(".")
tile_from_pip, tile_type = pip_prefix.split('/')
assert tile == tile_from_pip
_, src = src.split("/")
_, dst = dst.split("/")
pnum = int(pnum)
pdir = int(pdir)
if tile not in tiledata:
tiledata[tile] = {"type": tile_type, "pips": set(), "srcs": set(), "dsts": set()}
if tile_type not in pipdata:
pipdata[tile_type] = {}
if pip in pipdata[tile_type]:
assert pipdata[tile_type][pip] == (src, dst)
else:
pipdata[tile_type][pip] = (src, dst)
tiledata[tile]["pips"].add(pip)
tiledata[tile]["srcs"].add(src)
tiledata[tile]["dsts"].add(dst)
if pdir == 0:
tiledata[tile]["srcs"].add(dst)
tiledata[tile]["dsts"].add(src)
if pnum == 1 or pdir == 0:
ignpip.add(pip)
for tile, pips_srcs_dsts in tiledata.items():
tile_type = pips_srcs_dsts["type"]
pips = pips_srcs_dsts["pips"]
srcs = pips_srcs_dsts["srcs"]
dsts = pips_srcs_dsts["dsts"]
for pip, src_dst in pipdata[tile_type].items():
src, dst = src_dst
if pip in ignpip:
pass
elif pip in pips:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 1)
elif src_dst[1] not in dsts:
segmk.add_tile_tag(tile, "%s.%s" % (dst, src), 0)
segmk.compile()
segmk.write()

View File

@ -0,0 +1,14 @@
#!/bin/bash
set -ex
FUZDIR=$PWD
source ${XRAY_GENHEADER}
echo '`define SEED 32'"'h$(echo $1 | md5sum | cut -c1-8)" > setseed.vh
${XRAY_VIVADO} -mode batch -source $FUZDIR/generate.tcl | tee vivado_stdout.log | grep "FUZ[^:]\+:"
${XRAY_BITREAD} -F $XRAY_ROI_FRAMES -o design.bits -z -y design.bit
python3 $FUZDIR/generate.py

View File

@ -0,0 +1,45 @@
puts "FUZ([pwd]): Creating project"
create_project -force -part $::env(XRAY_PART) design design
puts "FUZ([pwd]): Reading verilog"
read_verilog top.v
puts "FUZ([pwd]): Synth design"
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_param tcl.collectionResultDisplayLimit 0
source "$::env(XRAY_DIR)/utils/utils.tcl"
puts "FUZ([pwd]): Placing design"
place_design
puts "FUZ([pwd]): Routing design"
route_design
write_checkpoint -force design.dcp
proc write_txtdata {filename} {
puts "FUZ([pwd]): Writing $filename."
set fp [open $filename w]
foreach net [get_nets -hierarchical] {
if [string match "*addr*" $net] {
puts "Tick $net."
foreach pip [get_pips -of_objects $net] {
set tile [get_tiles -of_objects $pip]
set src_wire [get_wires -uphill -of_objects $pip]
set dst_wire [get_wires -downhill -of_objects $pip]
set num_pips [llength [get_nodes -uphill -of_objects [get_nodes -of_objects $dst_wire]]]
set dir_prop [get_property IS_DIRECTIONAL $pip]
puts $fp "$tile $pip $src_wire $dst_wire $num_pips $dir_prop"
}
}
}
close $fp
}
write_bitstream -force design.bit
write_txtdata design.txt

View File

@ -0,0 +1,211 @@
import os
import sys
import random
import math
from prjxray import util
from prjxray.db import Database
random.seed(int(os.getenv("SEED"), 16))
def bram_count():
db = Database(util.get_db_root())
grid = db.grid()
count = 0
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']:
count += 1
return count
class LutMaker(object):
def __init__(self):
self.input_lut_idx = 0
self.output_lut_idx = 0
self.lut_input_idx = 0
def get_next_input_net(self):
net = 'lut_{}_i[{}]'.format(self.input_lut_idx, self.lut_input_idx)
self.lut_input_idx += 1
if self.lut_input_idx > 5:
self.lut_input_idx = 0
self.input_lut_idx += 1
return net
def get_next_output_net(self):
net = 'lut_{}_o'.format(self.output_lut_idx)
self.output_lut_idx += 1
return net
def create_wires_and_luts(self):
if self.output_lut_idx > self.input_lut_idx:
nluts = self.output_lut_idx
else:
nluts = self.input_lut_idx
if self.lut_input_idx > 0:
nluts += 1
for lut in range(nluts):
yield """
wire [5:0] lut_{lut}_i;
wire lut_{lut}_o;
(* KEEP, DONT_TOUCH *)
LUT6 lut_{lut} (
.I0(lut_{lut}_i[0]),
.I1(lut_{lut}_i[1]),
.I2(lut_{lut}_i[2]),
.I3(lut_{lut}_i[3]),
.I4(lut_{lut}_i[4]),
.I5(lut_{lut}_i[5]),
.O(lut_{lut}_o)
);
""".format(lut=lut)
def sdp_bram(name, width, address_bits):
depth = 2**address_bits
return '''
module {name}(
// Write port
input wrclk,
input [{width}-1:0] di,
input wren,
input [{address_bits}-1:0] wraddr,
// Read port
input rdclk,
input rden,
input [{address_bits}-1:0] rdaddr,
output reg [{width}-1:0] do);
(* ram_style = "block" *) reg [{width}-1:0] ram[0:{depth}];
always @ (posedge wrclk) begin
if(wren == 1) begin
ram[wraddr] <= di;
end
end
always @ (posedge rdclk) begin
if(rden == 1) begin
do <= ram[rdaddr];
end
end
endmodule
'''.format(
name=name,
width=width,
address_bits=address_bits,
depth=depth,
)
MAX_BRAM = 8
def emit_sdp_bram(luts, name, modules, lines, width, address_bits):
modules.append(sdp_bram(name=name, width=width, address_bits=address_bits))
lines.append('''
wire [9:0] {name}_wraddr;
wire [9:0] {name}_rdaddr;
'''.format(name=name))
for bit in range(10):
lines.append("""
assign {name}_wraddr[{bit}] = {net};""".format(
name=name,
bit=bit,
net=luts.get_next_output_net()))
for bit in range(10):
lines.append("""
assign {name}_rdaddr[{bit}] = {net};""".format(
name=name,
bit=bit,
net=luts.get_next_output_net()))
lines.append('''
(* KEEP, DONT_TOUCH *)
{name} {name}_inst(
.wraddr({name}_wraddr),
.rdaddr({name}_rdaddr)
);
'''.format(name=name))
return width, address_bits, math.ceil(float(width)/72)*72*(2**address_bits)
def max_address_bits(width):
return math.floor(math.log(float(MAX_BRAM*36*1024)/width, 2))
def random_sdp_bram(luts, name, modules, lines):
sdp_choices = set()
for width in (1, 18, 36):
sdp_choices.add((width, (1, max_address_bits(width))))
for nbram in range(2, MAX_BRAM+1):
#sdp_choices.add((nbram*32, (1, max_address_bits(nbram*32))))
#sdp_choices.add((nbram*36, (1, max_address_bits(nbram*36))))
#sdp_choices.add((nbram*16, (1, max_address_bits(nbram*16))))
#sdp_choices.add((nbram*32, (1, max_address_bits(nbram*32))))
# Bias some wide but shallow BRAMs to toggle the lower address bits
# more.
for address_bits in range(1, 4):
sdp_choices.add((nbram*32, (address_bits, address_bits)))
sdp_choices = sorted(sdp_choices)
width, address_bits_range = random.choice(sdp_choices)
address_bits = random.randint(*address_bits_range)
return emit_sdp_bram(luts, name, modules, lines, width, address_bits)
def run():
luts = LutMaker()
count = bram_count()
max_bram_count = random.randint(1, 200)
modules = []
lines = []
idx = 0
while count > MAX_BRAM:
width, address_bits, bits = random_sdp_bram(luts, "ram{}".format(idx), modules, lines)
brams = math.ceil(bits/float(36*1024))
count -= brams
print(width, address_bits, bits, brams, count, file=sys.stderr)
idx += 1
if idx >= max_bram_count:
break
for module in modules:
print(module)
print(
'''
module top();
''')
for lut in luts.create_wires_and_luts():
print(lut)
for l in lines:
print(l)
print("endmodule")
if __name__ == '__main__':
run()

View File

@ -60,6 +60,29 @@ proc write_int_ppips_db {filename tile} {
close $fp
}
proc write_bram_ppips_db {filename tile} {
set fp [open $filename "w"]
set tile [get_tiles $tile]
set tile_type [get_property TILE_TYPE $tile]
foreach pip [get_pips -of_objects $tile] {
set dst_wire [get_wires -downhill -of_objects $pip]
if {[get_pips -uphill -of_objects [get_nodes -of_objects $dst_wire]] == $pip} {
set src_wire [get_wires -uphill -of_objects $pip]
puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always"
}
# LOGIC_OUTS pips appear to be always, even thought multiple inputs to
# the pip junction. Best guess is that the underlying hardware is
# actually just one wire, and there is no actually junction.
if [string match "*LOGIC_OUTS*" dst_wire] {
puts $fp "${tile_type}.[regsub {.*/} $dst_wire ""].[regsub {.*/} $src_wire ""] always"
}
}
close $fp
}
foreach tile_type {CLBLM_L CLBLM_R CLBLL_L CLBLL_R} {
set tiles [get_tiles -filter "TILE_TYPE == $tile_type"]
if {[llength $tiles] != 0} {
@ -68,10 +91,17 @@ foreach tile_type {CLBLM_L CLBLM_R CLBLL_L CLBLL_R} {
}
}
foreach tile_type {INT_L INT_R BRAM_L BRAM_R BRAM_INT_INTERFACE_L BRAM_INT_INTERFACE_R} {
foreach tile_type {INT_L INT_R BRAM_INT_INTERFACE_L BRAM_INT_INTERFACE_R} {
set tiles [get_tiles -filter "TILE_TYPE == $tile_type"]
if {[llength $tiles] != 0} {
set tile [lindex $tiles 0]
write_int_ppips_db "ppips_[string tolower $tile_type].db" $tile
}
}
foreach tile_type {BRAM_L BRAM_R} {
set tiles [get_tiles -filter "TILE_TYPE == $tile_type"]
if {[llength $tiles] != 0} {
set tile [lindex $tiles 0]
write_bram_ppips_db "ppips_[string tolower $tile_type].db" $tile
}
}

View File

@ -1,28 +1,4 @@
TODO_N ?= 50
# Number of spcimens
ifeq ($(QUICK),Y)
N = 1
TODO_N = 3
SEGMATCH_FLAGS=
else
# Should be at least the -m value
N ?= 20
SEGMATCH_FLAGS=-m 15 -M 45
endif
# Iteration number (each containing N specimens)
# Driven by int_loop.sh
ITER ?= 1
MAKETODO_FLAGS ?=
PIP_TYPE?=pips_int
PIPLIST_TCL?=$(XRAY_FUZZERS_DIR)/piplist/piplist.tcl
# See int_loop_check.py
# rempips took 35 iters once, so set 50 as a good start point
CHECK_ARGS := --zero-entries --timeout-iters 50
SPECIMENS := $(addprefix build/$(ITER)/specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
# Individual fuzzer directory, such as ~/prjxray/fuzzers/010-lutinit
export FUZDIR=$(shell pwd)
include pip_loop.mk
# Specimens from current run must complete, but previous iterations may exist
database: $(SPECIMENS_OK)
@ -55,50 +31,3 @@ pushdb:
${XRAY_MERGEDB} mask_clbll_r build/mask_clbll_r.db
${XRAY_MERGEDB} mask_clblm_l build/mask_clblm_l.db
${XRAY_MERGEDB} mask_clblm_r build/mask_clblm_r.db
$(SPECIMENS_OK): build/todo.txt
mkdir -p build/$(ITER)
bash ${XRAY_DIR}/utils/top_generate.sh $(subst /OK,,$@)
touch $@
$(XRAY_FUZZERS_DIR)/piplist/build/$(PIP_TYPE)_l.txt: $(PIPLIST_TCL)
mkdir -p $(XRAY_FUZZERS_DIR)/piplist/build
cd $(XRAY_FUZZERS_DIR)/piplist/build && ${XRAY_VIVADO} -mode batch -source $(PIPLIST_TCL)
# Used 1) to see if we are done 2) pips to try in generate.tcl
build/todo.txt: $(XRAY_FUZZERS_DIR)/piplist/build/$(PIP_TYPE)_l.txt $(XRAY_DIR)/fuzzers/int_maketodo.py build/database/seeded
XRAY_DATABASE_DIR=${FUZDIR}/build/database python3 $(XRAY_DIR)/fuzzers/int_maketodo.py --pip-type $(PIP_TYPE) $(MAKETODO_FLAGS) |sort >build/todo_all.txt
cat build/todo_all.txt | sort -R | head -n$(TODO_N) > build/todo.txt.tmp
mv build/todo.txt.tmp build/todo.txt
# Per iter files
mkdir -p build/$(ITER)
cp build/todo_all.txt build/todo.txt build/$(ITER)/
# All in one dir for easier trending
mkdir -p build/todo
cp build/todo_all.txt build/todo/$(ITER)_all.txt
# Initial copy for first todo.txt
# Subsequent are based on updated db
build/database/seeded:
mkdir -p build/database/${XRAY_DATABASE}
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
touch build/database/seeded
# XXX: conider moving to script
run:
$(MAKE) clean
XRAY_DIR=${XRAY_DIR} MAKE="$(MAKE)" QUICK=$(QUICK) $(XRAY_DIR)/fuzzers/int_loop.sh --check-args "$(CHECK_ARGS)"
touch run.ok
clean:
rm -rf build run.ok todo
# Remove iteration specific files, but keep piplist.tcl output
cleaniter:
rm -rf build/$(ITER) build/todo.txt
cleanpiplist:
rm -rf $(XRAY_FUZZERS_DIR)/piplist/build
.PHONY: database pushdb run clean cleaniter cleanpiplist

View File

@ -91,6 +91,7 @@ def run(
pip_dir,
intre,
pip_type,
seg_type,
not_endswith=None,
verbose=False):
if db_dir is None:
@ -103,13 +104,13 @@ def run(
assert intre, "RE is required"
maketodo(
"%s/%s_l.txt" % (pip_dir, pip_type),
"%s/segbits_int_l.db" % db_dir,
"%s/segbits_%s_l.db" % (db_dir, seg_type),
intre,
not_endswith,
verbose=verbose)
maketodo(
"%s/%s_r.txt" % (pip_dir, pip_type),
"%s/segbits_int_r.db" % db_dir,
"%s/segbits_%s_r.db" % (db_dir, seg_type),
intre,
not_endswith,
verbose=verbose)
@ -127,6 +128,7 @@ def main():
parser.add_argument('--pip-dir', default=None, help='')
parser.add_argument('--re', required=True, help='')
parser.add_argument('--pip-type', default="pips_int", help='')
parser.add_argument('--seg-type', default="int", help='')
parser.add_argument(
'--not-endswith', help='Drop lines if they end with this')
args = parser.parse_args()
@ -137,6 +139,7 @@ def main():
pip_dir=args.pip_dir,
intre=args.re,
pip_type=args.pip_type,
seg_type=args.seg_type,
not_endswith=args.not_endswith,
verbose=args.verbose)

75
fuzzers/pip_loop.mk Normal file
View File

@ -0,0 +1,75 @@
TODO_N ?= 50
# Number of spcimens
ifeq ($(QUICK),Y)
N = 1
TODO_N = 3
SEGMATCH_FLAGS=
else
# Should be at least the -m value
N ?= 20
SEGMATCH_FLAGS=-m 15 -M 45
endif
# Iteration number (each containing N specimens)
# Driven by int_loop.sh
ITER ?= 1
MAKETODO_FLAGS ?=
PIP_TYPE?=pips_int
SEG_TYPE?=int
PIPLIST_TCL?=$(XRAY_FUZZERS_DIR)/piplist/piplist.tcl
# See int_loop_check.py
# rempips took 35 iters once, so set 50 as a good start point
CHECK_ARGS := --zero-entries --timeout-iters 50
SPECIMENS := $(addprefix build/$(ITER)/specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
# Individual fuzzer directory, such as ~/prjxray/fuzzers/010-lutinit
export FUZDIR=$(shell pwd)
all: database
$(SPECIMENS_OK): build/todo.txt
mkdir -p build/$(ITER)
bash ${XRAY_DIR}/utils/top_generate.sh $(subst /OK,,$@)
touch $@
$(XRAY_FUZZERS_DIR)/piplist/build/$(PIP_TYPE)_l.txt: $(PIPLIST_TCL)
mkdir -p $(XRAY_FUZZERS_DIR)/piplist/build
cd $(XRAY_FUZZERS_DIR)/piplist/build && ${XRAY_VIVADO} -mode batch -source $(PIPLIST_TCL)
# Used 1) to see if we are done 2) pips to try in generate.tcl
build/todo.txt: $(XRAY_FUZZERS_DIR)/piplist/build/$(PIP_TYPE)_l.txt $(XRAY_DIR)/fuzzers/int_maketodo.py build/database/seeded
XRAY_DATABASE_DIR=${FUZDIR}/build/database python3 $(XRAY_DIR)/fuzzers/int_maketodo.py --pip-type $(PIP_TYPE) --seg-type $(SEG_TYPE) $(MAKETODO_FLAGS) |sort >build/todo_all.txt
cat build/todo_all.txt | sort -R | head -n$(TODO_N) > build/todo.txt.tmp
mv build/todo.txt.tmp build/todo.txt
# Per iter files
mkdir -p build/$(ITER)
cp build/todo_all.txt build/todo.txt build/$(ITER)/
# All in one dir for easier trending
mkdir -p build/todo
cp build/todo_all.txt build/todo/$(ITER)_all.txt
# Initial copy for first todo.txt
# Subsequent are based on updated db
build/database/seeded:
mkdir -p build/database/${XRAY_DATABASE}
cp ${XRAY_DATABASE_DIR}/${XRAY_DATABASE}/segbits*.db build/database/${XRAY_DATABASE}
touch build/database/seeded
# XXX: conider moving to script
run:
$(MAKE) clean
XRAY_DIR=${XRAY_DIR} MAKE="$(MAKE)" QUICK=$(QUICK) $(XRAY_DIR)/fuzzers/int_loop.sh --check-args "$(CHECK_ARGS)"
touch run.ok
clean:
rm -rf build run.ok todo
# Remove iteration specific files, but keep piplist.tcl output
cleaniter:
rm -rf build/$(ITER) build/todo.txt
cleanpiplist:
rm -rf $(XRAY_FUZZERS_DIR)/piplist/build
.PHONY: all database pushdb run clean cleaniter cleanpiplist

View File

@ -20,7 +20,7 @@ clb_int_zero_db = [
def zero_range(tag, bits, wordmin, wordmax):
"""
If any bits occur wordmin <= word <= wordmax,
default bits in wordmin <= word <= wordmax to 0
default bits in wordmin <= word <= wordmax to 0
"""
# The bit index, if any, that needs to be one hotted
@ -105,7 +105,7 @@ def zero_groups(tag, bits, zero_db, strict=True, verbose=False):
def add_zero_bits(
fn_in, fn_out, zero_db, clb_int=False, strict=True, verbose=False):
fn_in, zero_db, clb_int=False, strict=True, verbose=False):
'''
Add multibit entries
This requires adding some zero bits (ex: !31_09)
@ -154,6 +154,13 @@ def add_zero_bits(
zero_range(tag, bits, 22, 25)
zero_groups(tag, bits, zero_db, strict=strict, verbose=verbose)
if len(bits) == 0:
verbose and print(
"WARNING: dropping unresolved line: %s" % line)
drops += 1
continue
new_line = " ".join([tag] + sorted(bits))
if re.match(r'.*<.*>.*', new_line):
@ -168,11 +175,7 @@ def add_zero_bits(
if drops:
print("WARNING: %s dropped %s unresolved lines" % (fn_in, drops))
with open(fn_out, "w") as f:
for line in sorted(new_lines):
print(line, file=f)
return changes
return changes, new_lines
def update_mask(db_root, mask_db, src_dbs, offset=0):
@ -224,6 +227,57 @@ def load_zero_db(fn):
ret.append(l)
return ret
def remove_ambiguous_solutions(fn_in, db_lines, strict=True, verbose=True):
""" Removes features with identical solutions.
During solving, some tags may be tightly coupled and solve to the same
solution. In these cases, those solutions must be dropped until
disambiguating information can be found.
"""
solutions = {}
dropped_solutions = set()
for l in db_lines:
parts = l.split()
feature = parts[0]
bits = frozenset(parts[1:])
if bits in solutions:
if strict:
assert False, "Found solution {} at least twice, in {} and {}".format(
bits, feature, solutions[bits])
else:
dropped_solutions.add(bits)
else:
solutions[bits] = feature
if strict:
return 0, db_lines
drops = 0
output_lines = []
for l in db_lines:
parts = l.split()
feature = parts[0]
bits = frozenset(parts[1:])
if bits not in dropped_solutions:
output_lines.append(l)
drops += 1
else:
if verbose:
print(
"WARNING: dropping line due to duplicate solution: %s" % l)
if drops > 0:
print("WARNING: %s dropped %s duplicate solutions" % (fn_in, drops))
return drops, output_lines
def update_seg_fns(
fn_inouts, zero_db, clb_int, lazy=False, strict=True, verbose=False):
@ -234,13 +288,27 @@ def update_seg_fns(
if lazy and not os.path.exists(fn_in):
continue
changes = add_zero_bits(
changes, new_lines = add_zero_bits(
fn_in,
fn_out,
zero_db,
clb_int=clb_int,
strict=strict,
verbose=verbose)
new_changes, final_lines = remove_ambiguous_solutions(
fn_in,
new_lines,
strict=strict,
verbose=verbose,
)
changes += new_changes
with open(fn_out, "w") as f:
for line in sorted(final_lines):
print(line, file=f)
if changes is not None:
seg_files += 1
seg_lines += changes
@ -249,6 +317,7 @@ def update_seg_fns(
(seg_files, seg_lines))
def update_masks(db_root):
for mask_db, src_dbs in [
("clbll_l", ("clbll_l", "int_l")),
@ -348,7 +417,7 @@ def main():
parser.add_argument('--zero-db', help='Apply custom patches')
parser.add_argument('--seg-fn-in', help='')
parser.add_argument('--seg-fn-out', help='')
util.add_bool_arg(parser, "--strict", default=None)
util.add_bool_arg(parser, "--strict", default=False)
args = parser.parse_args()
run(

View File

@ -27,7 +27,7 @@ export XRAY_DBFIXUP="python3 ${XRAY_UTILS_DIR}/dbfixup.py"
export XRAY_MASKMERGE="bash ${XRAY_UTILS_DIR}/maskmerge.sh"
export XRAY_SEGMATCH="${XRAY_TOOLS_DIR}/segmatch"
export XRAY_SEGPRINT="python3 ${XRAY_UTILS_DIR}/segprint.py"
export XRAY_BITS2FASM="python3 ${XRAY_UTILS_DIR}/bits2fasm.py"
export XRAY_BIT2FASM="python3 ${XRAY_UTILS_DIR}/bit2fasm.py"
export XRAY_FASM2FRAMES="python3 ${XRAY_UTILS_DIR}/fasm2frames.py"
export XRAY_BITTOOL="${XRAY_TOOLS_DIR}/bittool"
export XRAY_BLOCKWIDTH="python3 ${XRAY_UTILS_DIR}/blockwidth.py"

View File

@ -17,6 +17,7 @@ design_bits.ok: vivado.ok
\
for x in design*.bit; do \
${XRAY_BITREAD} -F ${XRAY_ROI_FRAMES} -o $${x}s -z -y $$x ; \
${XRAY_BIT2FASM} --verbose $$x > $${x%.*}.fasm; \
done
touch design_bits.ok