| # 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_by_tile = {} | |
| tiles_by_xy = {} | |
| rclk_int_l = [] | |
| slices_by_tile = {} | |
| with open(sys.argv[1], "r") as tf: | |
| for line in tf: | |
| sl = line.strip().split(",") | |
| if len(sl) < 4: | |
| continue | |
| tiles_by_xy[int(sl[0]), int(sl[1])] = sl[2] | |
| if sl[2].startswith("RCLK_INT_L"): | |
| rclk_int_l.append((int(sl[0]), int(sl[1]), sl[2])) | |
| for site in sl[4:]: | |
| if ("BUFGCE" in site or "BUFGCTRL" in site) and "HDIO" not in site: | |
| if sl[2] not in bufgces_by_tile: | |
| bufgces_by_tile[sl[2]] = [] | |
| bufgces_by_tile[sl[2]].append(site.split(":")) | |
| elif "SLICE_" in site: | |
| slices_by_tile[int(sl[0]), int(sl[1])] = site.split(":")[0] | |
| halfcolumn_slices_by_row = {} | |
| for x, y, rclk in rclk_int_l: | |
| hc_up = [] | |
| hc_down = [] | |
| if y not in halfcolumn_slices_by_row: | |
| halfcolumn_slices_by_row[y] = [] | |
| for yplus in range(y + 1, y + 31): | |
| if (x, yplus) not in tiles_by_xy: | |
| continue | |
| if not tiles_by_xy[x, yplus].startswith("INT_"): | |
| break | |
| slice_x = x + np.random.choice([+1, -1]) | |
| if (slice_x, yplus) not in slices_by_tile: | |
| continue | |
| hc_up.append(slices_by_tile[slice_x, yplus]) | |
| for yminus in range(y - 1, y - 31, -1): | |
| if (x, yminus) not in tiles_by_xy: | |
| continue | |
| if not tiles_by_xy[x, yminus].startswith("INT_"): | |
| break | |
| slice_x = x + np.random.choice([+1, -1]) | |
| if (slice_x, yminus) not in slices_by_tile: | |
| continue | |
| hc_down.append(slices_by_tile[slice_x, yminus]) | |
| halfcolumn_slices_by_row[y].append(hc_up) | |
| halfcolumn_slices_by_row[y].append(hc_down) | |
| X = 32 | |
| root = sys.argv[2] | |
| for x in range(X): | |
| buffers = [] | |
| tiles = list(sorted(bufgces_by_tile.keys())) | |
| np.random.shuffle(tiles) | |
| for tile in tiles: | |
| shuffled_bufs = list(bufgces_by_tile[tile]) | |
| np.random.shuffle(shuffled_bufs) | |
| target_type = np.random.choice( | |
| ["BUFGCE", "BUFGCE_DIV", "BUFGCTRL"] | |
| if len(buffers) > 0 else ["BUFGCE", "BUFGCE_DIV"]) | |
| tile_buffers = np.random.randint(6) | |
| found_buffers = 0 | |
| for buf, buftype in shuffled_bufs: | |
| if found_buffers >= tile_buffers: | |
| break | |
| if buftype != target_type: | |
| continue | |
| buffers.append((buf, buftype)) | |
| print("%s %s" % (tile, buf)) | |
| found_buffers += 1 | |
| def random_inversion(pins): | |
| return ", ".join( | |
| [".IS_%s_INVERTED(%d)" % (p, np.random.randint(2)) for p in pins]) | |
| def random_control(pins): | |
| return ", ".join( | |
| [".%s(aux[%d])" % (p, np.random.randint(10)) for p in pins]) | |
| with open(root + "/clkroute5/gclkc_%d.v" % x, "w") as f: | |
| print( | |
| "module top(input [23:0] i, input [9:0] aux, input d, output o, q);", | |
| file=f) | |
| N = 24 | |
| print(" wire [71:0] r;", file=f) | |
| # print(" assign r[0] = i;", file=f) | |
| # print(" assign o = r[%d];" % N, file=f) | |
| # for i in range(N): | |
| # bg, buftype = buffers[i] | |
| # #print("(* LOC=\"%s\" *)" % bg, file=f) | |
| # if "BUFGCTRL" in buftype: | |
| # print(" BUFGCTRL #(", file=f) | |
| # print(" %s," % random_inversion(["I0", "I1", "S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) | |
| # print(" .INIT_OUT(%d), .PRESELECT_I0(\"%s\"), .PRESELECT_I1(\"%s\")" % | |
| # (np.random.randint(2), np.random.choice(["TRUE", "FALSE"]), np.random.choice(["TRUE", "FALSE"])), file=f) | |
| # print(" ) bufgctrl_%d (" % i, file=f) | |
| # print(" .I0(r[%d]), .I1(r[%d]), " % (i, np.random.randint(i+1)), file=f) | |
| # print(" %s," % random_control(["S0", "S1", "CE0", "CE1", "IGNORE0", "IGNORE1"]), file=f) | |
| # print(" .O(r[%d])" % (i+1), file=f) | |
| # print(" );", file=f) | |
| print(" assign r[23:0] = i;", file=f) | |
| for i in range(12): | |
| print(" BUFGCE_DIV #(", file=f) | |
| print( | |
| " .BUFGCE_DIVIDE(%d)," % np.random.randint(1, 9), | |
| file=f) | |
| print(" %s" % random_inversion(["I", "CE", "CLR"]), file=f) | |
| print(" ) bufgce_div_%d (" % i, file=f) | |
| print(" .I(i[%d])," % i, file=f) | |
| print(" %s," % random_control(["CE", "CLR"]), file=f) | |
| print(" .O(r[%d])" % (24 + i), file=f) | |
| print(" );", file=f) | |
| for i in range(12): | |
| print(" BUFGCE #(", file=f) | |
| print( | |
| " .CE_TYPE(\"%s\")," % np.random.choice( | |
| ["SYNC", "ASYNC"]), | |
| file=f) | |
| print(" %s" % random_inversion(["I", "CE"]), file=f) | |
| print(" ) bufgce_%d (" % i, file=f) | |
| print(" .I(i[%d])," % np.random.randint(24), file=f) | |
| print(" %s," % random_control(["CE"]), file=f) | |
| print(" .O(r[%d])" % (i + 36), file=f) | |
| print(" );", file=f) | |
| R2 = 0 | |
| NS = 64 | |
| ffs = "" | |
| for row, hcs in sorted(halfcolumn_slices_by_row.items()): | |
| row_clks = np.random.randint(20, 25) | |
| clks = [np.random.randint(48) for k in range(row_clks)] | |
| hi = [] | |
| while len(hi) < NS: | |
| next_i = np.random.randint(len(hcs)) | |
| while next_i in hi: | |
| next_i = np.random.randint(len(hcs)) | |
| hi.append(next_i) | |
| halfs = [hcs[hi[k]] for k in range(NS)] | |
| for h in halfs: | |
| half_clks = np.random.randint(13, 17) | |
| rclks = [np.random.choice(clks) for k in range(half_clks)] | |
| for sl in h: | |
| ffs += "(* LOC=\"%s\" *) FDCE ff_%d (.C(r[%d]), .CE(aux[%d]), .CLR(~aux[%d]), .D(r2[%d]), .Q(r2[%d]));\n" % ( | |
| sl, R2, rclks[R2 % len(rclks)], np.random.randint(10), | |
| np.random.randint(10), R2, R2 + 1) | |
| R2 += 1 | |
| print(" wire [%d:0] r2;" % R2, file=f) | |
| print(" assign r2[0] = d;", file=f) | |
| print(" assign q = r2[%d];" % R2, file=f) | |
| print(ffs, file=f) | |
| print("endmodule", file=f) | |
| with open(root + "/clkroute5/gclkc_%d.tcl" % x, "w") as f: | |
| print("add_files %s" % (root + ("/clkroute5/gclkc_%d.v" % x)), file=f) | |
| #print("read_xdc %s" % (root + ("/clkroute5/gclkc_%d.xdc" % x)), file=f) | |
| print("synth_design -top top -part xczu7ev-ffvc1156-2-e", file=f) | |
| print("# set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets]", 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/gclkc_%d.dcp" % (root, x), | |
| file=f) | |
| print( | |
| "write_edif -force %s/specimen_clk/gclkc_%d.edf" % (root, x), | |
| file=f) | |
| print( | |
| "write_bitstream -force %s/specimen_clk/gclkc_%d.bit" % (root, x), | |
| file=f) | |
| with open(root + "/clkroute5/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 gclkc_%d.tcl" % x, | |
| file=f) | |
| print("if [ $? -eq 0 ]; then", file=f) | |
| print( | |
| " ../../ultra/tools/dump_bitstream %s/specimen_clk/gclkc_%d.bit %s/frames.txt > %s/specimen_clk/gclkc_%d.dump" | |
| % (root, x, root, root, x), | |
| file=f) | |
| print( | |
| " python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/gclkc_%d.dump > %s/specimen_clk/gclkc_%d.tbits" | |
| % (root, root, x, root, x), | |
| file=f) | |
| print("else", file=f) | |
| print(" rm %s/specimen_clk/gclkc_%d.dump" % (root, x), file=f) | |
| print(" rm %s/specimen_clk/gclkc_%d.tbits" % (root, x), file=f) | |
| print(" rm %s/specimen_clk/gclkc_%d.dcp" % (root, x), file=f) | |
| print(" rm %s/specimen_clk/gclkc_%d.bit" % (root, x), file=f) | |
| print(" rm %s/specimen_clk/gclkc_%d.features" % (root, x), file=f) | |
| print("fi", file=f) |