# 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

print("module top(input [15:0] clk, sr, ce, input [7:0] d, output [31:0] q);")
N = 500
D = ["d[%d]" % i for i in range(8)]

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 "SLICEM" in site or "SLICEL" in site:
				slices.append(site.split(":")[0])

np.random.shuffle(slices)

for i in range(N):
	sl = slices.pop()
	ffmode = np.random.randint(3, size=2)
	clk = tuple(np.random.randint(16, size=2))
	sr = tuple(["1'b1" if y >= 16 else "sr[%d]" % y for y in np.random.randint(25, size=2)])
	ce = tuple(["1'b1" if y >= 16 else "ce[%d]" % y for y in np.random.randint(25, size=4)])

	def random_fftype(mode):
		if mode == 0:
			return np.random.choice(["NONE", "FDSE", "FDRE"])
		elif mode == 1:
			return np.random.choice(["NONE", "FDPE", "FDCE"])
		elif mode == 2:
			return np.random.choice(["NONE", "LDPE", "LDCE"])

	def random_bit():
		return np.random.choice(D)

	def random_data(width):
		return "{%s}" % (", ".join([random_bit() for k in range(width)]))

	fftypes = [random_fftype(ffmode[j // 8]) for j in range(16)]

	print('   wire [31:0] d%d;' % i)
	print('   ultra_slice_logic #(')
	print('      .LOC("%s"),' % sl)
	for lut in "ABCDEFGH":
		print("      .%sLUT_INIT(64'b%s)," % (lut, "".join(str(_) for _ in np.random.randint(2, size=64))))
	for j in range(16):
		print('      .%sFF%s_TYPE("%s"),' % ("ABCDEFGH"[j//2], "2" if (j % 2) == 1 else "", fftypes[j]))
	print("      .FF_INIT(16'b%s)," % "".join(str(_) for _ in np.random.randint(2, size=16)))
	for j1 in "ABCDEFGH":
		for j2 in ("1", "2"):
			print('        .FFMUX%s%s("%s"),' % (j1, j2, np.random.choice(["F7F8", "D6", "D5", "BYP"])))
	for j in "ABCDEFGH":
		print('        .OUTMUX%s("%s"),' % (j, np.random.choice(["F7F8", "D6", "D5"])))
	print("      .CLKINV(2'd%d)," % np.random.randint(4))
	print("      .SRINV(2'd%d)" % np.random.randint(4))
	print('   ) slice%d (' % i)
	for j in range(1, 7):
		print("      .A%d(%s)," % (j, random_data(8)))
	print("      .I(%s)," % random_data(8))
	print("      .X(%s)," % random_data(8))
	print("      .CLK({clk[%d], clk[%d]})," % clk)
	print("      .SR({%s, %s})," % sr)
	print("      .CE({%s, %s, %s, %s})," % ce)
	print("      .O(d%d[7:0])," % i)
	print("      .Q(d%d[15:8])," % i)
	print("      .Q2(d%d[23:16])," % i)
	print("      .MUX(d%d[31:24])" % i)
	print('   );')
	print()
	D.clear()
	for j in range(8):
		D.append("d%d[%d]" % (i, j))
		D.append("d%d[%d]" % (i, 24 + j))
		if fftypes[2 * j] != "NONE":
			D.append("d%d[%d]" % (i, 8 + j))
		if fftypes[2 * j + 1] != "NONE":
			D.append("d%d[%d]" % (i, 16 + j))
print("    assign q = d%d;" % (N-1))
print("endmodule")