kasli_generic: validate description against schema, use defaults from schema

This commit is contained in:
Astro 2020-12-29 19:18:12 +01:00 committed by Sébastien Bourdeauducq
parent 45b5cfce05
commit c6807f4594
5 changed files with 66 additions and 33 deletions

View File

@ -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

View File

@ -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:

View 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

View File

@ -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")

View File

@ -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"