blob: 0d976d5b9464a3e62a696c645c7328e3f41ac627 [file] [log] [blame]
from collections import defaultdict
from fuzzconfig import FuzzConfig
import interconnect
import nets
import pytrellis
import re
import argparse
import fuzzloops
import nonrouting
import os
jobs = [
{
"cfg": FuzzConfig(job="PICB0_AB", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PB11:PIC_B0"]),
"side": "B",
"pins": [("13", "A"), ("14", "B")]
},
# Split into multiple jobs, because Diamond chokes if the I/Os don't
# actually physically exist (QFN32 is default).
{
"cfg": FuzzConfig(job="PICB0_CD", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PB6:PIC_B0"]),
"side": "B",
"pins": [("9", "C"), ("10", "D")]
},
{
"cfg": FuzzConfig(job="PICL0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PL5:PIC_L0"]),
"side": "L",
"pins": [("12", "A"), ("13", "B"), ("14", "C"), ("15", "D")],
"package": "TQFP100"
},
{
"cfg": FuzzConfig(job="PICR0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PR5:PIC_R0"]),
"side": "R",
"pins": [("65", "A"), ("64", "B"), ("63", "C"), ("62", "D")],
"package": "TQFP100"
},
{
"cfg": FuzzConfig(job="PICT0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PT10:PIC_T0"]),
"side": "T",
"pins": [("97", "A"), ("96", "B")],
"package": "TQFP100"
},
# FIXME: WARNING - map: In "LOCATE COMP "pad" SITE "PT10{C,D} pin" ;":
# Current SYS_CONFIG setting prohibits pin be used as user IO. This
# preference has been disabled. Why?
{
"cfg": FuzzConfig(job="PICT0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PT12:PIC_T0"]),
"side": "T",
"pins": [("28", "C"), ("27", "D")]
},
{
"cfg": FuzzConfig(job="PICRS0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PR3:PIC_RS0"]),
"side": "R",
"pins": [("71", "A"), ("70", "B")],
"package": "TQFP100"
},
{
"cfg": FuzzConfig(job="PICLS0_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PL9:PIC_LS0"]),
"side": "L",
"pins": [("20", "A"), ("21", "B")],
"package": "TQFP100"
},
{
"cfg": FuzzConfig(job="PICL0VREF_IO", family="MachXO2", device="LCMXO2-1200HC",
ncl="empty.ncl", tiles=["PL4:PIC_L0_VREF3"]),
"side": "L",
"pins": [("11", "A"), ("12", "B"), ("13", "C"), ("14", "D")],
"package": "TQFP144"
},
]
# Function constructed from reading the MachXO2 sysIO Usage Guide.
# Diamond is very sensitive to invalid I/O combinations, and will happily
# change the I/O type out from under you if you give it a bad combination.
# This can lead to further errors when the Diamond-assigned I/O type is
# invalid for the pin (for the complementary pair, especially).
def get_io_types(dir, pio, side):
# Singled-ended I/O types.
types = [
"LVTTL33",
"LVCMOS33",
"LVCMOS25",
"LVCMOS18",
"LVCMOS15",
"LVCMOS12",
"SSTL25_I",
"SSTL18_I",
"HSTL18_I"
]
if dir == "INPUT":
types += [
"SSTL25_II",
"SSTL18_II",
"HSTL18_II",
"LVCMOS25R33",
"LVCMOS18R33",
"LVCMOS18R25",
"LVCMOS15R33",
"LVCMOS15R25"
]
if dir in ("INPUT", "BIDIR"):
types += [
"LVCMOS12R33",
"LVCMOS12R25",
"LVCMOS10R33",
"LVCMOS10R25"
]
if side == "B":
# Only bottom bank supports PCI33.
types += [
"PCI33"
]
# Differential I/O types.
if pio in ("A", "C"):
types += [
"SSTL25D_I",
"SSTL18D_I",
"HSTL18D_I",
"MIPI",
"LVCMOS33D",
"LVCMOS25D",
"LVCMOS18D",
"LVCMOS15D",
"LVCMOS12D",
]
if dir == "INPUT":
# True differential inputs.
# FIXME: Also supported in bidir?
# map_impl.mrp suggests no (warning: violates legal combination
# and is ignored.)
types += [
"SSTL25D_II",
"SSTL18D_II",
"HSTL18D_II",
"LVDS25",
"LVPECL33",
"MLVDS25",
"BLVDS25",
"RSDS25"
]
if dir == "OUTPUT":
# Emulated differential output.
# FIXME: Also supported in bidir?
types += [
"LVDS25E",
"LVPECL33E",
"MLVDS25E",
"BLVDS25E",
"RSDS25E"
]
# True differential output. Only supported on Top and primary pair.
if pio == "A" and side == "T":
types += [
"LVDS25"
]
return types
def get_cfg_vccio(iotype):
m = re.match(r".*(\d)(\d)$", iotype)
if not m:
return "3.3"
return "{}.{}".format(m.group(1), m.group(2))
def main(args):
pytrellis.load_database("../../../database")
for job in [jobs[i] for i in args.ids]:
cfg = job["cfg"]
side = job["side"]
pins = job["pins"]
os.environ['DEV_PACKAGE'] = job.get("package", "QFN32")
cfg.setup()
empty_bitfile = cfg.build_design(cfg.ncl, {})
cfg.ncl = "pio.v"
def per_pin(pin):
loc, pio = pin
def get_substs(iomode, extracfg=None):
if iomode == "NONE":
iodir, type = "NONE", ""
else:
iodir, type = iomode.split("_", 1)
substs = {
"dir": iodir,
"io_type": type,
"loc": loc,
"extra_attrs": "",
"cfg_vio": "3.3"
}
if extracfg is not None:
substs["extra_attrs"] = '(* {}="{}" *)'.format(extracfg[0], extracfg[1])
if side == "B":
substs["cfg_vio"] = get_cfg_vccio(type)
return substs
modes = ["NONE"]
for iodir in ("INPUT", "OUTPUT", "BIDIR"):
modes += [iodir + "_" + _ for _ in get_io_types(iodir, pio, side)]
nonrouting.fuzz_enum_setting(cfg, "PIO{}.BASE_TYPE".format(pio), modes,
lambda x: get_substs(iomode=x),
empty_bitfile, False)
nonrouting.fuzz_enum_setting(cfg, "PIO{}.PULLMODE".format(pio), ["UP", "DOWN", "NONE", "KEEPER", "FAILSAFE"],
lambda x: get_substs(iomode="INPUT_LVCMOS33", extracfg=("PULLMODE", x)),
empty_bitfile)
nonrouting.fuzz_enum_setting(cfg, "PIO{}.SLEWRATE".format(pio), ["FAST", "SLOW"],
lambda x: get_substs(iomode="OUTPUT_LVCMOS33", extracfg=("SLEWRATE", x)),
empty_bitfile)
# # FIXME: Do LVCMOS12, which is 2/6mA.
nonrouting.fuzz_enum_setting(cfg, "PIO{}.DRIVE".format(pio), ["4", "8", "12", "16", "24"],
lambda x: get_substs(iomode="OUTPUT_LVCMOS33", extracfg=("DRIVE", x)),
empty_bitfile)
nonrouting.fuzz_enum_setting(cfg, "PIO{}.HYSTERESIS".format(pio), ["SMALL", "LARGE"],
lambda x: get_substs(iomode="INPUT_LVCMOS33", extracfg=("HYSTERESIS", x)),
empty_bitfile)
nonrouting.fuzz_enum_setting(cfg, "PIO{}.OPENDRAIN".format(pio), ["ON", "OFF"],
lambda x: get_substs(iomode="OUTPUT_LVCMOS33", extracfg=("OPENDRAIN", x)),
empty_bitfile)
if side in "B":
nonrouting.fuzz_enum_setting(cfg, "PIO{}.CLAMP".format(pio), ["PCI", "OFF"],
lambda x: get_substs(iomode="INPUT_PCI33", extracfg=("CLAMP", x)),
empty_bitfile)
else:
nonrouting.fuzz_enum_setting(cfg, "PIO{}.CLAMP".format(pio), ["ON", "OFF"],
lambda x: get_substs(iomode="INPUT_LVCMOS33", extracfg=("CLAMP", x)),
empty_bitfile)
if side in "T" and pio in "A":
nonrouting.fuzz_enum_setting(cfg, "PIO{}.DIFFDRIVE".format(pio), ["1.25"],
lambda x: get_substs(iomode="OUTPUT_LVDS25", extracfg=("DIFFDRIVE", x)),
empty_bitfile)
fuzzloops.parallel_foreach(pins, per_pin)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="PIO Attributes Fuzzer.")
parser.add_argument(dest="ids", metavar="N", type=int, nargs="*",
default=range(0, len(jobs)), help="Job (indices) to run.")
args = parser.parse_args()
main(args)