# 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 = {}
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 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(":"))

X = 64

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(8)
		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
	print()
	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 + "/clkroute3/gclk%d.v" % x, "w") as f:
		print("module top(input i, input [9:0] aux, d, output o, q);", file=f)
		N = len(buffers)
		print("    wire [%d:0] r;" % N, file=f)
		print("    assign r[0] = i;", file=f)
		print("    assign o = r[%d];" % N, file=f)
		print("    wire [%d:0] r2;" % (2*N), file=f)
		print("    assign r2[0] = d;", file=f)
		print("    assign q = r2[%d];" % (2*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)
			elif "DIV" in buftype:
				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(r[%d])," % i, file=f)
				print("        %s," % random_control(["CE", "CLR"]), file=f)
				print("        .O(r[%d])" % (i+1), file=f)
				print("    );", file=f)
			else:
				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_div_%d (" % i, file=f)
				print("        .I(r[%d])," % i, file=f)
				print("        %s," % random_control(["CE"]), file=f)
				print("        .O(r[%d])" % (i+1), file=f)
				print("    );", file=f)

			if np.random.randint(2) == 1:
				print("FDCE ff_%d(.C(r[%d]), .CE(1'b1), .CLR(1'b0), .D(r2[%d]), .Q(r2[%d]));" % (i, i, 2*i, 2*i+1), file=f)
			else:
				print("assign r2[%d] = r2[%d];" % (2*i+1, 2*i), file=f)

			if np.random.randint(2) == 1:
				print("SRLC32E srl_%d(.CLK(r[%d]), .CE(1'b1), .A(aux[4:0]), .D(r2[%d]), .Q(r2[%d]));" % (i, i, 2*i+1, 2*i+2), file=f)
			else:
				print("assign r2[%d] = r2[%d];" % (2*i+2, 2*i+1), file=f)

			print("", file=f)
		print("endmodule", file=f)
	with open(root + "/clkroute3/gclk%d.tcl" % x, "w") as f:
		print("add_files %s" % (root + ("/clkroute3/gclk%d.v" % x)), file=f)
		#print("read_xdc %s" % (root + ("/clkroute3/gclk%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/gclk%d.dcp" % (root, x), file=f)
		print("write_edif -force %s/specimen_clk/gclk%d.edf" % (root, x), file=f)
		print("write_bitstream -force %s/specimen_clk/gclk%d.bit" % (root, x), file=f)
with open(root + "/clkroute3/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 gclk%d.tcl" % x, file=f)
		print("if [ $? -eq 0 ]; then", file=f)
		print("    ../../ultra/tools/dump_bitstream %s/specimen_clk/gclk%d.bit %s/frames.txt > %s/specimen_clk/gclk%d.dump" % (root, x, root, root, x), file=f)
		print("    python3 ../../ultra/tools/bits_to_tiles.py %s/tile.json %s/specimen_clk/gclk%d.dump > %s/specimen_clk/gclk%d.tbits" % (root, root, x, root, x), file=f)
		print("else", file=f)
		print("   rm %s/specimen_clk/gclk%d.dump" % (root, x), file=f)
		print("   rm %s/specimen_clk/gclk%d.tbits" % (root, x), file=f)
		print("   rm %s/specimen_clk/gclk%d.dcp" % (root, x), file=f)
		print("   rm %s/specimen_clk/gclk%d.bit" % (root, x), file=f)
		print("   rm %s/specimen_clk/gclk%d.features" % (root, x), file=f)
		print("fi", file=f)