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