mirror of https://github.com/m-labs/artiq.git
gateware: merge kasli_generic into kasli. Closes #2279
This commit is contained in:
parent
de10e584f6
commit
e81e8f28cf
|
@ -77,6 +77,9 @@ Accesses to the data argument should be replaced as below:
|
||||||
Refer to the updated ``no_hardware/arguments_demo.py`` example for current usage.
|
Refer to the updated ``no_hardware/arguments_demo.py`` example for current usage.
|
||||||
* Almazny v1.2 is incompatible with the legacy versions and is the default.
|
* Almazny v1.2 is incompatible with the legacy versions and is the default.
|
||||||
To use legacy versions, specify ``almazny_hw_rev`` in the JSON description.
|
To use legacy versions, specify ``almazny_hw_rev`` in the JSON description.
|
||||||
|
* kasli_generic.py has been merged into kasli.py, and the demonstration designs without JSON descriptions
|
||||||
|
have been removed. The base classes remain present in kasli.py to support third-party flows without
|
||||||
|
JSON descriptions.
|
||||||
* Legacy PYON databases should be converted to LMDB with the script below:
|
* Legacy PYON databases should be converted to LMDB with the script below:
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import logging
|
||||||
|
from packaging.version import Version
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
@ -14,16 +16,20 @@ from misoc.targets.kasli import (
|
||||||
BaseSoC, MiniSoC, soc_kasli_args, soc_kasli_argdict)
|
BaseSoC, MiniSoC, soc_kasli_args, soc_kasli_argdict)
|
||||||
from misoc.integration.builder import builder_args, builder_argdict
|
from misoc.integration.builder import builder_args, builder_argdict
|
||||||
|
|
||||||
|
from artiq import __version__ as artiq_version
|
||||||
from artiq.gateware.amp import AMPSoC
|
from artiq.gateware.amp import AMPSoC
|
||||||
from artiq.gateware import rtio
|
from artiq.gateware import rtio
|
||||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter
|
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter
|
||||||
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
|
from artiq.gateware.rtio.xilinx_clocking import fix_serdes_timing_path
|
||||||
from artiq.gateware import eem
|
from artiq.gateware import rtio, eem, eem_7series
|
||||||
from artiq.gateware.drtio.transceiver import gtp_7series, eem_serdes
|
from artiq.gateware.drtio.transceiver import gtp_7series, eem_serdes
|
||||||
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
from artiq.gateware.drtio.siphaser import SiPhaser7Series
|
||||||
from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
|
from artiq.gateware.drtio.rx_synchronizer import XilinxRXSynchronizer
|
||||||
from artiq.gateware.drtio import *
|
from artiq.gateware.drtio import *
|
||||||
from artiq.build_soc import *
|
from artiq.build_soc import *
|
||||||
|
from artiq.coredevice import jsondesc
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class SMAClkinForward(Module):
|
class SMAClkinForward(Module):
|
||||||
|
@ -130,89 +136,6 @@ class StandaloneBase(MiniSoC, AMPSoC):
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
|
||||||
class Tester(StandaloneBase):
|
|
||||||
"""
|
|
||||||
Configuration for CI tests. Contains the maximum number of different EEMs.
|
|
||||||
"""
|
|
||||||
def __init__(self, hw_rev=None, dds=None, **kwargs):
|
|
||||||
if hw_rev is None:
|
|
||||||
hw_rev = "v2.0"
|
|
||||||
if dds is None:
|
|
||||||
dds = "ad9910"
|
|
||||||
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
|
||||||
|
|
||||||
# self.config["SI5324_EXT_REF"] = None
|
|
||||||
self.config["RTIO_FREQUENCY"] = "125.0"
|
|
||||||
if hw_rev == "v1.0":
|
|
||||||
# EEM clock fan-out from Si5324, not MMCX
|
|
||||||
self.comb += self.platform.request("clk_sel").eq(1)
|
|
||||||
|
|
||||||
self.rtio_channels = []
|
|
||||||
eem.DIO.add_std(self, 5,
|
|
||||||
ttl_serdes_7series.InOut_8X, ttl_serdes_7series.Output_8X,
|
|
||||||
edge_counter_cls=edge_counter.SimpleEdgeCounter)
|
|
||||||
eem.Urukul.add_std(self, 0, 1, ttl_serdes_7series.Output_8X, dds,
|
|
||||||
ttl_simple.ClockGen)
|
|
||||||
eem.Sampler.add_std(self, 3, 2, ttl_serdes_7series.Output_8X)
|
|
||||||
eem.Zotino.add_std(self, 4, ttl_serdes_7series.Output_8X)
|
|
||||||
|
|
||||||
if hw_rev in ("v1.0", "v1.1"):
|
|
||||||
for i in (1, 2):
|
|
||||||
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))
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
|
||||||
self.add_rtio(self.rtio_channels)
|
|
||||||
|
|
||||||
|
|
||||||
class SUServo(StandaloneBase):
|
|
||||||
"""
|
|
||||||
SUServo (Sampler-Urukul-Servo) extension variant configuration
|
|
||||||
"""
|
|
||||||
def __init__(self, hw_rev=None, **kwargs):
|
|
||||||
if hw_rev is None:
|
|
||||||
hw_rev = "v2.0"
|
|
||||||
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
|
||||||
|
|
||||||
# self.config["SI5324_EXT_REF"] = None
|
|
||||||
self.config["RTIO_FREQUENCY"] = "125.0"
|
|
||||||
if hw_rev == "v1.0":
|
|
||||||
# EEM clock fan-out from Si5324, not MMCX
|
|
||||||
self.comb += self.platform.request("clk_sel").eq(1)
|
|
||||||
|
|
||||||
self.rtio_channels = []
|
|
||||||
# EEM0, EEM1: DIO
|
|
||||||
eem.DIO.add_std(self, 0,
|
|
||||||
ttl_serdes_7series.InOut_8X, ttl_serdes_7series.Output_8X)
|
|
||||||
eem.DIO.add_std(self, 1,
|
|
||||||
ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X)
|
|
||||||
|
|
||||||
# EEM3/2: Sampler, EEM5/4: Urukul, EEM7/6: Urukul
|
|
||||||
eem.SUServo.add_std(self,
|
|
||||||
eems_sampler=(3, 2),
|
|
||||||
eems_urukul=[[5, 4], [7, 6]])
|
|
||||||
|
|
||||||
for i in (1, 2):
|
|
||||||
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))
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels)
|
|
||||||
|
|
||||||
pads = self.platform.lookup_request("sampler3_adc_data_p")
|
|
||||||
self.platform.add_false_path_constraints(
|
|
||||||
pads.clkout, self.crg.cd_sys.clk)
|
|
||||||
|
|
||||||
|
|
||||||
class MasterBase(MiniSoC, AMPSoC):
|
class MasterBase(MiniSoC, AMPSoC):
|
||||||
mem_map = {
|
mem_map = {
|
||||||
"cri_con": 0x10000000,
|
"cri_con": 0x10000000,
|
||||||
|
@ -640,77 +563,184 @@ class SatelliteBase(BaseSoC, AMPSoC):
|
||||||
self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
|
self.get_native_sdram_if(), cpu_dw=self.cpu_dw)
|
||||||
self.csr_devices.append("rtio_analyzer")
|
self.csr_devices.append("rtio_analyzer")
|
||||||
|
|
||||||
|
class GenericStandalone(StandaloneBase):
|
||||||
class Master(MasterBase):
|
def __init__(self, description, hw_rev=None,**kwargs):
|
||||||
def __init__(self, hw_rev=None, **kwargs):
|
|
||||||
if hw_rev is None:
|
if hw_rev is None:
|
||||||
hw_rev = "v2.0"
|
hw_rev = description["hw_rev"]
|
||||||
MasterBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
self.class_name_override = description["variant"]
|
||||||
|
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
||||||
|
self.config["RTIO_FREQUENCY"] = "{:.1f}".format(description["rtio_frequency"]/1e6)
|
||||||
|
if "ext_ref_frequency" in description:
|
||||||
|
self.config["SI5324_EXT_REF"] = None
|
||||||
|
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
||||||
|
description["ext_ref_frequency"]/1e6)
|
||||||
|
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 = []
|
self.rtio_channels = []
|
||||||
|
eem_7series.add_peripherals(self, description["peripherals"])
|
||||||
phy = ttl_simple.Output(self.platform.request("user_led", 0))
|
if hw_rev in ("v1.0", "v1.1"):
|
||||||
self.submodules += phy
|
for i in (1, 2):
|
||||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
print("SFP LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
# matches Tester EEM numbers
|
sfp_ctl = self.platform.request("sfp_ctl", i)
|
||||||
eem.DIO.add_std(self, 5,
|
phy = ttl_simple.Output(sfp_ctl.led)
|
||||||
ttl_serdes_7series.InOut_8X, ttl_serdes_7series.Output_8X)
|
self.submodules += phy
|
||||||
eem.Urukul.add_std(self, 0, 1, ttl_serdes_7series.Output_8X)
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
if hw_rev in ("v1.1", "v2.0"):
|
||||||
|
for i in range(3):
|
||||||
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
|
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
||||||
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
self.config["HAS_RTIO_LOG"] = None
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels)
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
||||||
|
|
||||||
|
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.crg.cd_sys.clk, getattr(self, grabber).deserializer.cd_cl.clk)
|
||||||
|
|
||||||
|
|
||||||
class Satellite(SatelliteBase):
|
class GenericMaster(MasterBase):
|
||||||
def __init__(self, hw_rev=None, **kwargs):
|
def __init__(self, description, hw_rev=None, **kwargs):
|
||||||
if hw_rev is None:
|
if hw_rev is None:
|
||||||
hw_rev = "v2.0"
|
hw_rev = description["hw_rev"]
|
||||||
SatelliteBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
self.class_name_override = description["variant"]
|
||||||
|
has_drtio_over_eem = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
||||||
|
MasterBase.__init__(self,
|
||||||
|
hw_rev=hw_rev,
|
||||||
|
rtio_clk_freq=description["rtio_frequency"],
|
||||||
|
enable_sata=description["enable_sata_drtio"],
|
||||||
|
enable_sys5x=has_drtio_over_eem,
|
||||||
|
**kwargs)
|
||||||
|
if "ext_ref_frequency" in description:
|
||||||
|
self.config["SI5324_EXT_REF"] = None
|
||||||
|
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
||||||
|
description["ext_ref_frequency"]/1e6)
|
||||||
|
if hw_rev == "v1.0":
|
||||||
|
# EEM clock fan-out from Si5324, not MMCX
|
||||||
|
self.comb += self.platform.request("clk_sel").eq(1)
|
||||||
|
|
||||||
|
if has_drtio_over_eem:
|
||||||
|
self.eem_drtio_channels = []
|
||||||
|
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
||||||
|
if has_grabber:
|
||||||
|
self.grabber_csr_group = []
|
||||||
|
|
||||||
self.rtio_channels = []
|
self.rtio_channels = []
|
||||||
phy = ttl_simple.Output(self.platform.request("user_led", 0))
|
eem_7series.add_peripherals(self, description["peripherals"])
|
||||||
self.submodules += phy
|
if hw_rev in ("v1.1", "v2.0"):
|
||||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
for i in range(3):
|
||||||
# matches Tester EEM numbers
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
eem.DIO.add_std(self, 5,
|
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
||||||
ttl_serdes_7series.InOut_8X, ttl_serdes_7series.Output_8X)
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels)
|
self.config["HAS_RTIO_LOG"] = None
|
||||||
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
|
if has_drtio_over_eem:
|
||||||
|
self.add_eem_drtio(self.eem_drtio_channels)
|
||||||
|
self.add_drtio_cpuif_groups()
|
||||||
|
|
||||||
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
||||||
|
|
||||||
|
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.gt_drtio.gtps[0].txoutclk, getattr(self, grabber).deserializer.cd_cl.clk)
|
||||||
|
|
||||||
|
|
||||||
VARIANTS = {cls.__name__.lower(): cls for cls in [Tester, SUServo, Master, Satellite]}
|
class GenericSatellite(SatelliteBase):
|
||||||
|
def __init__(self, description, hw_rev=None, **kwargs):
|
||||||
|
if hw_rev is None:
|
||||||
|
hw_rev = description["hw_rev"]
|
||||||
|
self.class_name_override = description["variant"]
|
||||||
|
SatelliteBase.__init__(self,
|
||||||
|
hw_rev=hw_rev,
|
||||||
|
rtio_clk_freq=description["rtio_frequency"],
|
||||||
|
enable_sata=description["enable_sata_drtio"],
|
||||||
|
**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 = []
|
||||||
|
eem_7series.add_peripherals(self, description["peripherals"])
|
||||||
|
if hw_rev in ("v1.1", "v2.0"):
|
||||||
|
for i in range(3):
|
||||||
|
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
||||||
|
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
||||||
|
self.submodules += phy
|
||||||
|
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
|
||||||
|
self.config["HAS_RTIO_LOG"] = None
|
||||||
|
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
||||||
|
self.rtio_channels.append(rtio.LogChannel())
|
||||||
|
|
||||||
|
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
||||||
|
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.gt_drtio.gtps[0].txoutclk, getattr(self, grabber).deserializer.cd_cl.clk)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description="ARTIQ device binary builder for Kasli systems")
|
description="ARTIQ device binary builder for generic Kasli systems")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
soc_kasli_args(parser)
|
soc_kasli_args(parser)
|
||||||
parser.set_defaults(output_dir="artiq_kasli")
|
parser.set_defaults(output_dir="artiq_kasli")
|
||||||
parser.add_argument("-V", "--variant", default="tester",
|
parser.add_argument("description", metavar="DESCRIPTION",
|
||||||
help="variant: {} (default: %(default)s)".format(
|
help="JSON system description file")
|
||||||
"/".join(sorted(VARIANTS.keys()))))
|
|
||||||
parser.add_argument("--tester-dds", default=None,
|
|
||||||
help="Tester variant DDS type: ad9910/ad9912 "
|
|
||||||
"(default: ad9910)")
|
|
||||||
parser.add_argument("--gateware-identifier-str", default=None,
|
parser.add_argument("--gateware-identifier-str", default=None,
|
||||||
help="Override ROM identifier")
|
help="Override ROM identifier")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
description = jsondesc.load(args.description)
|
||||||
|
|
||||||
argdict = dict()
|
min_artiq_version = description["min_artiq_version"]
|
||||||
argdict["gateware_identifier_str"] = args.gateware_identifier_str
|
if Version(artiq_version) < Version(min_artiq_version):
|
||||||
argdict["dds"] = args.tester_dds
|
logger.warning("ARTIQ version mismatch: current %s < %s minimum",
|
||||||
|
artiq_version, min_artiq_version)
|
||||||
|
|
||||||
variant = args.variant.lower()
|
if description["target"] != "kasli":
|
||||||
try:
|
raise ValueError("Description is for a different target")
|
||||||
cls = VARIANTS[variant]
|
|
||||||
except KeyError:
|
|
||||||
raise SystemExit("Invalid variant (-V/--variant)")
|
|
||||||
|
|
||||||
soc = cls(**soc_kasli_argdict(args), **argdict)
|
if description["drtio_role"] == "standalone":
|
||||||
|
cls = GenericStandalone
|
||||||
|
elif description["drtio_role"] == "master":
|
||||||
|
cls = GenericMaster
|
||||||
|
elif description["drtio_role"] == "satellite":
|
||||||
|
cls = GenericSatellite
|
||||||
|
else:
|
||||||
|
raise ValueError("Invalid DRTIO role")
|
||||||
|
|
||||||
|
has_shuttler = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
||||||
|
if has_shuttler and (description["drtio_role"] == "standalone"):
|
||||||
|
raise ValueError("Shuttler requires DRTIO, please switch role to master")
|
||||||
|
|
||||||
|
soc = cls(description, gateware_identifier_str=args.gateware_identifier_str, **soc_kasli_argdict(args))
|
||||||
|
args.variant = description["variant"]
|
||||||
build_artiq_soc(soc, builder_argdict(args))
|
build_artiq_soc(soc, builder_argdict(args))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,201 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import logging
|
|
||||||
from packaging.version import Version
|
|
||||||
|
|
||||||
from misoc.integration.builder import builder_args, builder_argdict
|
|
||||||
from misoc.targets.kasli import soc_kasli_args, soc_kasli_argdict
|
|
||||||
|
|
||||||
from artiq import __version__ as artiq_version
|
|
||||||
from artiq.coredevice import jsondesc
|
|
||||||
from artiq.gateware import rtio, eem_7series
|
|
||||||
from artiq.gateware.rtio.phy import ttl_simple
|
|
||||||
from artiq.gateware.targets.kasli import StandaloneBase, MasterBase, SatelliteBase
|
|
||||||
from artiq.build_soc import *
|
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
class GenericStandalone(StandaloneBase):
|
|
||||||
def __init__(self, description, hw_rev=None,**kwargs):
|
|
||||||
if hw_rev is None:
|
|
||||||
hw_rev = description["hw_rev"]
|
|
||||||
self.class_name_override = description["variant"]
|
|
||||||
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
|
||||||
self.config["RTIO_FREQUENCY"] = "{:.1f}".format(description["rtio_frequency"]/1e6)
|
|
||||||
if "ext_ref_frequency" in description:
|
|
||||||
self.config["SI5324_EXT_REF"] = None
|
|
||||||
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
|
||||||
description["ext_ref_frequency"]/1e6)
|
|
||||||
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 = []
|
|
||||||
eem_7series.add_peripherals(self, description["peripherals"])
|
|
||||||
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))
|
|
||||||
if hw_rev in ("v1.1", "v2.0"):
|
|
||||||
for i in range(3):
|
|
||||||
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
|
||||||
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
|
||||||
self.submodules += phy
|
|
||||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
|
||||||
|
|
||||||
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.crg.cd_sys.clk, getattr(self, grabber).deserializer.cd_cl.clk)
|
|
||||||
|
|
||||||
|
|
||||||
class GenericMaster(MasterBase):
|
|
||||||
def __init__(self, description, hw_rev=None, **kwargs):
|
|
||||||
if hw_rev is None:
|
|
||||||
hw_rev = description["hw_rev"]
|
|
||||||
self.class_name_override = description["variant"]
|
|
||||||
has_drtio_over_eem = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
|
||||||
MasterBase.__init__(self,
|
|
||||||
hw_rev=hw_rev,
|
|
||||||
rtio_clk_freq=description["rtio_frequency"],
|
|
||||||
enable_sata=description["enable_sata_drtio"],
|
|
||||||
enable_sys5x=has_drtio_over_eem,
|
|
||||||
**kwargs)
|
|
||||||
if "ext_ref_frequency" in description:
|
|
||||||
self.config["SI5324_EXT_REF"] = None
|
|
||||||
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
|
||||||
description["ext_ref_frequency"]/1e6)
|
|
||||||
if hw_rev == "v1.0":
|
|
||||||
# EEM clock fan-out from Si5324, not MMCX
|
|
||||||
self.comb += self.platform.request("clk_sel").eq(1)
|
|
||||||
|
|
||||||
if has_drtio_over_eem:
|
|
||||||
self.eem_drtio_channels = []
|
|
||||||
has_grabber = any(peripheral["type"] == "grabber" for peripheral in description["peripherals"])
|
|
||||||
if has_grabber:
|
|
||||||
self.grabber_csr_group = []
|
|
||||||
|
|
||||||
self.rtio_channels = []
|
|
||||||
eem_7series.add_peripherals(self, description["peripherals"])
|
|
||||||
if hw_rev in ("v1.1", "v2.0"):
|
|
||||||
for i in range(3):
|
|
||||||
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
|
||||||
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
|
||||||
self.submodules += phy
|
|
||||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
if has_drtio_over_eem:
|
|
||||||
self.add_eem_drtio(self.eem_drtio_channels)
|
|
||||||
self.add_drtio_cpuif_groups()
|
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
|
||||||
|
|
||||||
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.gt_drtio.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"]
|
|
||||||
self.class_name_override = description["variant"]
|
|
||||||
SatelliteBase.__init__(self,
|
|
||||||
hw_rev=hw_rev,
|
|
||||||
rtio_clk_freq=description["rtio_frequency"],
|
|
||||||
enable_sata=description["enable_sata_drtio"],
|
|
||||||
**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 = []
|
|
||||||
eem_7series.add_peripherals(self, description["peripherals"])
|
|
||||||
if hw_rev in ("v1.1", "v2.0"):
|
|
||||||
for i in range(3):
|
|
||||||
print("USER LED at RTIO channel 0x{:06x}".format(len(self.rtio_channels)))
|
|
||||||
phy = ttl_simple.Output(self.platform.request("user_led", i))
|
|
||||||
self.submodules += phy
|
|
||||||
self.rtio_channels.append(rtio.Channel.from_phy(phy))
|
|
||||||
|
|
||||||
self.config["HAS_RTIO_LOG"] = None
|
|
||||||
self.config["RTIO_LOG_CHANNEL"] = len(self.rtio_channels)
|
|
||||||
self.rtio_channels.append(rtio.LogChannel())
|
|
||||||
|
|
||||||
self.add_rtio(self.rtio_channels, sed_lanes=description["sed_lanes"])
|
|
||||||
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.gt_drtio.gtps[0].txoutclk, getattr(self, grabber).deserializer.cd_cl.clk)
|
|
||||||
|
|
||||||
|
|
||||||
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",
|
|
||||||
help="JSON system description file")
|
|
||||||
parser.add_argument("--gateware-identifier-str", default=None,
|
|
||||||
help="Override ROM identifier")
|
|
||||||
args = parser.parse_args()
|
|
||||||
description = jsondesc.load(args.description)
|
|
||||||
|
|
||||||
min_artiq_version = description["min_artiq_version"]
|
|
||||||
if Version(artiq_version) < Version(min_artiq_version):
|
|
||||||
logger.warning("ARTIQ version mismatch: current %s < %s minimum",
|
|
||||||
artiq_version, min_artiq_version)
|
|
||||||
|
|
||||||
if description["target"] != "kasli":
|
|
||||||
raise ValueError("Description is for a different target")
|
|
||||||
|
|
||||||
if description["drtio_role"] == "standalone":
|
|
||||||
cls = GenericStandalone
|
|
||||||
elif description["drtio_role"] == "master":
|
|
||||||
cls = GenericMaster
|
|
||||||
elif description["drtio_role"] == "satellite":
|
|
||||||
cls = GenericSatellite
|
|
||||||
else:
|
|
||||||
raise ValueError("Invalid DRTIO role")
|
|
||||||
|
|
||||||
has_shuttler = any(peripheral["type"] == "shuttler" for peripheral in description["peripherals"])
|
|
||||||
if has_shuttler and (description["drtio_role"] == "standalone"):
|
|
||||||
raise ValueError("Shuttler requires DRTIO, please switch role to master")
|
|
||||||
|
|
||||||
soc = cls(description, gateware_identifier_str=args.gateware_identifier_str, **soc_kasli_argdict(args))
|
|
||||||
args.variant = description["variant"]
|
|
||||||
build_artiq_soc(soc, builder_argdict(args))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
main()
|
|
|
@ -16,7 +16,7 @@ ARTIQ itself does not depend on Nix, and it is also possible to compile everythi
|
||||||
* Enable flakes in Nix by e.g. adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (for example ``~/.config/nix/nix.conf``).
|
* Enable flakes in Nix by e.g. adding ``experimental-features = nix-command flakes`` to ``nix.conf`` (for example ``~/.config/nix/nix.conf``).
|
||||||
* Clone the ARTIQ Git repository and run ``nix develop`` at the root (where ``flake.nix`` is).
|
* Clone the ARTIQ Git repository and run ``nix develop`` at the root (where ``flake.nix`` is).
|
||||||
* Make the current source code of ARTIQ available to the Python interpreter by running ``export PYTHONPATH=`pwd`:$PYTHONPATH``.
|
* Make the current source code of ARTIQ available to the Python interpreter by running ``export PYTHONPATH=`pwd`:$PYTHONPATH``.
|
||||||
* You can then build the firmware and gateware with a command such as ``$ python -m artiq.gateware.targets.kasli``. If you are using a JSON system description file, use ``$ python -m artiq.gateware.targets.kasli_generic file.json``.
|
* You can then build the firmware and gateware with a command such as ``$ python -m artiq.gateware.targets.kasli file.json``.
|
||||||
* Flash the binaries into the FPGA board with a command such as ``$ artiq_flash --srcbuild -d artiq_kasli/<your_variant>``. You need to configure OpenOCD as explained :ref:`in the user section <configuring-openocd>`. OpenOCD is already part of the flake's development environment.
|
* Flash the binaries into the FPGA board with a command such as ``$ artiq_flash --srcbuild -d artiq_kasli/<your_variant>``. You need to configure OpenOCD as explained :ref:`in the user section <configuring-openocd>`. OpenOCD is already part of the flake's development environment.
|
||||||
* Check that the board boots and examine the UART messages by running a serial terminal program, e.g. ``$ flterm /dev/ttyUSB1`` (``flterm`` is part of MiSoC and installed in the flake's development environment). Leave the terminal running while you are flashing the board, so that you see the startup messages when the board boots immediately after flashing. You can also restart the board (without reflashing it) with ``$ artiq_flash start``.
|
* Check that the board boots and examine the UART messages by running a serial terminal program, e.g. ``$ flterm /dev/ttyUSB1`` (``flterm`` is part of MiSoC and installed in the flake's development environment). Leave the terminal running while you are flashing the board, so that you see the startup messages when the board boots immediately after flashing. You can also restart the board (without reflashing it) with ``$ artiq_flash start``.
|
||||||
* The communication parameters are 115200 8-N-1. Ensure that your user has access to the serial device (e.g. by adding the user account to the ``dialout`` group).
|
* The communication parameters are 115200 8-N-1. Ensure that your user has access to the serial device (e.g. by adding the user account to the ``dialout`` group).
|
||||||
|
|
Loading…
Reference in New Issue