| # Copyright 2020 Project U-Ray Authors |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import numpy as np |
| import sys |
| |
| bufgces = [] |
| slices = [] |
| with open(sys.argv[1], "r") as tf: |
| for line in tf: |
| sl = line.strip().split(",") |
| if len(sl) < 4: |
| continue |
| for site in sl[4:]: |
| if "BUFGCE" in site and "HDIO" not in site: |
| bufgces.append(site.split(":")[0]) |
| if "SLICEM" in site or "SLICEL" in site: |
| slices.append(site.split(":")[0]) |
| orig_bufgces = list(bufgces) |
| np.random.shuffle(bufgces) |
| np.random.shuffle(slices) |
| X = 30 |
| |
| root = sys.argv[2] |
| |
| bufg_prob = np.random.randint(15, 20) |
| |
| for x in range(X): |
| with open(root + "/clkroute/clkr%d.v" % x, "w") as f: |
| N = 256 |
| M = 16 |
| for m in range(M): |
| print( |
| "module layer_1_%d(input [31:0] clk, input [71:0] cen, input d, output q);" |
| % m, |
| file=f) |
| print(" wire [%d:0] r;" % N, file=f) |
| print(" assign r[0] = d;", file=f) |
| print(" assign q = r[%d];" % N, file=f) |
| print("", file=f) |
| for i in range(N): |
| if N == 0 and len(slices) > 0: |
| loc = slices.pop() |
| print("(* LOC=\"%s\" *)" % loc, file=f) |
| print( |
| " FDCE ff_%d (.C(clk[%d]), .CLR(1'b0), .CE(cen[%d]), .D(r[%d]), .Q(r[%d]));" |
| % (i, (i * 32) // N, np.random.randint(72), i, i + 1), |
| file=f) |
| print("endmodule", file=f) |
| |
| print("module top(input [39:0] clk, cen, input d, output q);", file=f) |
| num_inputs = np.random.randint(8, 40) |
| print(" wire [511:0] clk_int;", file=f) |
| print(" wire [71:0] cen_int;", file=f) |
| print(" assign clk_int[%d:0] = clk;" % (num_inputs - 1), file=f) |
| print(" assign cen_int[%d:0] = cen;" % (num_inputs - 1), file=f) |
| print(" assign cen_int[71:64] = 8'hFF;", file=f) |
| |
| bufgces = list(orig_bufgces) |
| np.random.shuffle(bufgces) |
| |
| for i in range(num_inputs, 512): |
| a = np.random.randint(num_inputs) |
| b = None |
| while b is None or b == a: |
| b = np.random.randint(num_inputs) |
| c = None |
| while c is None or c == a or c == b: |
| c = np.random.randint(num_inputs) |
| bg = None |
| if len(bufgces) > 0: |
| bg = bufgces.pop() |
| if bg is not None and np.random.randint(20) >= bufg_prob or ( |
| bg is not None and "DIV" in bg |
| and np.random.randint(19) >= bufg_prob): |
| if "DIV" in bg: |
| print( |
| " BUFGCE_DIV #(.BUFGCE_DIVIDE(%d), .IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .IS_CLR_INVERTED(%d)) bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CLR(!cen[%d]), .CE(cen[%d]), .O(clk_int[%d]));" |
| % (np.random.randint(1, 9), np.random.randint(2), |
| np.random.randint(2), np.random.randint(2), i, a, b, |
| c, np.random.randint(40), np.random.randint(40), i), |
| file=f) |
| else: |
| ctype = np.random.choice(["", "_1"]) |
| params = " #(.IS_I_INVERTED(%d), .IS_CE_INVERTED(%d), .CE_TYPE(\"%s\")) " % ( |
| np.random.randint(2), np.random.randint(2), |
| np.random.choice(["SYNC", "ASYNC", "HARD_SYNC" |
| ])) if ctype == "" else "" |
| print( |
| " BUFGCE%s %s bufg_%d (.I(clk[%d] ^ clk[%d] ^ clk[%d]), .CE(cen[%d]), .O(clk_int[%d]));" |
| % (ctype, params, i, a, b, c, np.random.randint(40), |
| i), |
| file=f) |
| else: |
| print( |
| " assign clk_int[%d] = clk[%d] ^ clk[%d] ^ clk[%d];" % |
| (i, a, b, c), |
| file=f) |
| if i < 64: |
| print( |
| " assign cen_int[%d] = cen[%d] ^ cen[%d];" % (i, a, b), |
| file=f) |
| print("", file=f) |
| print(" wire [%d:0] r;" % M, file=f) |
| print(" assign r[0] = d;", file=f) |
| print(" assign q = r[%d];" % M, file=f) |
| for i in range(M): |
| print( |
| " layer_1_%d submod_%d(.clk(clk_int[%d +: 32]), .cen(cen_int), .d(r[%d]), .q(r[%d]));" |
| % (i, i, 32 * i, i, i + 1), |
| file=f) |
| print("endmodule", file=f) |
| with open(root + "/clkroute/clkr%d.tcl" % x, "w") as f: |
| print("add_files %s" % (root + ("/clkroute/clkr%d.v" % x)), file=f) |
| print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) |
| print("opt_design", file=f) |
| print("place_design", file=f) |
| print("route_design", file=f) |
| print( |
| "set_property SEVERITY {Warning} [get_drc_checks NSTD-1]", file=f) |
| print( |
| "set_property SEVERITY {Warning} [get_drc_checks UCIO-1]", file=f) |
| print( |
| "set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", |
| file=f) |
| print( |
| "write_checkpoint -force %s/specimen_clk/clkr%d.dcp" % (root, x), |
| file=f) |
| print( |
| "write_edif -force %s/specimen_clk/clkr%d.edf" % (root, x), file=f) |
| print( |
| "write_bitstream -force %s/specimen_clk/clkr%d.bit" % (root, x), |
| file=f) |
| with open(root + "/clkroute/run.sh", "w") as f: |
| print("#/usr/bin/env bash", file=f) |
| #print("set -ex", file=f) |
| for x in range(X): |
| print( |
| "vivado -mode batch -nolog -nojournal -source clkr%d.tcl" % x, |
| file=f) |
| print("if [ $? -eq 0 ]; then", file=f) |
| print( |
| " ../../ultra/tools/dump_bitstream %s/specimen_clk/clkr%d.bit %s/frames.txt > %s/specimen_clk/clkr%d.dump" |
| % (root, x, root, root, x), |
| file=f) |
| print( |
| " python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/clkr%d.dump > %s/specimen_clk/clkr%d.tbits" |
| % (root, root, x, root, x), |
| file=f) |
| print("else", file=f) |
| print(" rm %s/specimen_clk/clkr%d.dump" % (root, x), file=f) |
| print(" rm %s/specimen_clk/clkr%d.tbits" % (root, x), file=f) |
| print("fi", file=f) |