Merge pull request #71 from mcmasterg/demoscene

roi_harness Basys3 demo
This commit is contained in:
Rick Altherr 2018-02-01 11:24:28 -08:00 committed by GitHub
commit ea3aa0fa70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 546 additions and 162 deletions

View File

@ -7,3 +7,7 @@
/vivado*
/design.txt
/out_*
/*.fasm
/*.bit
/*.bin
/*.frm

View File

@ -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

View File

@ -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)

View File

@ -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'))

View File

@ -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"

View File

@ -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

View File

@ -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
@ -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]
@ -306,52 +306,59 @@ 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 ""
}
# 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 @@ 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,7 +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)"
puts $fp "$net $node $pin"
set wire [node2wire $node]
puts $fp "$net $node $pin $wire"
set y [expr {$y + $PITCH}]
}
@ -409,7 +418,8 @@ if {$fixed_xdc eq ""} {
}
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 @@ 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

View File

@ -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()

View File

@ -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

281
tools/simpleroute.py Normal file → Executable file
View File

@ -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 @@ 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
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:])