Add 010-lutinit fuzzer, Improve segmatch

Signed-off-by: Clifford Wolf <clifford@clifford.at>
Signed-off-by: Tim 'mithro' Ansell <mithro@mithis.com>
This commit is contained in:
Clifford Wolf 2017-10-15 03:00:56 +02:00
parent c5eaa5af77
commit 715b261c3e
7 changed files with 389 additions and 45 deletions

2
fuzzers/010-lutinit/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
/specimen_[0-9][0-9][0-9]/
/database.txt

View File

@ -0,0 +1,20 @@
N := 1
SPECIMENS := $(addprefix specimen_,$(shell seq -f '%03.0f' $(N)))
SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS))
database.txt: $(SPECIMENS_OK)
../../tools/segmatch -o database.txt \
$(addsuffix /segdata_0.txt,$(SPECIMENS)) \
$(addsuffix /segdata_1.txt,$(SPECIMENS)) \
$(addsuffix /segdata_2.txt,$(SPECIMENS))
$(SPECIMENS_OK):
bash generate.sh $(subst /OK,,$@)
touch $@
clean:
rm -rf $(SPECIMENS)
.PHONY: clean

View File

@ -0,0 +1,110 @@
#!/usr/bin/env python3
import os, sys, json, re
#################################################
# Loading Raw Source Data
grid = None
bits = dict()
luts = dict()
print("Loading grid.")
with open("../../../gridinfo/grid-%s-db.json" % os.getenv("XRAY_PART"), "r") as f:
grid = json.load(f)
print("Loading bits.")
with open("design_%s.bits" % sys.argv[1], "r") as f:
for line in f:
line = line.split("_")
bit_frame = int(line[1], 16)
bit_wordidx = int(line[2], 16)
bit_bitidx = int(line[3], 16)
base_frame = bit_frame & ~0x7f
if base_frame not in bits:
bits[base_frame] = dict()
if bit_wordidx not in bits[base_frame]:
bits[base_frame][bit_wordidx] = set()
bits[base_frame][bit_wordidx].add((bit_frame, bit_wordidx, bit_bitidx))
print("Loading lut data.")
with open("lutdata_%s.txt" % sys.argv[1], "r") as f:
for line in f:
line = line.split()
site = line[0]
bel = line[1]
init = int(line[2][4:], 16)
if site not in luts:
luts[site] = dict()
for i in range(64):
bitname = "%s.INIT[%02d]" % (bel, i)
luts[site][bitname] = ((init >> i) & 1) != 0
#################################################
# Group per Segment
print("Compile segment data.")
segments = dict()
for tilename, tiledata in grid["tiles"].items():
found_data = False
for site in tiledata["sites"]:
if site in luts:
found_data = True
if not found_data:
continue
tile_type = tiledata["props"]["TYPE"]
segname = "%s_%02x" % (tiledata["cfgcol"]["BASE_FRAMEID"][2:], min(tiledata["cfgcol"]["WORDS"]))
if not segname in segments:
segments[segname] = { "bits": list(), "tags": dict() }
for site in tiledata["sites"]:
if site not in luts:
continue
if re.match(r"SLICE_X[0-9]*[02468]Y", site):
sitekey = "SLICE_X0"
elif re.match(r"SLICE_X[0-9]*[13579]Y", site):
sitekey = "SLICE_X1"
else:
assert 0
for name, value in luts[site].items():
segments[segname]["tags"]["%s.%s.%s" % (tile_type, sitekey, name)] = value
base_frame = int(tiledata["cfgcol"]["BASE_FRAMEID"][2:], 16)
for wordidx in tiledata["cfgcol"]["WORDS"]:
if base_frame not in bits:
continue
if wordidx not in bits[base_frame]:
continue
for bit_frame, bit_wordidx, bit_bitidx in bits[base_frame][wordidx]:
segments[segname]["bits"].append("%02x_%02x_%02x" % (bit_frame - base_frame, bit_wordidx - min(tiledata["cfgcol"]["WORDS"]), bit_bitidx))
segments[segname]["bits"].sort()
#################################################
# Print
print("Write segment data.")
with open("segdata_%s.txt" % sys.argv[1], "w") as f:
for segname, segdata in sorted(segments.items()):
print("seg %s" % segname, file=f)
for bitname in sorted(segdata["bits"]):
print("bit %s" % bitname, file=f)
for tagname, tagval in sorted(segdata["tags"].items()):
print("tag %s %d" % (tagname, tagval), file=f)

View File

@ -0,0 +1,19 @@
#!/bin/bash
set -ex
source ../../settings.sh
test $# = 1
test ! -e $1
mkdir $1
cd $1
echo '`define SEED 32'"'h$(echo $1 | md5sum | cut -c1-8)" > setseed.vh
vivado -mode batch -source ../generate.tcl
for i in 0 1 2; do
../../../tools/bitread -F $XRAY_ROI_FRAMES -o design_$i.bits -zy < design_$i.bit
python3 ../generate.py $i
done

View File

@ -0,0 +1,89 @@
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 di]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_02) IOSTANDARD LVCMOS33" [get_ports do]
set_property -dict "PACKAGE_PIN $::env(XRAY_PIN_03) IOSTANDARD LVCMOS33" [get_ports stb]
set_property LOCK_PINS {I0:A1 I1:A2 I2:A3 I3:A4 I4:A5 I5:A6} \
[get_cells -quiet -filter {REF_NAME == LUT6} -hierarchical]
create_pblock roi
add_cells_to_pblock [get_pblocks roi] [get_cells 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_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF]
place_design
route_design
write_checkpoint -force design.dcp
########################################
# Unmodified design with random LUTs
proc write_lutdata {filename} {
puts "Writing $filename."
set fp [open $filename w]
foreach cell [get_cells -hierarchical -filter {REF_NAME == LUT6}] {
set bel [get_property BEL $cell]
set loc [get_property LOC $cell]
set init [get_property INIT $cell]
puts $fp "$loc $bel $init"
}
close $fp
}
write_bitstream -force design_0.bit
write_lutdata lutdata_0.txt
########################################
# XOR LUT INITs
set pattern_list {
0x1234567812345678
0xFFFFFFFF00000000
0xFFFF0000FFFF0000
0xFF00FF00FF00FF00
0xF0F0F0F0F0F0F0F0
0xCCCCCCCCCCCCCCCC
0xAAAAAAAAAAAAAAAA
}
set pattern_index 0
foreach cell [get_cells -hierarchical -filter {REF_NAME == LUT6}] {
set v [get_property init $cell]
set v [scan [string range $v 4 100] %x]
set v [expr $v ^ [lindex $pattern_list $pattern_index]]
set v [format %x $v]
set_property init 64'h$v $cell
set pattern_index [expr ($pattern_index + 1) % 7]
}
write_bitstream -force design_1.bit
write_lutdata lutdata_1.txt
########################################
# Set LUT INITs
set pattern_index 1
foreach cell [get_cells -hierarchical -filter {REF_NAME == LUT6}] {
set_property init 64'h[lindex $pattern_list $pattern_index] $cell
set pattern_index [expr ($pattern_index + 1) % 7]
}
write_bitstream -force design_2.bit
write_lutdata lutdata_2.txt

92
fuzzers/010-lutinit/top.v Normal file
View File

@ -0,0 +1,92 @@
`include "setseed.vh"
module top(input clk, stb, di, output do);
localparam integer DIN_N = 10;
localparam integer DOUT_N = 10;
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];
roi roi (
.clk(clk),
.din(din),
.dout(dout)
);
endmodule
module roi(input clk, input [9:0] din, output [9:0] dout);
localparam integer N = 200;
function [31:0] xorshift32(input [31:0] v);
begin
xorshift32 = v;
xorshift32 = xorshift32 ^ (xorshift32 << 13);
xorshift32 = xorshift32 ^ (xorshift32 >> 17);
xorshift32 = xorshift32 ^ (xorshift32 << 5);
end
endfunction
function [31:0] hash32(input [31:0] v);
begin
hash32 = v ^ `SEED;
hash32 = xorshift32(hash32);
hash32 = xorshift32(hash32);
hash32 = xorshift32(hash32);
hash32 = xorshift32(hash32);
end
endfunction
function [63:0] hash64(input [31:0] v);
begin
hash64[63:32] = hash32(v);
hash64[31: 0] = hash32(~v);
end
endfunction
wire [N*10+9:0] nets;
assign nets[9:0] = din;
assign dout = nets[N*10+9:N*10];
genvar i, j;
generate
for (i = 0; i < N; i = i+1) begin:is
for (j = 0; j < 10; j = j+1) begin:js
localparam integer k = i*10 + j + 10;
wire lut_out;
LUT6 #(
.INIT(hash64({i, j, 8'hff}))
) lut (
.I0(nets[hash32({i, j, 8'h00}) % k]),
.I1(nets[hash32({i, j, 8'h01}) % k]),
.I2(nets[k-10]),
.I3(nets[k-9]),
.I4(nets[k-8]),
.I5(nets[k-7]),
.O(lut_out)
);
reg lut_out_reg;
always @(posedge clk)
lut_out_reg <= lut_out;
assign nets[k] = ((i+j) % 17) < 10 ? lut_out_reg : lut_out;
end
end
endgenerate
endmodule

View File

@ -5,6 +5,7 @@
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
#include <numeric>
#include <map>
#include <set>
@ -26,18 +27,18 @@ static inline vector<bool> &segdata_bits(segdata_t &sd) { return std::get<0>(sd)
static inline vector<bool> &segdata_tags1(segdata_t &sd) { return std::get<1>(sd); }
static inline vector<bool> &segdata_tags0(segdata_t &sd) { return std::get<2>(sd); }
void read_input()
void read_input(std::istream &f, std::string filename)
{
string token;
segdata_t *segptr = nullptr;
while (std::cin >> token)
while (f >> token)
{
if (token == "seg")
{
std::cin >> token;
while (segdata.count(token))
token += "_";
f >> token;
token = filename + ":" + token;
assert(segdata.count(token) == 0);
segptr = &segdata[token];
continue;
}
@ -46,7 +47,7 @@ void read_input()
{
assert(segptr != nullptr);
std::cin >> token;
f >> token;
if (bit_ids.count(token) == 0) {
bit_ids[token] = num_bits++;
bit_ids_r.push_back(token);
@ -66,7 +67,7 @@ void read_input()
{
assert(segptr != nullptr);
std::cin >> token;
f >> token;
if (tag_ids.count(token) == 0) {
tag_ids[token] = num_tags++;
tag_ids_r.push_back(token);
@ -74,7 +75,7 @@ void read_input()
int tag_idx = tag_ids.at(token);
std::cin >> token;
f >> token;
assert(token == "0" || token == "1");
auto &tags = token == "1" ? segdata_tags1(*segptr) : segdata_tags0(*segptr);
@ -116,53 +117,57 @@ void andc_masks(vector<bool> &dst_mask, const vector<bool> &src_mask)
int main(int argc, char **argv)
{
const char *outfile = nullptr;
int opt;
while ((opt = getopt(argc, argv, "")) != -1)
while ((opt = getopt(argc, argv, "o:")) != -1)
switch (opt)
{
// case 'c':
// mode_c = true;
// break;
// case 'r':
// mode_r = true;
// break;
// case 'm':
// mode_m = true;
// break;
// case 'x':
// mode_x = true;
// break;
// case 'y':
// mode_y = true;
// break;
// case 'z':
// mode_z = true;
// break;
// case 'C':
// chksum = true;
// break;
// case 'f':
// frames.insert(strtol(optarg, nullptr, 0));
// break;
// case 'o':
// outfile = optarg;
// break;
case 'o':
outfile = optarg;
break;
default:
goto help;
}
if (optind != argc) {
if (0) {
help:
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [options] < segdata.txt\n", argv[0]);
fprintf(stderr, "Usage: %s [options] file..\n", argv[0]);
fprintf(stderr, "\n");
// fprintf(stderr, " -c\n");
// fprintf(stderr, " continuation mode. output '*' for repeating patterns\n");
fprintf(stderr, " -o <filename>\n");
fprintf(stderr, " set output file\n");
fprintf(stderr, "\n");
return 1;
}
read_input();
if (optind != argc) {
while (optind != argc) {
printf("Reading %s.\n", argv[optind]);
std::ifstream f;
f.open(argv[optind]);
assert(!f.fail());
read_input(f, argv[optind++]);
}
} else {
printf("Reading from stding.\n");
read_input(std::cin, "stdin");
}
printf("#of segments: %d\n", int(segdata.size()));
printf("#of bits: %d\n", num_bits);
printf("#of tags: %d\n", num_tags);
FILE *f = stdout;
if (outfile) {
f = fopen(outfile, "w");
assert(f != nullptr);
}
int min_candidates = num_bits;
int max_candidates = 0;
float avg_candidates = 0;
for (int tag_idx = 0; tag_idx < num_tags; tag_idx++)
{
@ -184,19 +189,26 @@ help:
}
int num_candidates = std::accumulate(mask.begin(), mask.end(), 0);
min_candidates = std::min(min_candidates, num_candidates);
max_candidates = std::max(max_candidates, num_candidates);
avg_candidates += float(num_candidates) / num_tags;
printf("%s", tag_ids_r.at(tag_idx).c_str());
fprintf(f, "%s", tag_ids_r.at(tag_idx).c_str());
if (0 < num_candidates && num_candidates <= 4) {
for (int bit_idx = 0; bit_idx < num_bits; bit_idx++)
if (mask.at(bit_idx))
printf(" %s", bit_ids_r.at(bit_idx).c_str());
printf("\n");
fprintf(f, " %s", bit_ids_r.at(bit_idx).c_str());
fprintf(f, "\n");
} else {
printf(" <%d candidates>\n", num_candidates);
fprintf(f, " <%d candidates>\n", num_candidates);
}
}
printf("min #of candidates: %d\n", min_candidates);
printf("max #of candidates: %d\n", max_candidates);
printf("avg #of candidates: %f\n", avg_candidates);
return 0;
}