mirror of https://github.com/openXC7/prjxray.git
Merge pull request #71 from mcmasterg/demoscene
roi_harness Basys3 demo
This commit is contained in:
commit
ea3aa0fa70
|
|
@ -7,3 +7,7 @@
|
|||
/vivado*
|
||||
/design.txt
|
||||
/out_*
|
||||
/*.fasm
|
||||
/*.bit
|
||||
/*.bin
|
||||
/*.frm
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -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'))
|
||||
|
|
@ -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"
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:])
|
||||
|
|
|
|||
Loading…
Reference in New Issue