2019-02-12 19:16:16 +08:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
import argparse
|
2021-02-10 07:52:23 +08:00
|
|
|
import logging
|
|
|
|
from distutils.version import LooseVersion
|
2019-02-12 19:16:16 +08:00
|
|
|
|
|
|
|
from misoc.integration.builder import builder_args, builder_argdict
|
|
|
|
from misoc.targets.kasli import soc_kasli_args, soc_kasli_argdict
|
|
|
|
|
2021-02-10 07:52:23 +08:00
|
|
|
from artiq import __version__ as artiq_version
|
2021-01-16 10:43:14 +08:00
|
|
|
from artiq.coredevice import jsondesc
|
2021-02-07 14:34:26 +08:00
|
|
|
from artiq.gateware import rtio, eem_7series
|
|
|
|
from artiq.gateware.rtio.phy import ttl_simple
|
2019-02-12 19:16:16 +08:00
|
|
|
from artiq.gateware.targets.kasli import StandaloneBase, MasterBase, SatelliteBase
|
|
|
|
from artiq.build_soc import *
|
|
|
|
|
2021-02-10 07:52:23 +08:00
|
|
|
logger = logging.getLogger(__name__)
|
2019-02-12 19:16:16 +08:00
|
|
|
|
|
|
|
class GenericStandalone(StandaloneBase):
|
|
|
|
def __init__(self, description, hw_rev=None,**kwargs):
|
|
|
|
if hw_rev is None:
|
|
|
|
hw_rev = description["hw_rev"]
|
2019-03-08 19:57:20 +08:00
|
|
|
self.class_name_override = description["variant"]
|
2019-02-12 19:16:16 +08:00
|
|
|
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
|
|
|
|
|
|
|
self.config["SI5324_AS_SYNTHESIZER"] = None
|
2020-12-30 02:18:12 +08:00
|
|
|
self.config["RTIO_FREQUENCY"] = "{:.1f}".format(description["rtio_frequency"]/1e6)
|
2019-05-08 23:45:45 +08:00
|
|
|
if "ext_ref_frequency" in description:
|
|
|
|
self.config["SI5324_EXT_REF"] = None
|
|
|
|
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
|
|
|
description["ext_ref_frequency"]/1e6)
|
2019-02-12 19:16:16 +08:00
|
|
|
if hw_rev == "v1.0":
|
|
|
|
# EEM clock fan-out from Si5324, not MMCX
|
|
|
|
self.comb += self.platform.request("clk_sel").eq(1)
|
|
|
|
|
|
|
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
|
|
|
if has_grabber:
|
|
|
|
self.grabber_csr_group = []
|
|
|
|
|
|
|
|
self.rtio_channels = []
|
2021-02-07 14:34:26 +08:00
|
|
|
eem_7series.add_peripherals(self, description["peripherals"])
|
2020-07-08 18:14:44 +08:00
|
|
|
if hw_rev in ("v1.0", "v1.1"):
|
|
|
|
for i in (1, 2):
|
|
|
|
print("SFP LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
|
|
|
sfp_ctl = self.platform.request("sfp_ctl", i)
|
|
|
|
phy = ttl_simple.Output(sfp_ctl.led)
|
|
|
|
self.submodules += phy
|
|
|
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
2021-06-07 16:05:50 +08:00
|
|
|
if hw_rev == "v2.0":
|
|
|
|
for i in (1, 2):
|
2021-08-05 23:29:38 +08:00
|
|
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
2021-06-07 16:05:50 +08:00
|
|
|
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
|
|
|
self.submodules += phy
|
2021-08-05 23:29:38 +08:00
|
|
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
2019-02-12 19:16:16 +08:00
|
|
|
|
|
|
|
self.config["HAS_RTIO_LOG"] = None
|
|
|
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
|
|
self.rtio_channels.append(rtio.LogChannel())
|
|
|
|
|
2021-12-03 17:05:35 +08:00
|
|
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
|
|
|
|
2019-02-12 19:16:16 +08:00
|
|
|
if has_grabber:
|
|
|
|
self.config["HAS_GRABBER"] = None
|
|
|
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
|
|
|
for grabber in self.grabber_csr_group:
|
|
|
|
self.platform.add_false_path_constraints(
|
|
|
|
self.rtio_crg.cd_rtio.clk, getattr(self, grabber).deserializer.cd_cl.clk)
|
|
|
|
|
|
|
|
|
2019-02-23 15:41:05 +08:00
|
|
|
class GenericMaster(MasterBase):
|
|
|
|
def __init__(self, description, hw_rev=None, **kwargs):
|
|
|
|
if hw_rev is None:
|
|
|
|
hw_rev = description["hw_rev"]
|
2019-03-08 19:57:20 +08:00
|
|
|
self.class_name_override = description["variant"]
|
2019-02-23 15:41:05 +08:00
|
|
|
MasterBase.__init__(self,
|
|
|
|
hw_rev=hw_rev,
|
2020-12-30 02:18:12 +08:00
|
|
|
rtio_clk_freq=description["rtio_frequency"],
|
|
|
|
enable_sata=description["enable_sata_drtio"],
|
2019-02-23 15:41:05 +08:00
|
|
|
**kwargs)
|
2019-11-30 02:46:27 +08:00
|
|
|
if "ext_ref_frequency" in description:
|
|
|
|
self.config["SI5324_EXT_REF"] = None
|
|
|
|
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
|
|
|
description["ext_ref_frequency"]/1e6)
|
2019-02-23 15:41:05 +08:00
|
|
|
if hw_rev == "v1.0":
|
|
|
|
# EEM clock fan-out from Si5324, not MMCX
|
|
|
|
self.comb += self.platform.request("clk_sel").eq(1)
|
|
|
|
|
|
|
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
|
|
|
if has_grabber:
|
|
|
|
self.grabber_csr_group = []
|
|
|
|
|
|
|
|
self.rtio_channels = []
|
2021-02-07 14:34:26 +08:00
|
|
|
eem_7series.add_peripherals(self, description["peripherals"])
|
2019-02-23 15:41:05 +08:00
|
|
|
self.config["HAS_RTIO_LOG"] = None
|
|
|
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
|
|
self.rtio_channels.append(rtio.LogChannel())
|
|
|
|
|
2021-12-03 17:05:35 +08:00
|
|
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
2019-02-23 15:41:05 +08:00
|
|
|
if has_grabber:
|
|
|
|
self.config["HAS_GRABBER"] = None
|
|
|
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
|
|
|
for grabber in self.grabber_csr_group:
|
|
|
|
self.platform.add_false_path_constraints(
|
|
|
|
self.drtio_transceiver.gtps[0].txoutclk, getattr(self, grabber).deserializer.cd_cl.clk)
|
|
|
|
|
|
|
|
|
|
|
|
class GenericSatellite(SatelliteBase):
|
|
|
|
def __init__(self, description, hw_rev=None, **kwargs):
|
|
|
|
if hw_rev is None:
|
|
|
|
hw_rev = description["hw_rev"]
|
2019-03-08 19:57:20 +08:00
|
|
|
self.class_name_override = description["variant"]
|
2019-02-23 15:41:05 +08:00
|
|
|
SatelliteBase.__init__(self,
|
|
|
|
hw_rev=hw_rev,
|
2020-12-30 02:18:12 +08:00
|
|
|
rtio_clk_freq=description["rtio_frequency"],
|
|
|
|
enable_sata=description["enable_sata_drtio"],
|
2019-02-23 15:41:05 +08:00
|
|
|
**kwargs)
|
|
|
|
if hw_rev == "v1.0":
|
|
|
|
# EEM clock fan-out from Si5324, not MMCX
|
|
|
|
self.comb += self.platform.request("clk_sel").eq(1)
|
|
|
|
|
|
|
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
|
|
|
if has_grabber:
|
|
|
|
self.grabber_csr_group = []
|
|
|
|
|
|
|
|
self.rtio_channels = []
|
2021-02-07 14:34:26 +08:00
|
|
|
eem_7series.add_peripherals(self, description["peripherals"])
|
2019-02-23 15:41:05 +08:00
|
|
|
self.config["HAS_RTIO_LOG"] = None
|
|
|
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
|
|
self.rtio_channels.append(rtio.LogChannel())
|
|
|
|
|
2021-12-03 17:05:35 +08:00
|
|
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
2019-02-23 15:41:05 +08:00
|
|
|
if has_grabber:
|
|
|
|
self.config["HAS_GRABBER"] = None
|
|
|
|
self.add_csr_group("grabber", self.grabber_csr_group)
|
|
|
|
for grabber in self.grabber_csr_group:
|
|
|
|
self.platform.add_false_path_constraints(
|
|
|
|
self.drtio_transceiver.gtps[0].txoutclk, getattr(self, grabber).deserializer.cd_cl.clk)
|
|
|
|
|
|
|
|
|
2019-02-12 19:16:16 +08:00
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="ARTIQ device binary builder for generic Kasli systems")
|
|
|
|
builder_args(parser)
|
|
|
|
soc_kasli_args(parser)
|
|
|
|
parser.set_defaults(output_dir="artiq_kasli")
|
|
|
|
parser.add_argument("description", metavar="DESCRIPTION",
|
2019-02-22 17:19:20 +08:00
|
|
|
help="JSON system description file")
|
2020-09-01 23:48:43 +08:00
|
|
|
parser.add_argument("--gateware-identifier-str", default=None,
|
2020-08-28 05:56:57 +08:00
|
|
|
help="Override ROM identifier")
|
2019-02-12 19:16:16 +08:00
|
|
|
args = parser.parse_args()
|
2020-12-30 02:18:12 +08:00
|
|
|
description = jsondesc.load(args.description)
|
2019-02-12 19:16:16 +08:00
|
|
|
|
2021-02-10 07:52:23 +08:00
|
|
|
min_artiq_version = description.get("min_artiq_version", "0")
|
|
|
|
if LooseVersion(artiq_version) < LooseVersion(min_artiq_version):
|
|
|
|
logger.warning("ARTIQ version mismatch: current %s < %s minimum",
|
|
|
|
artiq_version, min_artiq_version)
|
|
|
|
|
2019-02-12 19:16:16 +08:00
|
|
|
if description["target"] != "kasli":
|
|
|
|
raise ValueError("Description is for a different target")
|
|
|
|
|
|
|
|
if description["base"] == "standalone":
|
|
|
|
cls = GenericStandalone
|
|
|
|
elif description["base"] == "master":
|
|
|
|
cls = GenericMaster
|
|
|
|
elif description["base"] == "satellite":
|
|
|
|
cls = GenericSatellite
|
|
|
|
else:
|
|
|
|
raise ValueError("Invalid base")
|
|
|
|
|
2020-09-01 23:48:43 +08:00
|
|
|
soc = cls(description, gateware_identifier_str=args.gateware_identifier_str, **soc_kasli_argdict(args))
|
2019-02-12 19:16:16 +08:00
|
|
|
args.variant = description["variant"]
|
|
|
|
build_artiq_soc(soc, builder_argdict(args))
|
|
|
|
|
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|