From 2f28ad2e5192f341b4559855f20a7e0d7e77ef05 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 23 Jan 2018 18:05:15 -0800 Subject: [PATCH 01/15] bassy3 LED demos Signed-off-by: John McMaster --- minitests/roi_harness/roi_demoscene.v | 149 ++++++++++++++++++++++++++ minitests/roi_harness/runme.tcl | 4 +- 2 files changed, 151 insertions(+), 2 deletions(-) create mode 100644 minitests/roi_harness/roi_demoscene.v diff --git a/minitests/roi_harness/roi_demoscene.v b/minitests/roi_harness/roi_demoscene.v new file mode 100644 index 00000000..8834d326 --- /dev/null +++ b/minitests/roi_harness/roi_demoscene.v @@ -0,0 +1,149 @@ +//See README and tcl for more info + +`default_nettype none + +`include "defines.v" + +module roi(input wire clk, + input wire [DIN_N-1:0] din, output wire [DOUT_N-1:0] dout); + parameter DIN_N = `DIN_N; + parameter DOUT_N = `DOUT_N; + + wire [DIN_N-1:0] din_lut; + wire [DOUT_N-1:0] dout_lut; + + genvar i; + generate + //CLK + (* KEEP, DONT_TOUCH *) + reg clk_reg; + always @(posedge clk) begin + clk_reg <= clk_reg; + end + + //DIN + for (i = 0; i < DIN_N; i = i+1) begin:ins + (* KEEP, DONT_TOUCH *) + LUT6 #( + .INIT(64'b01) + ) lut ( + .I0(din[i]), + .I1(1'b0), + .I2(1'b0), + .I3(1'b0), + .I4(1'b0), + .I5(1'b0), + .O(din_lut[i])); + end + + //DOUT + for (i = 0; i < DOUT_N; i = i+1) begin:outs + (* KEEP, DONT_TOUCH *) + LUT6 #( + .INIT(64'b01) + ) lut ( + .I0(dout_lut[i]), + .I1(1'b0), + .I2(1'b0), + .I3(1'b0), + .I4(1'b0), + .I5(1'b0), + .O(dout[i])); + end + endgenerate + + demoscene demoscene(.clk(clk), .din(din_lut), .dout(dout_lut)); +endmodule + +module demoscene(input wire clk, + input wire [DIN_N-1:0] din, output wire [DOUT_N-1:0] dout); + parameter DIN_N = `DIN_N; + parameter DOUT_N = `DOUT_N; + + //assign dout = 8'b10101010; + demoscene_scroll dut(.clk(clk), .din(din), .dout(dout)); +endmodule + +/* +Leftmost LED counts at one second +*/ +module demoscene_counter(input wire clk, + input wire [DIN_N-1:0] din, output wire [DOUT_N-1:0] dout); + parameter DIN_N = `DIN_N; + parameter DOUT_N = `DOUT_N; + /* + 100 MHz clock + Lets get MSB to 1 second + Need 27 bits + In [3]: math.log(100e6, 2) + Out[3]: 26.5754247590989 + */ + reg [26:0] div; + always @(posedge clk) begin + div <= div + 1'b1; + end + assign dout = div[26:19]; +endmodule + +//Loosely based on http://www.asic-world.com/code/hdl_models/lfsr.v +module lfsr(input wire clk, output wire dout); + reg [7:0] out = 8'hAA; + wire feedback = !(out[7] ^ out[3]); + + always @(posedge clk) begin + out <= {out[6],out[5], + out[4],out[3], + out[2],out[1], + out[0], feedback}; + end + assign dout = out[0]; +endmodule + +// http://www.fpga4fun.com/Counters3.html +module lfsr2(input wire clk, output wire dout); + reg [7:0] LFSR = 255; + wire feedback = LFSR[7]; + assign dout = LFSR[0]; + + always @(posedge clk) begin + LFSR[0] <= feedback; + LFSR[1] <= LFSR[0]; + LFSR[2] <= LFSR[1] ^ feedback; + LFSR[3] <= LFSR[2] ^ feedback; + LFSR[4] <= LFSR[3] ^ feedback; + LFSR[5] <= LFSR[4]; + LFSR[6] <= LFSR[5]; + LFSR[7] <= LFSR[6]; + end +endmodule +/* +Scrolls an LSFR across +*/ +module demoscene_scroll(input wire clk, + input wire [DIN_N-1:0] din, output wire [DOUT_N-1:0] dout); + parameter DIN_N = `DIN_N; + parameter DOUT_N = `DOUT_N; + + reg [26:0] div; + always @(posedge clk) begin + div <= div + 1'b1; + end + + wire randbit; + lfsr2 lfsr(.clk(clk), .dout(randbit)); + + reg [7:0] leds = 8'hCC; + reg last; + reg tick; + always @(posedge clk) begin + last <= div[23]; + tick <= div[23] ^ last; + + if (tick) begin + leds = {leds, randbit}; + end + end + + assign dout = leds; +endmodule + diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index 43f43748..b8b12396 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -199,7 +199,7 @@ if {$fixed_xdc eq ""} { set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] - set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] + #set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design] set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets clk_IBUF] @@ -428,6 +428,6 @@ if {$fixed_xdc eq ""} { } write_checkpoint -force $outdir/design.dcp -set_property BITSTREAM.GENERAL.DEBUGBITSTREAM YES [current_design] +#set_property BITSTREAM.GENERAL.DEBUGBITSTREAM YES [current_design] write_bitstream -force $outdir/design.bit From 941ae551c9ce46fbb140e71af9692334156f0202 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Mon, 29 Jan 2018 15:49:35 -0800 Subject: [PATCH 02/15] roi_harness: write design.txt into output dir Signed-off-by: John McMaster --- minitests/roi_harness/runme.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index b8b12396..ebe28930 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -350,7 +350,7 @@ proc route_via2 {net nodes} { } # XXX: maybe add IOB? -set fp [open "design.txt" w] +set fp [open "$outdir/design.txt" w] puts $fp "name node pin" # Manual routing if {$fixed_xdc eq ""} { From cb4b0889907d58fd4fef9eaafbf3aa901abe2fd6 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 10:48:08 -0800 Subject: [PATCH 03/15] roi_harness utility scripts Signed-off-by: John McMaster --- minitests/partial_reconfig_flow/v2bit.sh | 39 +++++++++++++++++++ minitests/roi_harness/fasm2bit.sh | 48 ++++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100755 minitests/partial_reconfig_flow/v2bit.sh create mode 100755 minitests/roi_harness/fasm2bit.sh diff --git a/minitests/partial_reconfig_flow/v2bit.sh b/minitests/partial_reconfig_flow/v2bit.sh new file mode 100755 index 00000000..c331cbf4 --- /dev/null +++ b/minitests/partial_reconfig_flow/v2bit.sh @@ -0,0 +1,39 @@ +set -ex + +fin=$1 +if [ -z "$fin" ] ; then + echo "need fin arg" + exit +fi +# fin=roi_blinky.v +prefix=$(echo $fin |sed "s/\.v//") +if [ "$fin" = "$prefix" ] ; then + echo "bad prefix" + exit +fi +echo "$fin => $prefix" + +make +mkdir -p $prefix + +vivado -mode batch -source /dev/stdin <hand_crafted.bit + +openocd -f openocd-basys3.cfg -c "init; pld load 0 hand_crafted.bit; exit" + From 0cea91bc07e3c99424aaf12631f87abfb730b739 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 10:49:02 -0800 Subject: [PATCH 04/15] roi_harness: dump tile entry/exit nodes Signed-off-by: John McMaster --- minitests/roi_harness/runme.tcl | 68 +++++++++++++++++---------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index ebe28930..d7e6fdc0 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -23,7 +23,7 @@ set X_BASE $XRAY_ROI_X0 set Y_BASE $XRAY_ROI_Y0 # set Y_DIN_BASE 100 -set Y_CLK_BASE $Y_BASE +set Y_CLK_BASE $Y_BASE # Clock lut in middle set Y_DIN_BASE [expr "$Y_CLK_BASE + 1"] # Sequential @@ -306,47 +306,47 @@ proc route_via2 {net nodes} { # net: net as string # nodes: string list of one or more intermediate routing nodes to visit - set net [get_nets $net] - # Start at the net source - set fixed_route [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] - # End at the net destination - # For sone reason this doesn't always show up - set site_pins [get_site_pins -filter {DIRECTION == IN} -of_objects $net] + set net [get_nets $net] + # Start at the net source + set fixed_route [get_nodes -of_objects [get_site_pins -filter {DIRECTION == OUT} -of_objects $net]] + # End at the net destination + # For sone reason this doesn't always show up + set site_pins [get_site_pins -filter {DIRECTION == IN} -of_objects $net] if {$site_pins eq ""} { puts "WARNING: could not find end node" #error "Could not find end node" } else { - set end_node [get_nodes -of_objects] - lappend nodes [$end_node] - } + set end_node [get_nodes -of_objects] + lappend nodes [$end_node] + } - puts "" - puts "Routing net $net:" + puts "" + puts "Routing net $net:" - foreach to_node $nodes { + foreach to_node $nodes { if {$to_node eq ""} { error "Empty node" } - # Node string to object - set to_node [get_nodes -of_objects [get_wires $to_node]] - # Start at last routed position - set from_node [lindex $fixed_route end] - # Let vivado do heavy liftin in between - set route [find_routing_path -quiet -from $from_node -to $to_node] - if {$route == ""} { - # Some errors print a huge route - puts [concat [string range " $from_node -> $to_node" 0 1000] ": no route found - assuming direct PIP"] - lappend fixed_route $to_node - } { - puts [concat [string range " $from_node -> $to_node: $route" 0 1000] "routed"] - set fixed_route [concat $fixed_route [lrange $route 1 end]] - } - set_property -quiet FIXED_ROUTE $fixed_route $net - } + # Node string to object + set to_node [get_nodes -of_objects [get_wires $to_node]] + # Start at last routed position + set from_node [lindex $fixed_route end] + # Let vivado do heavy liftin in between + set route [find_routing_path -quiet -from $from_node -to $to_node] + if {$route == ""} { + # Some errors print a huge route + puts [concat [string range " $from_node -> $to_node" 0 1000] ": no route found - assuming direct PIP"] + lappend fixed_route $to_node + } { + puts [concat [string range " $from_node -> $to_node: $route" 0 1000] "routed"] + set fixed_route [concat $fixed_route [lrange $route 1 end]] + } + set_property -quiet FIXED_ROUTE $fixed_route $net + } - set_property -quiet FIXED_ROUTE $fixed_route $net - puts "" + set_property -quiet FIXED_ROUTE $fixed_route $net + puts "" } # XXX: maybe add IOB? @@ -378,7 +378,8 @@ if {$fixed_xdc eq ""} { route_via2 "din_IBUF[$i]" "INT_R_X${x_EE2BEG3}Y${y}/EE2BEG3 $node" set net "din[$i]" set pin "$net2pin($net)" - puts $fp "$net $node $pin" + set more [get_wires -of_objects [get_nodes $node]] + puts $fp "$net $node $pin $more" set y [expr {$y + $PITCH}] } @@ -409,7 +410,8 @@ if {$fixed_xdc eq ""} { } set net "dout[$i]" set pin "$net2pin($net)" - puts $fp "$net $node $pin" + set more [get_wires -of_objects [get_nodes $node]] + puts $fp "$net $node $pin $more" set y [expr {$y + $PITCH}] } } From c06c2a8a8e3f22a476898ddecab312afee8308ad Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 11:21:42 -0800 Subject: [PATCH 05/15] roi_harness: add tile wire to metadata Signed-off-by: John McMaster --- minitests/roi_harness/runme.tcl | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index d7e6fdc0..9d960ac4 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -349,6 +349,13 @@ proc route_via2 {net nodes} { puts "" } +# Return the wire on the ROI boundary +proc node2wire {node} { + set wires [get_wires -of_objects [get_nodes $node]] + set wire [lsearch -inline $wires *VBRK*] + return $wire +} + # XXX: maybe add IOB? set fp [open "$outdir/design.txt" w] puts $fp "name node pin" @@ -361,10 +368,11 @@ if {$fixed_xdc eq ""} { # But we still need to record something, so lets force a route # FIXME: very ROI specific set node "CLK_HROW_TOP_R_X60Y130/CLK_HROW_CK_BUFHCLK_L0" + set wire [node2wire $node] route_via2 "clk_IBUF_BUFG" "$node" set net "clk" set pin "$net2pin($net)" - puts $fp "$net $node $pin" + puts $fp "$net $node $pin $wire" puts "Routing ROI inputs" # Arbitrary offset as observed @@ -378,8 +386,8 @@ if {$fixed_xdc eq ""} { route_via2 "din_IBUF[$i]" "INT_R_X${x_EE2BEG3}Y${y}/EE2BEG3 $node" set net "din[$i]" set pin "$net2pin($net)" - set more [get_wires -of_objects [get_nodes $node]] - puts $fp "$net $node $pin $more" + set wire [node2wire $node] + puts $fp "$net $node $pin $wire" set y [expr {$y + $PITCH}] } @@ -410,8 +418,8 @@ if {$fixed_xdc eq ""} { } set net "dout[$i]" set pin "$net2pin($net)" - set more [get_wires -of_objects [get_nodes $node]] - puts $fp "$net $node $pin $more" + set wire [node2wire $node] + puts $fp "$net $node $pin $wire" set y [expr {$y + $PITCH}] } } From 8148cd0d719bd0014e6694f9951b4321aaa910b2 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 11:25:57 -0800 Subject: [PATCH 06/15] simpleroute: enable library function use Signed-off-by: John McMaster --- tools/simpleroute.py | 132 +++++++++++++++++++++++-------------------- 1 file changed, 70 insertions(+), 62 deletions(-) mode change 100644 => 100755 tools/simpleroute.py diff --git a/tools/simpleroute.py b/tools/simpleroute.py old mode 100644 new mode 100755 index 28ac5b04..77efa09f --- a/tools/simpleroute.py +++ b/tools/simpleroute.py @@ -1,16 +1,6 @@ #!/usr/bin/env python3 -import getopt, sys, os, json, re - -if len(sys.argv) == 1 or (len(sys.argv) % 2) != 1: - print() - print("Usage: %s src1 dst1 [src2 dst2 [...]]" % sys.argv[0]) - print() - print( - "Example: %s VBRK_X29Y140/VBRK_ER1BEG2 VFRAME_X47Y113/VFRAME_EL1BEG2" % - sys.argv[0]) - print() - sys.exit(1) +import sys, os, json class MergeFind: @@ -98,67 +88,85 @@ for tile_type in ["int_l", "int_r"]: tile, dst, src) reverse_node_node[dst_node].add(src_node) -for argidx in range((len(sys.argv) - 1) // 2): - src_tile, src_wire = sys.argv[2 * argidx + 1].split("/") - dst_tile, dst_wire = sys.argv[2 * argidx + 2].split("/") - src_node = nodes.find((src_tile, src_wire)) - dst_node = nodes.find((dst_tile, dst_wire)) +def route(args): + for argidx in range((len(args)) // 2): + src_tile, src_wire = args[2 * argidx].split("/") + dst_tile, dst_wire = args[2 * argidx + 1].split("/") - print("Routing %s -> %s:" % (src_node, dst_node)) + src_node = nodes.find((src_tile, src_wire)) + dst_node = nodes.find((dst_tile, dst_wire)) - node_scores = dict() + print("Routing %s -> %s:" % (src_node, dst_node)) - def write_scores(nodes, count): - next_nodes = set() - for n in nodes: - if n in node_scores: - continue - node_scores[n] = count - if n == src_node: - return - if n in reverse_node_node: - for nn in reverse_node_node[n]: - if nn not in node_scores and nn not in blocked_nodes: - next_nodes.add(nn) - write_scores(next_nodes, count + 1) + node_scores = dict() - write_scores(set([dst_node]), 1) - print(" route length: %d" % node_scores[src_node]) + def write_scores(nodes, count): + next_nodes = set() + for n in nodes: + if n in node_scores: + continue + node_scores[n] = count + if n == src_node: + return + if n in reverse_node_node: + for nn in reverse_node_node[n]: + if nn not in node_scores and nn not in blocked_nodes: + next_nodes.add(nn) + write_scores(next_nodes, count + 1) - count = 0 - c = src_node - blocked_nodes.add(c) - print(" %4d: %s" % (count, c)) + write_scores(set([dst_node]), 1) + print(" route length: %d" % node_scores[src_node]) - score = node_scores[src_node] - while c != dst_node: - nn = None - for n in node_node_pip[c].keys(): - if n in node_scores and node_scores[n] < score: - nn, score = n, node_scores[n] - - pip = node_node_pip[c][nn] - active_pips.add(pip) - print(" %s" % pip) - - count += 1 - c = nn + count = 0 + c = src_node blocked_nodes.add(c) print(" %4d: %s" % (count, c)) -print("====") -pipnames = list() + score = node_scores[src_node] + while c != dst_node: + nn = None + for n in node_node_pip[c].keys(): + if n in node_scores and node_scores[n] < score: + nn, score = n, node_scores[n] -for pip in sorted(active_pips): - tile, dst, src = pip.split(".") - pipnames.append("%s/%s.%s->>%s" % (tile, tile[0:5], src, dst)) + pip = node_node_pip[c][nn] + active_pips.add(pip) + print(" %s" % pip) -print( - "highlight_objects -color orange [get_nodes -of_objects [get_wires {%s}]]" - % " ".join(["%s/%s" % n for n in sorted(blocked_nodes)])) -print("highlight_objects -color orange [get_pips {%s}]" % " ".join(pipnames)) + count += 1 + c = nn + blocked_nodes.add(c) + print(" %4d: %s" % (count, c)) -print("====") -for pip in sorted(active_pips): - print(pip) + print("====") + pipnames = list() + + for pip in sorted(active_pips): + tile, dst, src = pip.split(".") + pipnames.append("%s/%s.%s->>%s" % (tile, tile[0:5], src, dst)) + + print( + "highlight_objects -color orange [get_nodes -of_objects [get_wires {%s}]]" + % " ".join(["%s/%s" % n for n in sorted(blocked_nodes)])) + print( + "highlight_objects -color orange [get_pips {%s}]" % " ".join(pipnames)) + + print("====") + for pip in sorted(active_pips): + print(pip) + return active_pips + + +if __name__ == '__main__': + if len(sys.argv) == 1 or (len(sys.argv) % 2) != 1: + print() + print("Usage: %s src1 dst1 [src2 dst2 [...]]" % sys.argv[0]) + print("Where entires as tile/wire") + print() + print( + "Example: %s VBRK_X29Y140/VBRK_ER1BEG2 VFRAME_X47Y113/VFRAME_EL1BEG2" + % sys.argv[0]) + print() + sys.exit(1) + route(sys.argv[1:]) From 9849e537a5b4f555a8291ffe2b53dba1d84ebbeb Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:36:02 -0800 Subject: [PATCH 07/15] simpleroute: better stack overflow message, dont remember previous route Signed-off-by: John McMaster --- tools/simpleroute.py | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/tools/simpleroute.py b/tools/simpleroute.py index 77efa09f..6a78fb4a 100755 --- a/tools/simpleroute.py +++ b/tools/simpleroute.py @@ -68,8 +68,6 @@ print("Processing PIPs..") node_node_pip = dict() reverse_node_node = dict() -blocked_nodes = set() -active_pips = set() for tile_type in ["int_l", "int_r"]: with open("%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), @@ -90,6 +88,9 @@ for tile_type in ["int_l", "int_r"]: def route(args): + active_pips = set() + blocked_nodes = set() + for argidx in range((len(args)) // 2): src_tile, src_wire = args[2 * argidx].split("/") dst_tile, dst_wire = args[2 * argidx + 1].split("/") @@ -115,7 +116,10 @@ def route(args): next_nodes.add(nn) write_scores(next_nodes, count + 1) - write_scores(set([dst_node]), 1) + try: + write_scores(set([dst_node]), 1) + except RecursionError as e: + raise Exception("Could not find route for node %s" % (dst_node,)) from None print(" route length: %d" % node_scores[src_node]) count = 0 From c5496632ede2face04bbe17963348718cc4155c9 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:36:43 -0800 Subject: [PATCH 08/15] fasm2bit: bit argument. remove prog hack Signed-off-by: John McMaster --- minitests/roi_harness/fasm2bit.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/minitests/roi_harness/fasm2bit.sh b/minitests/roi_harness/fasm2bit.sh index 0f064664..3e7798c9 100755 --- a/minitests/roi_harness/fasm2bit.sh +++ b/minitests/roi_harness/fasm2bit.sh @@ -14,9 +14,18 @@ if [ -z "$bit_in" ] ; then echo "need .bit arg" exit fi +bit_out=$3 +if [ -z "$bit_out" ] ; then + bit_out=$(echo $fasm_in |sed s/.fasm/.bit/) + if [ "$bit_out" = "$fasm_in" ] ; then + echo "Expected fasm file" + exit 1 + fi +fi echo "Design .fasm: $fasm_in" echo "Harness .bit: $bit_in" +echo "Out .bit: $bit_out" ${XRAY_DIR}/tools/fasm2frame.py $fasm_in roi_partial.frm @@ -42,7 +51,7 @@ xxd -p -s 0x216abf $bit_in | \ fold -w 40 | \ xxd -r -p - final_sequence.bin -cat init_sequence.bit no_headers.bin final_sequence.bin >hand_crafted.bit +cat init_sequence.bit no_headers.bin final_sequence.bin >$bit_out -openocd -f openocd-basys3.cfg -c "init; pld load 0 hand_crafted.bit; exit" +#openocd -f $XRAY_DIR/utils/openocd/board-digilent-basys3.cfg -c "init; pld load 0 $bit_out; exit" From 618fbf87c4d2618c2d89210d41adc3d476ae349e Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:37:10 -0800 Subject: [PATCH 09/15] roi_harness runme: add missing wire to header Signed-off-by: John McMaster --- minitests/roi_harness/runme.tcl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/minitests/roi_harness/runme.tcl b/minitests/roi_harness/runme.tcl index 9d960ac4..bb793082 100644 --- a/minitests/roi_harness/runme.tcl +++ b/minitests/roi_harness/runme.tcl @@ -358,7 +358,7 @@ proc node2wire {node} { # XXX: maybe add IOB? set fp [open "$outdir/design.txt" w] -puts $fp "name node pin" +puts $fp "name node pin wire" # Manual routing if {$fixed_xdc eq ""} { set x $X_BASE From 2a3eebdd9d474120f3764c8a898472bd5bfda897 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:39:09 -0800 Subject: [PATCH 10/15] fasm2frame: dont print nested exception Signed-off-by: John McMaster --- tools/fasm2frame.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/fasm2frame.py b/tools/fasm2frame.py index c4e845a3..d844d264 100755 --- a/tools/fasm2frame.py +++ b/tools/fasm2frame.py @@ -226,7 +226,7 @@ def run(f_in, f_out, sparse=False, debug=False): except KeyError: raise FASMSyntaxError( "Segment DB %s, key %s not found from line '%s'" % - (segj['type'], db_k, l)) + (segj['type'], db_k, l)) from None if not value: # If its binary, allow omitted value default to 1 From 12516c53fb74bc8afc0dea8617ecff902d0131af Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:43:18 -0800 Subject: [PATCH 11/15] roi_harness: Basys3 LED switch demo Signed-off-by: John McMaster --- minitests/roi_harness/.gitignore | 4 ++ minitests/roi_harness/demo_sw_led.py | 31 ++++++++++++ minitests/roi_harness/demo_sw_led_fasm.py | 57 +++++++++++++++++++++++ minitests/roi_harness/test_demo_sw_led.py | 16 +++++++ 4 files changed, 108 insertions(+) create mode 100644 minitests/roi_harness/demo_sw_led.py create mode 100644 minitests/roi_harness/demo_sw_led_fasm.py create mode 100644 minitests/roi_harness/test_demo_sw_led.py diff --git a/minitests/roi_harness/.gitignore b/minitests/roi_harness/.gitignore index dd262534..b24efbad 100644 --- a/minitests/roi_harness/.gitignore +++ b/minitests/roi_harness/.gitignore @@ -7,3 +7,7 @@ /vivado* /design.txt /out_* +/*.fasm +/*.bit +/*.bin +/*.frm diff --git a/minitests/roi_harness/demo_sw_led.py b/minitests/roi_harness/demo_sw_led.py new file mode 100644 index 00000000..161151f1 --- /dev/null +++ b/minitests/roi_harness/demo_sw_led.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 + +import subprocess +import demo_sw_led_fasm +import os + +def run(roi_dir, swn, ledn): + design_txt_fn = roi_dir + '/design.txt' + bit_ref_fn = roi_dir + '/design.bit' + fasm_fn = 'demo_sw_led.fasm' + bit_out_fn = 'demo_sw_led.bit' + ocd_cfg = os.getenv('XRAY_DIR') + '/utils/openocd/board-digilent-basys3.cfg' + + # Clean up old tmp files to be sure we are generating them fresh + subprocess.call('rm -f %s %s' % (fasm_fn, bit_out_fn), shell=True) + + # subprocess.shell("python3 demo_sw_led.py out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev/design.txt 0 0 demo.fasm") + demo_sw_led_fasm.run(open(design_txt_fn, 'r'), swn, ledn, open(fasm_fn, 'w')) + subprocess.check_call("./fasm2bit.sh %s %s %s" % (fasm_fn, bit_ref_fn , bit_out_fn), shell=True) + subprocess.check_call('openocd -f %s -c "init; pld load 0 %s; exit"' % (ocd_cfg, bit_out_fn), shell=True) + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser(description='Basys3 switch to LED interconnect demo. Compiles and programs') + parser.add_argument('roi_dir', help='ROI project dir for harness .bit and metadata.txt') + parser.add_argument('sw', type=int, help='Switch to use') + parser.add_argument('led', type=int, help='LED to use') + + args = parser.parse_args() + run(args.roi_dir, args.sw, args.led) diff --git a/minitests/roi_harness/demo_sw_led_fasm.py b/minitests/roi_harness/demo_sw_led_fasm.py new file mode 100644 index 00000000..a773fee2 --- /dev/null +++ b/minitests/roi_harness/demo_sw_led_fasm.py @@ -0,0 +1,57 @@ +#!/usr/bin/env python3 + +import sys +import os +sys.path.append(os.getenv("XRAY_DIR") + "/tools") +import simpleroute + +print() +print('ready') + +def load_design(f): + ''' + name node pin wire + clk CLK_HROW_TOP_R_X60Y130/CLK_HROW_CK_BUFHCLK_L0 W5 HCLK_VBRK_X34Y130/HCLK_VBRK_CK_BUFHCLK0 + din[0] INT_R_X9Y100/NE2BEG3 V17 VBRK_X29Y106/VBRK_NE2A3 + ''' + ret = {} + f.readline() + for l in f: + l = l.strip() + name,node,pin,wire = l.split(' ') + ret[name] = wire + return ret + +def route2fasm(route, out_f): + pips = simpleroute.route(route) + for pip in pips: + # INT_L_X10Y122.NL1BEG2.NE2END3 + # to + # INT_L_X10Y122.NL1BEG2 NE2END3 + doti = pip.rfind('.') + pip = pip[0:doti] + ' ' + pip[doti + 1:] + out_f.write(pip + '\n') + +def run(design_f, swn, ledn, out_f): + name2wire = load_design(design_f) + led_name = 'dout[%d]' % ledn + sw_name = 'din[%d]' % swn + led_wire = name2wire[led_name] + sw_wire = name2wire[sw_name] + print('Routing %s (%s) => %s (%s)' % (sw_wire, sw_name, led_wire, led_name)) + + route2fasm((sw_wire, led_wire), out_f) + # XXX: terminate LEDs so they are off? + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser(description='Switch to LED interconnect demo: FASM generator') + parser.add_argument('design_txt', help='ROI metadata file') + parser.add_argument('sw', type=int, help='Switch to use') + parser.add_argument('led', type=int, help='LED to use') + # For now can't use stdout since simpleroute is spewing out prints + parser.add_argument('out_fasm', help='Output .fasm file') + + args = parser.parse_args() + run(open(args.design_txt, 'r'), args.sw, args.led, open(args.out_fasm, 'w')) diff --git a/minitests/roi_harness/test_demo_sw_led.py b/minitests/roi_harness/test_demo_sw_led.py new file mode 100644 index 00000000..0a35abd6 --- /dev/null +++ b/minitests/roi_harness/test_demo_sw_led.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python3 + +import unittest +import demo_sw_led + +class TestStringMethods(unittest.TestCase): + def test_all(self): + for i in range(8): + print() + print() + print() + print(i) + demo_sw_led.run('out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev', i, i) + +if __name__ == '__main__': + unittest.main() From 8da9f4f57245a77fb0a8e345f76cb2dcf95021a1 Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:45:29 -0800 Subject: [PATCH 12/15] roi_harness: fix formatting Signed-off-by: John McMaster --- minitests/roi_harness/demo_sw_led.py | 25 ++++++++++++++++------- minitests/roi_harness/demo_sw_led_fasm.py | 18 +++++++++++----- minitests/roi_harness/test_demo_sw_led.py | 2 ++ tools/simpleroute.py | 3 ++- 4 files changed, 35 insertions(+), 13 deletions(-) diff --git a/minitests/roi_harness/demo_sw_led.py b/minitests/roi_harness/demo_sw_led.py index 161151f1..3ffb089d 100644 --- a/minitests/roi_harness/demo_sw_led.py +++ b/minitests/roi_harness/demo_sw_led.py @@ -4,28 +4,39 @@ import subprocess import demo_sw_led_fasm import os + def run(roi_dir, swn, ledn): design_txt_fn = roi_dir + '/design.txt' bit_ref_fn = roi_dir + '/design.bit' fasm_fn = 'demo_sw_led.fasm' bit_out_fn = 'demo_sw_led.bit' - ocd_cfg = os.getenv('XRAY_DIR') + '/utils/openocd/board-digilent-basys3.cfg' + ocd_cfg = os.getenv( + 'XRAY_DIR') + '/utils/openocd/board-digilent-basys3.cfg' # Clean up old tmp files to be sure we are generating them fresh subprocess.call('rm -f %s %s' % (fasm_fn, bit_out_fn), shell=True) # subprocess.shell("python3 demo_sw_led.py out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev/design.txt 0 0 demo.fasm") - demo_sw_led_fasm.run(open(design_txt_fn, 'r'), swn, ledn, open(fasm_fn, 'w')) - subprocess.check_call("./fasm2bit.sh %s %s %s" % (fasm_fn, bit_ref_fn , bit_out_fn), shell=True) - subprocess.check_call('openocd -f %s -c "init; pld load 0 %s; exit"' % (ocd_cfg, bit_out_fn), shell=True) + demo_sw_led_fasm.run( + open(design_txt_fn, 'r'), swn, ledn, open(fasm_fn, 'w')) + subprocess.check_call( + "./fasm2bit.sh %s %s %s" % (fasm_fn, bit_ref_fn, bit_out_fn), + shell=True) + subprocess.check_call( + 'openocd -f %s -c "init; pld load 0 %s; exit"' % (ocd_cfg, bit_out_fn), + shell=True) + if __name__ == '__main__': import argparse - parser = argparse.ArgumentParser(description='Basys3 switch to LED interconnect demo. Compiles and programs') - parser.add_argument('roi_dir', help='ROI project dir for harness .bit and metadata.txt') + parser = argparse.ArgumentParser( + description= + 'Basys3 switch to LED interconnect demo. Compiles and programs') + parser.add_argument( + 'roi_dir', help='ROI project dir for harness .bit and metadata.txt') parser.add_argument('sw', type=int, help='Switch to use') parser.add_argument('led', type=int, help='LED to use') - + args = parser.parse_args() run(args.roi_dir, args.sw, args.led) diff --git a/minitests/roi_harness/demo_sw_led_fasm.py b/minitests/roi_harness/demo_sw_led_fasm.py index a773fee2..e2027c8c 100644 --- a/minitests/roi_harness/demo_sw_led_fasm.py +++ b/minitests/roi_harness/demo_sw_led_fasm.py @@ -8,6 +8,7 @@ import simpleroute print() print('ready') + def load_design(f): ''' name node pin wire @@ -18,10 +19,11 @@ def load_design(f): f.readline() for l in f: l = l.strip() - name,node,pin,wire = l.split(' ') + name, node, pin, wire = l.split(' ') ret[name] = wire return ret + def route2fasm(route, out_f): pips = simpleroute.route(route) for pip in pips: @@ -32,26 +34,32 @@ def route2fasm(route, out_f): pip = pip[0:doti] + ' ' + pip[doti + 1:] out_f.write(pip + '\n') + def run(design_f, swn, ledn, out_f): name2wire = load_design(design_f) led_name = 'dout[%d]' % ledn sw_name = 'din[%d]' % swn led_wire = name2wire[led_name] sw_wire = name2wire[sw_name] - print('Routing %s (%s) => %s (%s)' % (sw_wire, sw_name, led_wire, led_name)) + print( + 'Routing %s (%s) => %s (%s)' % (sw_wire, sw_name, led_wire, led_name)) route2fasm((sw_wire, led_wire), out_f) # XXX: terminate LEDs so they are off? + if __name__ == '__main__': import argparse - parser = argparse.ArgumentParser(description='Switch to LED interconnect demo: FASM generator') + parser = argparse.ArgumentParser( + description='Switch to LED interconnect demo: FASM generator') parser.add_argument('design_txt', help='ROI metadata file') parser.add_argument('sw', type=int, help='Switch to use') parser.add_argument('led', type=int, help='LED to use') # For now can't use stdout since simpleroute is spewing out prints parser.add_argument('out_fasm', help='Output .fasm file') - + args = parser.parse_args() - run(open(args.design_txt, 'r'), args.sw, args.led, open(args.out_fasm, 'w')) + run( + open(args.design_txt, 'r'), args.sw, args.led, open( + args.out_fasm, 'w')) diff --git a/minitests/roi_harness/test_demo_sw_led.py b/minitests/roi_harness/test_demo_sw_led.py index 0a35abd6..cd5b77fd 100644 --- a/minitests/roi_harness/test_demo_sw_led.py +++ b/minitests/roi_harness/test_demo_sw_led.py @@ -3,6 +3,7 @@ import unittest import demo_sw_led + class TestStringMethods(unittest.TestCase): def test_all(self): for i in range(8): @@ -12,5 +13,6 @@ class TestStringMethods(unittest.TestCase): print(i) demo_sw_led.run('out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev', i, i) + if __name__ == '__main__': unittest.main() diff --git a/tools/simpleroute.py b/tools/simpleroute.py index 6a78fb4a..5691f867 100755 --- a/tools/simpleroute.py +++ b/tools/simpleroute.py @@ -119,7 +119,8 @@ def route(args): try: write_scores(set([dst_node]), 1) except RecursionError as e: - raise Exception("Could not find route for node %s" % (dst_node,)) from None + raise Exception("Could not find route for node %s" % + (dst_node, )) from None print(" route length: %d" % node_scores[src_node]) count = 0 From c8ad3e219b26ab36bd9c6b5fcb1c015c751aab3f Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 14:50:13 -0800 Subject: [PATCH 13/15] roi_harness: add README info, chmod +x Signed-off-by: John McMaster --- minitests/roi_harness/README.txt | 4 ++++ minitests/roi_harness/demo_sw_led.py | 0 minitests/roi_harness/demo_sw_led_fasm.py | 0 minitests/roi_harness/test_demo_sw_led.py | 0 4 files changed, 4 insertions(+) mode change 100644 => 100755 minitests/roi_harness/demo_sw_led.py mode change 100644 => 100755 minitests/roi_harness/demo_sw_led_fasm.py mode change 100644 => 100755 minitests/roi_harness/test_demo_sw_led.py diff --git a/minitests/roi_harness/README.txt b/minitests/roi_harness/README.txt index 2f24f2da..c81a5ad7 100644 --- a/minitests/roi_harness/README.txt +++ b/minitests/roi_harness/README.txt @@ -17,3 +17,7 @@ To build the baseline harness: To build a sample Vivado design using the harness: XRAY_ROIV=roi_inv.v XRAY_FIXED_XDC=out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev/fixed_noclk.xdc ./runme.sh Note: this was intended for verification only and not as an end user flow (they should use SymbiFlow) + +To use the harness for the basys3 demo, do something like: +python3 demo_sw_led.py out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev 3 2 +This example connects switch 3 to LED 2 diff --git a/minitests/roi_harness/demo_sw_led.py b/minitests/roi_harness/demo_sw_led.py old mode 100644 new mode 100755 diff --git a/minitests/roi_harness/demo_sw_led_fasm.py b/minitests/roi_harness/demo_sw_led_fasm.py old mode 100644 new mode 100755 diff --git a/minitests/roi_harness/test_demo_sw_led.py b/minitests/roi_harness/test_demo_sw_led.py old mode 100644 new mode 100755 From a7092468f9ac1469c6a98250529e5e309fe7192b Mon Sep 17 00:00:00 2001 From: John McMaster Date: Tue, 30 Jan 2018 18:15:19 -0800 Subject: [PATCH 14/15] simpleroute: pickle to improve performance Signed-off-by: John McMaster --- tools/simpleroute.py | 124 +++++++++++++++++++++++++------------------ 1 file changed, 73 insertions(+), 51 deletions(-) diff --git a/tools/simpleroute.py b/tools/simpleroute.py index 5691f867..86139616 100755 --- a/tools/simpleroute.py +++ b/tools/simpleroute.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 import sys, os, json +import pickle class MergeFind: @@ -21,70 +22,91 @@ class MergeFind: return a -print("Reading database..") +def db_gen(): + print("Reading database..") -with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), - os.getenv("XRAY_DATABASE")), "r") as f: - tiles = json.load(f)["tiles"] + with open("%s/%s/tilegrid.json" % (os.getenv("XRAY_DATABASE_DIR"), + os.getenv("XRAY_DATABASE")), "r") as f: + tiles = json.load(f)["tiles"] -with open("%s/%s/tileconn.json" % (os.getenv("XRAY_DATABASE_DIR"), - os.getenv("XRAY_DATABASE")), "r") as f: - tileconn = json.load(f) + with open("%s/%s/tileconn.json" % (os.getenv("XRAY_DATABASE_DIR"), + os.getenv("XRAY_DATABASE")), "r") as f: + tileconn = json.load(f) -type_to_tiles = dict() -grid_to_tile = dict() -nodes = MergeFind() + type_to_tiles = dict() + grid_to_tile = dict() + nodes = MergeFind() -for tile, tiledata in tiles.items(): - if tiledata["type"] not in type_to_tiles: - type_to_tiles[tiledata["type"]] = list() - type_to_tiles[tiledata["type"]].append(tile) - grid_to_tile[(tiledata["grid_x"], tiledata["grid_y"])] = tile + for tile, tiledata in tiles.items(): + if tiledata["type"] not in type_to_tiles: + type_to_tiles[tiledata["type"]] = list() + type_to_tiles[tiledata["type"]].append(tile) + grid_to_tile[(tiledata["grid_x"], tiledata["grid_y"])] = tile -print("Processing tileconn..") + print("Processing tileconn..") -for entry in tileconn: - type_a, type_b = entry["tile_types"] - for tile_a in type_to_tiles[type_a]: - tiledata_a = tiles[tile_a] - grid_a = (tiledata_a["grid_x"], tiledata_a["grid_y"]) - grid_b = ( - grid_a[0] + entry["grid_deltas"][0], - grid_a[1] + entry["grid_deltas"][1]) + for entry in tileconn: + type_a, type_b = entry["tile_types"] + for tile_a in type_to_tiles[type_a]: + tiledata_a = tiles[tile_a] + grid_a = (tiledata_a["grid_x"], tiledata_a["grid_y"]) + grid_b = ( + grid_a[0] + entry["grid_deltas"][0], + grid_a[1] + entry["grid_deltas"][1]) - if grid_b not in grid_to_tile: - continue + if grid_b not in grid_to_tile: + continue - tile_b = grid_to_tile[grid_b] - tiledata_b = tiles[tile_b] + tile_b = grid_to_tile[grid_b] + tiledata_b = tiles[tile_b] - if tiledata_b["type"] != type_b: - continue + if tiledata_b["type"] != type_b: + continue - for pair in entry["wire_pairs"]: - nodes.merge((tile_a, pair[0]), (tile_b, pair[1])) + for pair in entry["wire_pairs"]: + nodes.merge((tile_a, pair[0]), (tile_b, pair[1])) -print("Processing PIPs..") + print("Processing PIPs..") -node_node_pip = dict() -reverse_node_node = dict() + node_node_pip = dict() + reverse_node_node = dict() -for tile_type in ["int_l", "int_r"]: - with open("%s/%s/segbits_%s.db" % (os.getenv("XRAY_DATABASE_DIR"), - os.getenv("XRAY_DATABASE"), tile_type), - "r") as f: - for line in f: - _, dst, src = line.split()[0].split(".") - for tile in type_to_tiles[tile_type.upper()]: - src_node = nodes.find((tile, src)) - dst_node = nodes.find((tile, dst)) - if src_node not in node_node_pip: - node_node_pip[src_node] = dict() - if dst_node not in reverse_node_node: - reverse_node_node[dst_node] = set() - node_node_pip[src_node][dst_node] = "%s.%s.%s" % ( - tile, dst, src) - reverse_node_node[dst_node].add(src_node) + for tile_type in ["int_l", "int_r"]: + with open("%s/%s/segbits_%s.db" % + (os.getenv("XRAY_DATABASE_DIR"), os.getenv("XRAY_DATABASE"), + tile_type), "r") as f: + for line in f: + _, dst, src = line.split()[0].split(".") + for tile in type_to_tiles[tile_type.upper()]: + src_node = nodes.find((tile, src)) + dst_node = nodes.find((tile, dst)) + if src_node not in node_node_pip: + node_node_pip[src_node] = dict() + if dst_node not in reverse_node_node: + reverse_node_node[dst_node] = set() + node_node_pip[src_node][dst_node] = "%s.%s.%s" % ( + tile, dst, src) + reverse_node_node[dst_node].add(src_node) + + return type_to_tiles, grid_to_tile, nodes, node_node_pip, reverse_node_node + + +def db_load(): + # Takes a while. Speed things up + picklef = os.getenv('XRAY_DIR') + '/tools/simpleroute.p' + if os.path.exists(picklef): + #print('Pickle: load') + db_res = pickle.load(open(picklef, 'rb')) + else: + #print('Pickle: rebuilding') + db_res = db_gen() + #print('Pickle: save') + pickle.dump(db_res, open(picklef, 'wb')) + return db_res + + +type_to_tiles, grid_to_tile, nodes, node_node_pip, reverse_node_node = db_load( +) def route(args): From 1a7e6919f80c8da3352b9ce33c49473b2ee088db Mon Sep 17 00:00:00 2001 From: John McMaster Date: Thu, 1 Feb 2018 11:16:52 -0800 Subject: [PATCH 15/15] partial_reconfig: remove obsolete v2bit script Signed-off-by: John McMaster --- minitests/partial_reconfig_flow/v2bit.sh | 39 ------------------------ 1 file changed, 39 deletions(-) delete mode 100755 minitests/partial_reconfig_flow/v2bit.sh diff --git a/minitests/partial_reconfig_flow/v2bit.sh b/minitests/partial_reconfig_flow/v2bit.sh deleted file mode 100755 index c331cbf4..00000000 --- a/minitests/partial_reconfig_flow/v2bit.sh +++ /dev/null @@ -1,39 +0,0 @@ -set -ex - -fin=$1 -if [ -z "$fin" ] ; then - echo "need fin arg" - exit -fi -# fin=roi_blinky.v -prefix=$(echo $fin |sed "s/\.v//") -if [ "$fin" = "$prefix" ] ; then - echo "bad prefix" - exit -fi -echo "$fin => $prefix" - -make -mkdir -p $prefix - -vivado -mode batch -source /dev/stdin <