From 7379977c1d835e6a05b86f78ae75a42cda67e422 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Mon, 17 Sep 2018 19:13:09 -0700 Subject: [PATCH] timfuz: reorganize minitest, fixup Signed-off-by: John McMaster --- fuzzers/007-timing/test_unique/.gitignore | 3 + fuzzers/007-timing/test_unique/Makefile | 22 ++++ fuzzers/007-timing/test_unique/README.md | 11 ++ fuzzers/007-timing/test_unique/generate.sh | 9 ++ fuzzers/007-timing/test_unique/generate.tcl | 97 ++++++++++++++++ .../007-timing/test_unique}/node_unique.py | 19 +-- .../007-timing/test_unique}/perf_test.py | 0 .../007-timing/test_unique}/pip_unique.py | 21 ++-- fuzzers/007-timing/test_unique/top.v | 109 ++++++++++++++++++ .../007-timing/test_unique}/wire_unique.py | 19 +-- 10 files changed, 288 insertions(+), 22 deletions(-) create mode 100644 fuzzers/007-timing/test_unique/.gitignore create mode 100644 fuzzers/007-timing/test_unique/Makefile create mode 100644 fuzzers/007-timing/test_unique/README.md create mode 100755 fuzzers/007-timing/test_unique/generate.sh create mode 100644 fuzzers/007-timing/test_unique/generate.tcl rename {minitests/timfuz => fuzzers/007-timing/test_unique}/node_unique.py (86%) rename {minitests/timfuz => fuzzers/007-timing/test_unique}/perf_test.py (100%) rename {minitests/timfuz => fuzzers/007-timing/test_unique}/pip_unique.py (81%) create mode 100644 fuzzers/007-timing/test_unique/top.v rename {minitests/timfuz => fuzzers/007-timing/test_unique}/wire_unique.py (83%) diff --git a/fuzzers/007-timing/test_unique/.gitignore b/fuzzers/007-timing/test_unique/.gitignore new file mode 100644 index 00000000..374eddc2 --- /dev/null +++ b/fuzzers/007-timing/test_unique/.gitignore @@ -0,0 +1,3 @@ +specimen_* +build + diff --git a/fuzzers/007-timing/test_unique/Makefile b/fuzzers/007-timing/test_unique/Makefile new file mode 100644 index 00000000..f7dca553 --- /dev/null +++ b/fuzzers/007-timing/test_unique/Makefile @@ -0,0 +1,22 @@ +N := 1 +SPECIMENS := $(addprefix specimen_,$(shell seq -f '%03.0f' $(N))) +SPECIMENS_OK := $(addsuffix /OK,$(SPECIMENS)) + +all: $(SPECIMENS_OK) + +$(SPECIMENS_OK): + bash generate.sh $(subst /OK,,$@) || (if [ "$(BADPRJ_OK)" != 'Y' ] ; then exit 1; fi; exit 0) + touch $@ + +run: + $(MAKE) clean + $(MAKE) all + touch run.ok + +clean: + rm -rf specimen_[0-9][0-9][0-9]/ seg_clblx.segbits __pycache__ run.ok + rm -rf vivado*.log vivado_*.str vivado*.jou design *.bits *.dcp *.bit + rm -rf build + +.PHONY: all run clean + diff --git a/fuzzers/007-timing/test_unique/README.md b/fuzzers/007-timing/test_unique/README.md new file mode 100644 index 00000000..44db73b9 --- /dev/null +++ b/fuzzers/007-timing/test_unique/README.md @@ -0,0 +1,11 @@ +Characterizes how attributes vary across pips, wires, and nodes. Usage: + +``` +$ make +$ python3 pip_unique.py +$ python3 wire_unique.py +$ python3 node_unique.py +``` + +NOTE: this will take a long time + diff --git a/fuzzers/007-timing/test_unique/generate.sh b/fuzzers/007-timing/test_unique/generate.sh new file mode 100755 index 00000000..76583ac2 --- /dev/null +++ b/fuzzers/007-timing/test_unique/generate.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +set -ex + +source ${XRAY_GENHEADER} +TIMFUZ_DIR=$XRAY_DIR/fuzzers/007-timing + +vivado -mode batch -source ../generate.tcl + diff --git a/fuzzers/007-timing/test_unique/generate.tcl b/fuzzers/007-timing/test_unique/generate.tcl new file mode 100644 index 00000000..99fd39d0 --- /dev/null +++ b/fuzzers/007-timing/test_unique/generate.tcl @@ -0,0 +1,97 @@ +source ../../../../utils/utils.tcl + +proc build_design {} { + create_project -force -part $::env(XRAY_PART) design design + read_verilog ../../src/picorv32.v + read_verilog ../top.v + synth_design -top top + + puts "Locking pins" + set_property LOCK_PINS {I0:A1 I1:A2 I2:A3 I3:A4 I4:A5 I5:A6} \ + [get_cells -quiet -filter {REF_NAME == LUT6} -hierarchical] + + puts "Package stuff" + 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] + + puts "pblocking" + create_pblock roi + set roipb [get_pblocks roi] + set_property EXCLUDE_PLACEMENT 1 $roipb + add_cells_to_pblock $roipb [get_cells roi] + resize_pblock $roipb -add "$::env(XRAY_ROI)" + + puts "randplace" + randplace_pblock 50 roi + + set_property CFGBVS VCCO [current_design] + set_property CONFIG_VOLTAGE 3.3 [current_design] + set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + + puts "dedicated route" + set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] + + place_design + route_design + + write_checkpoint -force design.dcp + # disable combinitorial loop + # set_property IS_ENABLED 0 [get_drc_checks {LUTLP-1}] + #write_bitstream -force design.bit +} + +proc pips_all {} { + set outdir "." + set fp [open "$outdir/pip_all.txt" w] + set items [get_pips] + puts "Items: [llength $items]" + + set needspace 0 + set properties [list_property [lindex $items 0]] + foreach item $items { + set needspace 0 + foreach property $properties { + set val [get_property $property $item] + if {"$val" ne ""} { + if $needspace { + puts -nonewline $fp " " + } + puts -nonewline $fp "$property:$val" + set needspace 1 + } + } + puts $fp "" + } + close $fp +} +proc wires_all {} { + set outdir "." + set fp [open "$outdir/wire_all.txt" w] + set items [get_wires] + puts "Items: [llength $items]" + + set needspace 0 + set properties [list_property [lindex $items 0]] + foreach item $items { + set needspace 0 + foreach property $properties { + set val [get_property $property $item] + if {"$val" ne ""} { + if $needspace { + puts -nonewline $fp " " + } + puts -nonewline $fp "$property:$val" + set needspace 1 + } + } + puts $fp "" + } + close $fp +} + +build_design +pips_all +wires_all + diff --git a/minitests/timfuz/node_unique.py b/fuzzers/007-timing/test_unique/node_unique.py similarity index 86% rename from minitests/timfuz/node_unique.py rename to fuzzers/007-timing/test_unique/node_unique.py index 4a0630e7..6e87e438 100644 --- a/minitests/timfuz/node_unique.py +++ b/fuzzers/007-timing/test_unique/node_unique.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import re @@ -40,8 +42,8 @@ def run(node_fin, verbose=0): return anode['wname'] #return (anode['tile_type'], anode['wname']) - if nodei % 1000 == 0: - print 'Check node %d' % nodei + if nodei % 10000 == 0: + print('Check node %d, %u node types' % (nodei, len(refnodes))) # Existing node? try: refnode = refnodes[getk(anode)] @@ -62,10 +64,10 @@ def run(node_fin, verbose=0): if k in refnode and k in anode: def fail(): - print 'Mismatch on %s' % k - print refnode[k], anode[k] - print refnode['l'] - print anode['l'] + print('Mismatch on %s' % k) + print(refnode[k], anode[k]) + print(refnode['l']) + print(anode['l']) #assert 0 if k == 'SPEED_CLASS': @@ -97,6 +99,9 @@ if __name__ == '__main__': parser.add_argument('--verbose', type=int, help='') parser.add_argument( - 'node_fn_in', default='/dev/stdin', nargs='?', help='Input file') + 'node_fn_in', + default='specimen_001/wire_all.txt', + nargs='?', + help='Input file') args = parser.parse_args() run(open(args.node_fn_in, 'r'), verbose=args.verbose) diff --git a/minitests/timfuz/perf_test.py b/fuzzers/007-timing/test_unique/perf_test.py similarity index 100% rename from minitests/timfuz/perf_test.py rename to fuzzers/007-timing/test_unique/perf_test.py diff --git a/minitests/timfuz/pip_unique.py b/fuzzers/007-timing/test_unique/pip_unique.py similarity index 81% rename from minitests/timfuz/pip_unique.py rename to fuzzers/007-timing/test_unique/pip_unique.py index f49cb1ca..6df2f5b2 100644 --- a/minitests/timfuz/pip_unique.py +++ b/fuzzers/007-timing/test_unique/pip_unique.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import re @@ -29,8 +31,8 @@ def run(node_fin, verbose=0): return anode['wname'] return (anode['tile_type'], anode['wname']) - if nodei % 1000 == 0: - print 'Check node %d' % nodei + if nodei % 10000 == 0: + print('Check node %d, %u node types' % (nodei, len(refnodes))) # Existing node? try: refnode = refnodes[getk(anode)] @@ -56,14 +58,14 @@ def run(node_fin, verbose=0): if k in refnode and k in anode: def fail(): - print 'Mismatch on %s' % k - print refnode[k], anode[k] - print refnode['l'] - print anode['l'] + print('Mismatch on %s' % k) + print(refnode[k], anode[k]) + print(refnode['l']) + print(anode['l']) #assert 0 if refnode[k] != anode[k]: - print + print('') fail() # A key in one but not the other? elif k in refnode or k in anode: @@ -81,6 +83,9 @@ if __name__ == '__main__': parser.add_argument('--verbose', type=int, help='') parser.add_argument( - 'node_fn_in', default='/dev/stdin', nargs='?', help='Input file') + 'node_fn_in', + default='specimen_001/pip_all.txt', + nargs='?', + help='Input file') args = parser.parse_args() run(open(args.node_fn_in, 'r'), verbose=args.verbose) diff --git a/fuzzers/007-timing/test_unique/top.v b/fuzzers/007-timing/test_unique/top.v new file mode 100644 index 00000000..0cb9b8a3 --- /dev/null +++ b/fuzzers/007-timing/test_unique/top.v @@ -0,0 +1,109 @@ +//move some stuff to minitests/ncy0 + +`define SEED 32'h12345678 + +module top(input clk, stb, di, output do); + localparam integer DIN_N = 42; + localparam integer DOUT_N = 79; + + 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 #(.DIN_N(DIN_N), .DOUT_N(DOUT_N)) + roi ( + .clk(clk), + .din(din), + .dout(dout) + ); +endmodule + +module roi(input clk, input [DIN_N-1:0] din, output [DOUT_N-1:0] dout); + parameter integer DIN_N = -1; + parameter integer DOUT_N = -1; + + /* + //Take out for now to make sure LUTs are more predictable + picorv32 picorv32 ( + .clk(clk), + .resetn(din[0]), + .mem_valid(dout[0]), + .mem_instr(dout[1]), + .mem_ready(din[1]), + .mem_addr(dout[33:2]), + .mem_wdata(dout[66:34]), + .mem_wstrb(dout[70:67]), + .mem_rdata(din[33:2]) + ); + */ + + /* + randluts randluts ( + .din(din[41:34]), + .dout(dout[78:71]) + ); + */ + randluts #(.N(150)) randluts ( + .din(din[41:34]), + .dout(dout[78:71]) + ); +endmodule + +module randluts(input [7:0] din, output [7:0] dout); + parameter integer N = 250; + + function [31:0] xorshift32(input [31:0] xorin); + begin + xorshift32 = xorin; + xorshift32 = xorshift32 ^ (xorshift32 << 13); + xorshift32 = xorshift32 ^ (xorshift32 >> 17); + xorshift32 = xorshift32 ^ (xorshift32 << 5); + end + endfunction + + function [63:0] lutinit(input [7:0] a, b); + begin + lutinit[63:32] = xorshift32(xorshift32(xorshift32(xorshift32({a, b} ^ `SEED)))); + lutinit[31: 0] = xorshift32(xorshift32(xorshift32(xorshift32({b, a} ^ `SEED)))); + end + endfunction + + wire [(N+1)*8-1:0] nets; + + assign nets[7:0] = din; + assign dout = nets[(N+1)*8-1:N*8]; + + genvar i, j; + generate + for (i = 0; i < N; i = i+1) begin:is + for (j = 0; j < 8; j = j+1) begin:js + localparam integer k = xorshift32(xorshift32(xorshift32(xorshift32((i << 20) ^ (j << 10) ^ `SEED)))) & 255; + (* KEEP, DONT_TOUCH *) + LUT6 #( + .INIT(lutinit(i, j)) + ) lut ( + .I0(nets[8*i+(k+0)%8]), + .I1(nets[8*i+(k+1)%8]), + .I2(nets[8*i+(k+2)%8]), + .I3(nets[8*i+(k+3)%8]), + .I4(nets[8*i+(k+4)%8]), + .I5(nets[8*i+(k+5)%8]), + .O(nets[8*i+8+j]) + ); + end + end + endgenerate +endmodule diff --git a/minitests/timfuz/wire_unique.py b/fuzzers/007-timing/test_unique/wire_unique.py similarity index 83% rename from minitests/timfuz/wire_unique.py rename to fuzzers/007-timing/test_unique/wire_unique.py index c7b57272..4d286566 100644 --- a/minitests/timfuz/wire_unique.py +++ b/fuzzers/007-timing/test_unique/wire_unique.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import re @@ -29,8 +31,8 @@ def run(node_fin, verbose=0): return anode['wname'] #return (anode['tile_type'], anode['wname']) - if nodei % 1000 == 0: - print 'Check node %d' % nodei + if nodei % 10000 == 0: + print('Check node %d, %u node types' % (nodei, len(refnodes))) # Existing node? try: refnode = refnodes[getk(anode)] @@ -61,10 +63,10 @@ def run(node_fin, verbose=0): if k in refnode and k in anode: def fail(): - print 'Mismatch on %s' % k - print refnode[k], anode[k] - print refnode['l'] - print anode['l'] + print('Mismatch on %s' % k) + print(refnode[k], anode[k]) + print(refnode['l']) + print(anode['l']) #assert 0 if refnode[k] != anode[k]: @@ -86,6 +88,9 @@ if __name__ == '__main__': parser.add_argument('--verbose', type=int, help='') parser.add_argument( - 'node_fn_in', default='/dev/stdin', nargs='?', help='Input file') + 'node_fn_in', + default='specimen_001/wire_all.txt', + nargs='?', + help='Input file') args = parser.parse_args() run(open(args.node_fn_in, 'r'), verbose=args.verbose)