forked from M-Labs/artiq
kasli_generic: validate description against schema, use defaults from schema
This commit is contained in:
parent
45b5cfce05
commit
c6807f4594
@ -3,3 +3,4 @@ graft artiq/examples
|
||||
include artiq/gui/logo*.svg
|
||||
include versioneer.py
|
||||
include artiq/_version.py
|
||||
include artiq/gateware/targets/kasli_generic.schema.json
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
import json
|
||||
import textwrap
|
||||
from collections import defaultdict
|
||||
from itertools import count
|
||||
|
||||
from artiq import __version__ as artiq_version
|
||||
from artiq.gateware import jsondesc
|
||||
|
||||
|
||||
def process_header(output, description):
|
||||
@ -57,8 +57,8 @@ def process_header(output, description):
|
||||
}}
|
||||
""").format(
|
||||
variant=description["variant"],
|
||||
core_addr=description.get("core_addr", "192.168.1.70"),
|
||||
ref_period=1/(8*description.get("rtio_frequency", 125e6))),
|
||||
core_addr=description["core_addr"],
|
||||
ref_period=1/(8*description["rtio_frequency"])),
|
||||
file=output)
|
||||
|
||||
|
||||
@ -116,7 +116,7 @@ class PeripheralManager:
|
||||
|
||||
def process_urukul(self, rtio_offset, peripheral):
|
||||
urukul_name = self.get_name("urukul")
|
||||
synchronization = peripheral.get("synchronization", False)
|
||||
synchronization = peripheral["synchronization"]
|
||||
channel = count(0)
|
||||
self.gen("""
|
||||
device_db["eeprom_{name}"]={{
|
||||
@ -181,10 +181,10 @@ class PeripheralManager:
|
||||
}}""",
|
||||
name=urukul_name,
|
||||
sync_device="\"ttl_{name}_sync\"".format(name=urukul_name) if synchronization else "None",
|
||||
refclk=peripheral.get("refclk", self.master_description.get("rtio_frequency", 125e6)),
|
||||
refclk=peripheral.get("refclk", self.master_description["rtio_frequency"]),
|
||||
clk_sel=peripheral["clk_sel"])
|
||||
dds = peripheral.get("dds", "ad9910")
|
||||
pll_vco = peripheral.get("pll_vco", None)
|
||||
dds = peripheral["dds"]
|
||||
pll_vco = peripheral.get("pll_vco")
|
||||
for i in range(4):
|
||||
if dds == "ad9910":
|
||||
self.gen("""
|
||||
@ -280,8 +280,8 @@ class PeripheralManager:
|
||||
}},
|
||||
}}""",
|
||||
name=mirny_name,
|
||||
refclk=peripheral.get("refclk", 100e6),
|
||||
clk_sel=peripheral.get("clk_sel", 0))
|
||||
refclk=peripheral["refclk"],
|
||||
clk_sel=peripheral["clk_sel"])
|
||||
|
||||
return next(channel)
|
||||
|
||||
@ -394,7 +394,7 @@ class PeripheralManager:
|
||||
}}""",
|
||||
sampler_name=sampler_name,
|
||||
sampler_channel=rtio_offset+next(channel))
|
||||
pll_vco = peripheral.get("pll_vco", None)
|
||||
pll_vco = peripheral.get("pll_vco")
|
||||
for urukul_name in (urukul0_name, urukul1_name):
|
||||
self.gen("""
|
||||
device_db["spi_{urukul_name}"] = {{
|
||||
@ -425,10 +425,10 @@ class PeripheralManager:
|
||||
}}""",
|
||||
urukul_name=urukul_name,
|
||||
urukul_channel=rtio_offset+next(channel),
|
||||
refclk=peripheral.get("refclk", self.master_description.get("rtio_frequency", 125e6)),
|
||||
refclk=peripheral.get("refclk", self.master_description["rtio_frequency"]),
|
||||
clk_sel=peripheral["clk_sel"],
|
||||
pll_vco=",\n \"pll_vco\": {}".format(pll_vco) if pll_vco is not None else "",
|
||||
pll_n=peripheral.get("pll_n", 32))
|
||||
pll_n=peripheral["pll_n"])
|
||||
return next(channel)
|
||||
|
||||
def process_zotino(self, rtio_offset, peripheral):
|
||||
@ -573,13 +573,12 @@ def main():
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.master_description, "r") as f:
|
||||
master_description = json.load(f)
|
||||
master_description = jsondesc.load(args.master_description)
|
||||
|
||||
satellites = []
|
||||
for destination, description in args.satellite:
|
||||
with open(description, "r") as f:
|
||||
satellites.append((int(destination, 0), json.load(f)))
|
||||
for destination, description_path in args.satellite:
|
||||
satellite_description = jsondesc.load(description_path)
|
||||
satellites.append((int(destination, 0), satellite_description))
|
||||
|
||||
if args.output is not None:
|
||||
with open(args.output, "w") as f:
|
||||
|
35
artiq/gateware/jsondesc.py
Normal file
35
artiq/gateware/jsondesc.py
Normal file
@ -0,0 +1,35 @@
|
||||
from os import path
|
||||
import json
|
||||
from jsonschema import Draft7Validator, validators
|
||||
|
||||
def extend_with_default(validator_class):
|
||||
validate_properties = validator_class.VALIDATORS["properties"]
|
||||
|
||||
def set_defaults(validator, properties, instance, schema):
|
||||
for property, subschema in properties.items():
|
||||
if "default" in subschema:
|
||||
instance.setdefault(property, subschema["default"])
|
||||
|
||||
for error in validate_properties(
|
||||
validator, properties, instance, schema,
|
||||
):
|
||||
yield error
|
||||
|
||||
return validators.extend(
|
||||
validator_class, {"properties" : set_defaults},
|
||||
)
|
||||
|
||||
schema_path = path.join(path.dirname(__file__), "targets/kasli_generic.schema.json")
|
||||
with open(schema_path, "r") as f:
|
||||
schema = json.load(f)
|
||||
|
||||
validator = extend_with_default(Draft7Validator)(schema)
|
||||
|
||||
def load(description_path):
|
||||
with open(description_path, "r") as f:
|
||||
result = json.load(f)
|
||||
|
||||
global validator
|
||||
validator.validate(result)
|
||||
|
||||
return result
|
@ -1,14 +1,12 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
from misoc.integration.builder import builder_args, builder_argdict
|
||||
from misoc.targets.kasli import soc_kasli_args, soc_kasli_argdict
|
||||
|
||||
from artiq.gateware import rtio
|
||||
from artiq.gateware import rtio, eem, jsondesc
|
||||
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, edge_counter
|
||||
from artiq.gateware import eem
|
||||
from artiq.gateware.targets.kasli import StandaloneBase, MasterBase, SatelliteBase
|
||||
from artiq.build_soc import *
|
||||
|
||||
@ -20,7 +18,7 @@ def peripheral_dio(module, peripheral):
|
||||
}
|
||||
if len(peripheral["ports"]) != 1:
|
||||
raise ValueError("wrong number of ports")
|
||||
if peripheral.get("edge_counter", False):
|
||||
if peripheral["edge_counter"]:
|
||||
edge_counter_cls = edge_counter.SimpleEdgeCounter
|
||||
else:
|
||||
edge_counter_cls = None
|
||||
@ -37,7 +35,7 @@ def peripheral_urukul(module, peripheral):
|
||||
port, port_aux = peripheral["ports"]
|
||||
else:
|
||||
raise ValueError("wrong number of ports")
|
||||
if peripheral.get("synchronization", False):
|
||||
if peripheral["synchronization"]:
|
||||
sync_gen_cls = ttl_simple.ClockGen
|
||||
else:
|
||||
sync_gen_cls = None
|
||||
@ -110,7 +108,7 @@ def peripheral_fastino(module, peripheral):
|
||||
if len(peripheral["ports"]) != 1:
|
||||
raise ValueError("wrong number of ports")
|
||||
eem.Fastino.add_std(module, peripheral["ports"][0],
|
||||
peripheral.get("log2_width", 0))
|
||||
peripheral["log2_width"])
|
||||
|
||||
|
||||
def peripheral_phaser(module, peripheral):
|
||||
@ -146,7 +144,7 @@ class GenericStandalone(StandaloneBase):
|
||||
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
||||
|
||||
self.config["SI5324_AS_SYNTHESIZER"] = None
|
||||
self.config["RTIO_FREQUENCY"] = "{:.1f}".format(description.get("rtio_frequency", 125e6)/1e6)
|
||||
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(
|
||||
@ -189,8 +187,8 @@ class GenericMaster(MasterBase):
|
||||
self.class_name_override = description["variant"]
|
||||
MasterBase.__init__(self,
|
||||
hw_rev=hw_rev,
|
||||
rtio_clk_freq=description.get("rtio_frequency", 125e6),
|
||||
enable_sata=description.get("enable_sata_drtio", False),
|
||||
rtio_clk_freq=description["rtio_frequency"],
|
||||
enable_sata=description["enable_sata_drtio"],
|
||||
**kwargs)
|
||||
if "ext_ref_frequency" in description:
|
||||
self.config["SI5324_EXT_REF"] = None
|
||||
@ -226,8 +224,8 @@ class GenericSatellite(SatelliteBase):
|
||||
self.class_name_override = description["variant"]
|
||||
SatelliteBase.__init__(self,
|
||||
hw_rev=hw_rev,
|
||||
rtio_clk_freq=description.get("rtio_frequency", 125e6),
|
||||
enable_sata=description.get("enable_sata_drtio", False),
|
||||
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
|
||||
@ -263,9 +261,7 @@ def main():
|
||||
parser.add_argument("--gateware-identifier-str", default=None,
|
||||
help="Override ROM identifier")
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(args.description, "r") as f:
|
||||
description = json.load(f)
|
||||
description = jsondesc.load(args.description)
|
||||
|
||||
if description["target"] != "kasli":
|
||||
raise ValueError("Description is for a different target")
|
||||
|
@ -42,7 +42,8 @@
|
||||
"core_addr": {
|
||||
"type": "string",
|
||||
"format": "ipv4",
|
||||
"description": "IPv4 address"
|
||||
"description": "IPv4 address",
|
||||
"default": "192.168.1.70"
|
||||
},
|
||||
"vendor": {
|
||||
"type": "string",
|
||||
@ -262,7 +263,8 @@
|
||||
"maximum": 3
|
||||
},
|
||||
"pll_n": {
|
||||
"type": "integer"
|
||||
"type": "integer",
|
||||
"default": 32
|
||||
},
|
||||
"pll_vco": {
|
||||
"type": "integer"
|
||||
|
Loading…
Reference in New Issue
Block a user