Merge pull request #71 from mcmasterg/demoscene
roi_harness Basys3 demo
diff --git a/minitests/roi_harness/.gitignore b/minitests/roi_harness/.gitignore
index dd26253..b24efba 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/README.txt b/minitests/roi_harness/README.txt
index 2f24f2d..c81a5ad 100644
--- a/minitests/roi_harness/README.txt
+++ b/minitests/roi_harness/README.txt
@@ -17,3 +17,7 @@
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
new file mode 100755
index 0000000..3ffb089
--- /dev/null
+++ b/minitests/roi_harness/demo_sw_led.py
@@ -0,0 +1,42 @@
+#!/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 100755
index 0000000..e2027c8
--- /dev/null
+++ b/minitests/roi_harness/demo_sw_led_fasm.py
@@ -0,0 +1,65 @@
+#!/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/fasm2bit.sh b/minitests/roi_harness/fasm2bit.sh
new file mode 100755
index 0000000..3e7798c
--- /dev/null
+++ b/minitests/roi_harness/fasm2bit.sh
@@ -0,0 +1,57 @@
+# Example pre-req
+# ./runme.sh
+# XRAY_ROIV=roi_inv.v XRAY_FIXED_XDC=out_xc7a35tcpg236-1_BASYS3-SWBUT_roi_basev/fixed_noclk.xdc ./runme.sh
+
+set -ex
+
+fasm_in=$1
+if [ -z "$fasm_in" ] ; then
+ echo "need .fasm arg"
+ exit
+fi
+bit_in=$2
+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
+
+${XRAY_TOOLS_DIR}/xc7patch \
+ --part_file ${XRAY_PART_YAML} \
+ --bitstream_file $bit_in \
+ --frm_file roi_partial.frm \
+ --output_file patched.bin
+
+# WARNING: these values need to be tweaked if anything about the
+# Vivado-generated design changes.
+xxd -p -l 0x147 $bit_in | xxd -r -p - init_sequence.bit
+
+# WARNING: these values need to be tweaked if anything about the
+# Vivado-generated design changes.
+xxd -p -s 0x18 patched.bin | xxd -r -p - no_headers.bin
+
+# WARNING: these values need to be tweaked if anything about the
+# Vivado-generated design changes.
+xxd -p -s 0x216abf $bit_in | \
+ tr -d '\n' | \
+ sed -e 's/30000001.\{8\}/3000800100000007/g' | \
+ fold -w 40 | \
+ xxd -r -p - final_sequence.bin
+
+cat init_sequence.bit no_headers.bin final_sequence.bin >$bit_out
+
+#openocd -f $XRAY_DIR/utils/openocd/board-digilent-basys3.cfg -c "init; pld load 0 $bit_out; exit"
+
diff --git a/minitests/roi_harness/roi_demoscene.v b/minitests/roi_harness/roi_demoscene.v
new file mode 100644
index 0000000..8834d32
--- /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 43f4374..bb79308 100644
--- a/minitests/roi_harness/runme.tcl
+++ b/minitests/roi_harness/runme.tcl
@@ -23,7 +23,7 @@
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
@@ -199,7 +199,7 @@
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]
@@ -306,52 +306,59 @@
# 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 ""
+}
+
+# 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 "design.txt" w]
-puts $fp "name node pin"
+set fp [open "$outdir/design.txt" w]
+puts $fp "name node pin wire"
# Manual routing
if {$fixed_xdc eq ""} {
set x $X_BASE
@@ -361,10 +368,11 @@
# 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,7 +386,8 @@
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 wire [node2wire $node]
+ puts $fp "$net $node $pin $wire"
set y [expr {$y + $PITCH}]
}
@@ -409,7 +418,8 @@
}
set net "dout[$i]"
set pin "$net2pin($net)"
- puts $fp "$net $node $pin"
+ set wire [node2wire $node]
+ puts $fp "$net $node $pin $wire"
set y [expr {$y + $PITCH}]
}
}
@@ -428,6 +438,6 @@
}
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
diff --git a/minitests/roi_harness/test_demo_sw_led.py b/minitests/roi_harness/test_demo_sw_led.py
new file mode 100755
index 0000000..cd5b77f
--- /dev/null
+++ b/minitests/roi_harness/test_demo_sw_led.py
@@ -0,0 +1,18 @@
+#!/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()
diff --git a/tools/fasm2frame.py b/tools/fasm2frame.py
index c4e845a..d844d26 100755
--- a/tools/fasm2frame.py
+++ b/tools/fasm2frame.py
@@ -226,7 +226,7 @@
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
diff --git a/tools/simpleroute.py b/tools/simpleroute.py
old mode 100644
new mode 100755
index 28ac5b0..8613961
--- a/tools/simpleroute.py
+++ b/tools/simpleroute.py
@@ -1,16 +1,7 @@
#!/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
+import pickle
class MergeFind:
@@ -31,134 +22,178 @@
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
-
- tile_b = grid_to_tile[grid_b]
- tiledata_b = tiles[tile_b]
-
- if tiledata_b["type"] != type_b:
- continue
-
- for pair in entry["wire_pairs"]:
- nodes.merge((tile_a, pair[0]), (tile_b, pair[1]))
-
-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"),
- 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 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))
-
- print("Routing %s -> %s:" % (src_node, dst_node))
-
- node_scores = dict()
-
- def write_scores(nodes, count):
- next_nodes = set()
- for n in nodes:
- if n in node_scores:
+ if grid_b not in grid_to_tile:
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)
- write_scores(set([dst_node]), 1)
- print(" route length: %d" % node_scores[src_node])
+ tile_b = grid_to_tile[grid_b]
+ tiledata_b = tiles[tile_b]
- count = 0
- c = src_node
- blocked_nodes.add(c)
- print(" %4d: %s" % (count, c))
+ if tiledata_b["type"] != type_b:
+ continue
- 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 pair in entry["wire_pairs"]:
+ nodes.merge((tile_a, pair[0]), (tile_b, pair[1]))
- pip = node_node_pip[c][nn]
- active_pips.add(pip)
- print(" %s" % pip)
+ print("Processing PIPs..")
- count += 1
- c = nn
+ 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)
+
+ 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):
+ 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("/")
+
+ src_node = nodes.find((src_tile, src_wire))
+ dst_node = nodes.find((dst_tile, dst_wire))
+
+ print("Routing %s -> %s:" % (src_node, dst_node))
+
+ node_scores = dict()
+
+ 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)
+
+ 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
+ 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:])