blob: 4153cfaafabef0cf8b382b02227c3fc74063469c [file]
# 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
X = 110
root = sys.argv[1]
pins = []
bank_to_pins = {}
bank_to_iotype = {}
site_to_pin = {}
pin_to_bank = {}
with open (root + "/iopins.txt", "r") as iof:
for line in iof:
sl = line.strip().split(",")
if len(sl) < 5:
continue
pin = sl[0]
bank = int(sl[1])
func = sl[2]
site_name = sl[3]
site_type = sl[4]
pins.append((pin, bank, func, site_name, site_type))
if bank not in bank_to_pins:
bank_to_pins[bank] = []
bank_to_pins[bank].append(pin)
pin_to_bank[pin] = bank
if bank not in bank_to_iotype:
bank_to_iotype[bank] = site_type.split("_")[0]
site_to_pin[site_name] = pin
for x in range(X):
used_pins = []
io_config = []
bank_to_vcc = {}
bank_pod_used = set()
bank_pod_not_used = set()
lut_inputs = []
lut_outputs = []
bank_iref = {}
bound_pins = set()
def inp():
sig = "li[%d]" % len(lut_inputs)
lut_inputs.append(sig)
return sig
def outp():
sig = "lo[%d]" % len(lut_outputs)
lut_outputs.append(sig)
return sig
def maybe_inp():
return inp() if np.random.choice([True, False]) else ""
def maybe_outp():
return outp() if np.random.choice([True, False]) else ""
for b, t in sorted(bank_to_iotype.items()):
if t == "HPIOB":
bank_to_vcc[b] = np.random.choice(
["1.0", "1.2", "1.35", "1.5", "1.8"]
)
elif t == "HDIOB":
bank_to_vcc[b] = np.random.choice(
["1.2", "1.5", "1.8", "2.5", "3.3"]
)
else:
assert False, t
standards = {
("HPIOB", "1.8"): ["LVCMOS18", "LVDCI_18", "HSLVDCI_18",
"HSTL_I_18", "HSTL_I_DCI_18",
"SSTL18_I", "SSTL18_I_DCI"],
("HPIOB", "1.5"): ["LVCMOS15", "LVDCI_15", "HSLVDCI_15",
"HSTL_I", "HSTL_I_DCI",
"SSTL15", "SSTL15_DCI"],
("HPIOB", "1.35"): ["SSTL135", "SSTL135_DCI"],
("HPIOB", "1.2"): ["LVCMOS12", "HSTL_I_12", "HSTL_I_DCI_12",
"SSTL12", "SSTL12_DCI",
"HSUL_12", "HSUL_12_DCI",
"POD12", "POD12_DCI"],
("HPIOB", "1.0"): ["POD10", "POD10_DCI"],
("HDIOB", "3.3"): ["LVCMOS33", "LVTTL"],
("HDIOB", "2.5"): ["LVCMOS25"],
("HDIOB", "1.8"): ["LVCMOS18"],
("HDIOB", "1.5"): ["LVCMOS15"],
("HDIOB", "1.2"): ["LVCMOS12"]
}
prims = {
"HPIOB": ["IBUF", "OBUF", "OBUFT", "IOBUF", "IOBUFE3", "IBUF_IBUFDISABLE"],
"HDIOB": ["IBUF","OBUF", "OBUFT", "IOBUF"]
}
drives = {
("HPIOB", "LVCMOS18"): ["2", "4", "6", "8", "12"],
("HPIOB", "LVCMOS15"): ["2", "4", "6", "8", "12"],
("HPIOB", "LVCMOS12"): ["2", "4", "6", "8"],
("HDIOB", "LVCMOS33"): ["4", "8", "12", "16"],
("HDIOB", "LVCMOS25"): ["4", "8", "12", "16"],
("HDIOB", "LVCMOS18"): ["4", "8", "12", "16"],
("HDIOB", "LVCMOS15"): ["4", "8", "12", "16"],
("HDIOB", "LVCMOS12"): ["4", "8", "12"],
}
for (pin, bank, func, sn, st) in pins:
if "VREF" in func:
continue # conflict
if "VRP" in func or "VRN" in func:
continue # conflict
if np.random.randint(1, 3) == 1:
continue # improved fuzzing
params = {}
iot = st.split("_")[0]
assert (iot, bank_to_vcc[bank]) in standards, (pin, bank, iot, bank_to_vcc[bank])
ios = np.random.choice(standards[iot, bank_to_vcc[bank]])
if bank in bank_pod_used and ios in ("HSTL_I_12", "HSTL_I_DCI_12", "SSTL12", "SSTL12_DCI", "HSUL_12", "HSUL_12_DCI"):
ios = "LVCMOS12"
if bank in bank_pod_not_used and ios in ("POD12", "POD12_DCI"):
ios = "LVCMOS12"
params["IOSTANDARD"] = ios
prim = np.random.choice(prims[iot])
params["prim"] = prim
if prim in ("IBUF", "IOBUF", "IOBUFE3", "IBUF_IBUFDISABLE", "IBUF_INTERMDISABLE"):
params["PULLTYPE"] = np.random.choice(["NONE", "PULLUP", "PULLDOWN", "KEEPER"])
if prim in ("OBUF", "OBUFT", "IOBUF", "IOBUFE3"):
if (iot, ios) in drives:
params["DRIVE"] = np.random.choice(drives[iot, ios])
if iot == "HPIOB":
params["SLEW"] = np.random.choice(["SLOW", "MEDIUM", "FAST"])
else:
params["SLEW"] = np.random.choice(["SLOW", "FAST"])
if iot == "HPIOB" and ("POD" in ios or "SSTL" in ios):
params["OUTPUT_IMPEDANCE"] = np.random.choice(["RDRV_40_40", "RDRV_48_48", "RDRV_60_60"])
if prim in ("IBUF", "IOBUF", "IOBUFE3", "IBUF_IBUFDISABLE", "IBUF_INTERMDISABLE"):
if "POD" in ios:
odt_choices = []
if "DCI" not in ios:
odt_choices.append("RTT_NONE")
if "OUTPUT_IMPEDANCE" not in params or params["OUTPUT_IMPEDANCE"] != "RDRV_48_48":
odt_choices += ["RTT_40", "RTT_60"]
else:
odt_choices += ["RTT_48"]
params["ODT"] = np.random.choice(odt_choices)
if "POD12" in ios:
params["EQUALIZATION"] = np.random.choice(["EQ_LEVEL0", "EQ_LEVEL1", "EQ_LEVEL2", "EQ_LEVEL3", "EQ_LEVEL4", "EQ_NONE"])
used_pins.append(pin)
io_config.append(params)
if iot == "HDIOB":
if ios in ( "HSTL_I_18", "SSTL18_I", "SSTL18_II"):
bank_iref[bank] = "0.90"
elif ios in ( "HSTL_I", "SSTL15", "SSTL15_II"):
bank_iref[bank] = "0.75"
elif ios in ("SSTL135", "SSTL135_II"):
bank_iref[bank] = "0.675"
elif ios == "SSTL12":
bank_iref[bank] = "0.60"
if ios in ("POD12", "POD12_DCI"):
bank_pod_used.add(bank)
bank_iref[bank] = np.random.choice([None, "0.84"])
if ios in ("HSTL_I_12", "HSTL_I_DCI_12", "SSTL12", "SSTL12_DCI", "HSUL_12", "HSUL_12_DCI"):
bank_pod_not_used.add(bank)
bank_iref[bank] = np.random.choice([None, "0.60"])
with open(root + "/io/io%d.v" % x, "w") as f:
print("module top(", file=f);
for i, params in enumerate(io_config):
prim = params["prim"]
bank = pin_to_bank[used_pins[i]]
if bank in bank_iref and bank_iref[bank] is not None:
params["internal_vref"] = bank_iref[bank]
print ("(* %s *)" % ", ".join('X_%s="%s"' % (k, v) for k, v in sorted(params.items())), file=f)
if prim in ("IBUF", "IBUF_IBUFDISABLE"):
print("input p%d%s" % (i, "," if i < len(io_config)-1 else ""), file=f)
elif prim in ("OBUF", "OBUFT"):
print("output p%d%s" % (i, "," if i < len(io_config)-1 else ""), file=f)
elif prim in ("IOBUF", "IOBUFE3"):
print("inout p%d%s" % (i, "," if i < len(io_config)-1 else ""), file=f)
print(");", file=f)
for i, params in enumerate(io_config):
print("(* KEEP, DONT_TOUCH *)", file=f)
prim = params["prim"]
if prim == "IBUF":
print("""
IBUF buf_{i} (
.I(p{i}),
.O({sig_o})
);
""".format(i=i, sig_o=maybe_inp()), file=f)
elif prim == "OBUF":
print("""
OBUF buf_{i} (
.O(p{i}),
.I({sig_i})
);
""".format(i=i, sig_i=maybe_outp()), file=f)
elif prim == "OBUFT":
print("""
OBUFT buf_{i} (
.O(p{i}),
.T({sig_t}),
.I({sig_i})
);
""".format(i=i, sig_t=outp(), sig_i=maybe_outp()), file=f)
elif prim == "IOBUF":
print("""
IOBUF buf_{i} (
.IO(p{i}),
.T({sig_t}),
.I({sig_i}),
.O({sig_o})
);
""".format(i=i, sig_t=maybe_outp(), sig_i=maybe_outp(), sig_o=maybe_inp()), file=f)
elif prim == "IBUF_IBUFDISABLE":
print("""
IBUF_IBUFDISABLE buf_{i} (
.I(p{i}),
.O({sig_o}),
.IBUFDISABLE({ibuf_dis})
);
""".format(i=i, sig_o=maybe_inp(), ibuf_dis=maybe_outp()), file=f)
elif prim == "IOBUFE3":
if np.random.choice([True, False]):
print("(* KEEP, DONT_TOUCH *)", file=f)
print("""
IOBUFE3 buf_{i} (
.IO(p{i}),
.T({sig_t}),
.I({sig_i}),
.O({sig_o}),
.DCITERMDISABLE({dci_dis}),
.IBUFDISABLE({ibuf_dis})
);
""".format(i=i, sig_t=maybe_outp(), sig_i=maybe_outp(), sig_o=maybe_inp(),
dci_dis=maybe_outp(), ibuf_dis=maybe_outp()), file=f)
print("", file=f)
print("wire [%d:0] li;" % (len(lut_inputs)-1), file=f)
print("wire [%d:0] lo;" % (len(lut_outputs)-1), file=f)
for i in range(max(len(lut_inputs)//6 + 1, len(lut_outputs))):
ip = ["1'b0" if (i * 6 + j) >= len(lut_inputs) else "li[%d]" % (i * 6 + j) for j in range(6)]
op = "lo[%d]" % i if i < len(lut_outputs) else ""
print("""
(* KEEP, DONT_TOUCH *)
LUT6 lut{i} (.I0({i0}), .I1({i1}), .I2({i2}), .I3({i3}), .I4({i4}), .I5({i5}), .O({o}));
""".format(
i=i, i0=ip[0], i1=ip[1], i2=ip[2], i3=ip[3], i4=ip[4], i5=ip[5], o=op,
), file=f)
print("endmodule", file=f)
with open(root + "/io/io%d.xdc" % x, "w") as f:
for i, params in enumerate(io_config):
pin = used_pins[i]
print("set_property PACKAGE_PIN %s [get_ports {p%d}]" % (pin, i), file=f)
for k, v in sorted(params.items()):
if k.isupper():
print("set_property %s %s [get_ports {p%d}]" % (k, v, i), file=f)
for bank, iref in sorted(bank_iref.items()):
if iref is None:
continue
print("set_property INTERNAL_VREF {%s} [get_iobanks %d]" % (iref, bank), file=f)
with open(root + "/io/io%d.tcl" % x, "w") as f:
print("add_files %s" % (root + ("/io/io%d.v" % x)), file=f)
print("add_files %s" % (root + ("/io/io%d.xdc" % x)), file=f)
print("synth_design -top top -part xczu7ev-ffvf1517-2-e", 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 SEVERITY {Warning} [get_drc_checks AVAL-*]", file=f)
print("set_property SEVERITY {Warning} [get_drc_checks REQP-*]", file=f)
print("set_property SEVERITY {Warning} [get_drc_checks BIVR-*]", file=f)
print("set_property SEVERITY {Warning} [get_drc_checks PLHDIO-1]", file=f)
print("opt_design", file=f)
print("place_design", file=f)
print("route_design", file=f)
print("set_property BITSTREAM.GENERAL.PERFRAMECRC YES [current_design]", file=f)
print("write_checkpoint -force %s/specimen_io/io%d.dcp" % (root, x), file=f)
print("write_edif -force %s/specimen_io/io%d.edf" % (root, x), file=f)
print("write_bitstream -force %s/specimen_io/io%d.bit" % (root, x), file=f)
with open(root + "/io/run.sh", "w") as f:
print("#/usr/bin/env bash", file=f)
print("set -ex", file=f)
print("vivado -mode batch -nolog -nojournal -source io$1.tcl", file=f)
print("if [ $? -eq 0 ]; then", file=f)
print(" ../../ultra/tools/dump_bitstream %s/specimen_io/io$1.bit %s/frames.txt > %s/specimen_io/io$1.dump" % (root, root, root), file=f)
print(" python3 ../../ultra/tools/bits_to_tiles.py %s/tilebits.json %s/specimen_io/io$1.dump > %s/specimen_io/io$1.tbits" % (root, root, root), file=f)
#print(" rm %s/specimen_io/io$1.bit" % (root, ), file=f)
#print(" rm %s/specimen_io/io$1.dump" % (root, ), file=f)
print("else", file=f)
print(" rm %s/specimen_io/io$1.dump" % (root, ), file=f)
print(" rm %s/specimen_io/io$1.tbits" % (root, ), file=f)
print(" rm %s/specimen_io/io$1.dcp" % (root, ), file=f)
print(" rm %s/specimen_io/io$1.bit" % (root, ), file=f)
print(" rm %s/specimen_io/io$1.features" % (root, ), file=f)
print("fi", file=f)
with open(root + "/io/Makefile", "w") as f:
print("all: %s" % " ".join(["%d.done" % i for i in range(X)]), file=f)
print("", file=f)
print("%.done: ", file=f)
print("\tbash run.sh $*", file=f)
print("\ttouch $@", file=f)
print("", file=f)
print("clean: ", file=f)
print("\trm -f *.done", file=f)