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 artiq/gui/logo*.svg
|
||||||
include versioneer.py
|
include versioneer.py
|
||||||
include artiq/_version.py
|
include artiq/_version.py
|
||||||
|
include artiq/gateware/targets/kasli_generic.schema.json
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import sys
|
import sys
|
||||||
import json
|
|
||||||
import textwrap
|
import textwrap
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
from itertools import count
|
from itertools import count
|
||||||
|
|
||||||
from artiq import __version__ as artiq_version
|
from artiq import __version__ as artiq_version
|
||||||
|
from artiq.gateware import jsondesc
|
||||||
|
|
||||||
|
|
||||||
def process_header(output, description):
|
def process_header(output, description):
|
||||||
@ -57,8 +57,8 @@ def process_header(output, description):
|
|||||||
}}
|
}}
|
||||||
""").format(
|
""").format(
|
||||||
variant=description["variant"],
|
variant=description["variant"],
|
||||||
core_addr=description.get("core_addr", "192.168.1.70"),
|
core_addr=description["core_addr"],
|
||||||
ref_period=1/(8*description.get("rtio_frequency", 125e6))),
|
ref_period=1/(8*description["rtio_frequency"])),
|
||||||
file=output)
|
file=output)
|
||||||
|
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ class PeripheralManager:
|
|||||||
|
|
||||||
def process_urukul(self, rtio_offset, peripheral):
|
def process_urukul(self, rtio_offset, peripheral):
|
||||||
urukul_name = self.get_name("urukul")
|
urukul_name = self.get_name("urukul")
|
||||||
synchronization = peripheral.get("synchronization", False)
|
synchronization = peripheral["synchronization"]
|
||||||
channel = count(0)
|
channel = count(0)
|
||||||
self.gen("""
|
self.gen("""
|
||||||
device_db["eeprom_{name}"]={{
|
device_db["eeprom_{name}"]={{
|
||||||
@ -181,10 +181,10 @@ class PeripheralManager:
|
|||||||
}}""",
|
}}""",
|
||||||
name=urukul_name,
|
name=urukul_name,
|
||||||
sync_device="\"ttl_{name}_sync\"".format(name=urukul_name) if synchronization else "None",
|
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"])
|
clk_sel=peripheral["clk_sel"])
|
||||||
dds = peripheral.get("dds", "ad9910")
|
dds = peripheral["dds"]
|
||||||
pll_vco = peripheral.get("pll_vco", None)
|
pll_vco = peripheral.get("pll_vco")
|
||||||
for i in range(4):
|
for i in range(4):
|
||||||
if dds == "ad9910":
|
if dds == "ad9910":
|
||||||
self.gen("""
|
self.gen("""
|
||||||
@ -280,8 +280,8 @@ class PeripheralManager:
|
|||||||
}},
|
}},
|
||||||
}}""",
|
}}""",
|
||||||
name=mirny_name,
|
name=mirny_name,
|
||||||
refclk=peripheral.get("refclk", 100e6),
|
refclk=peripheral["refclk"],
|
||||||
clk_sel=peripheral.get("clk_sel", 0))
|
clk_sel=peripheral["clk_sel"])
|
||||||
|
|
||||||
return next(channel)
|
return next(channel)
|
||||||
|
|
||||||
@ -394,7 +394,7 @@ class PeripheralManager:
|
|||||||
}}""",
|
}}""",
|
||||||
sampler_name=sampler_name,
|
sampler_name=sampler_name,
|
||||||
sampler_channel=rtio_offset+next(channel))
|
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):
|
for urukul_name in (urukul0_name, urukul1_name):
|
||||||
self.gen("""
|
self.gen("""
|
||||||
device_db["spi_{urukul_name}"] = {{
|
device_db["spi_{urukul_name}"] = {{
|
||||||
@ -425,10 +425,10 @@ class PeripheralManager:
|
|||||||
}}""",
|
}}""",
|
||||||
urukul_name=urukul_name,
|
urukul_name=urukul_name,
|
||||||
urukul_channel=rtio_offset+next(channel),
|
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"],
|
clk_sel=peripheral["clk_sel"],
|
||||||
pll_vco=",\n \"pll_vco\": {}".format(pll_vco) if pll_vco is not None else "",
|
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)
|
return next(channel)
|
||||||
|
|
||||||
def process_zotino(self, rtio_offset, peripheral):
|
def process_zotino(self, rtio_offset, peripheral):
|
||||||
@ -573,13 +573,12 @@ def main():
|
|||||||
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
with open(args.master_description, "r") as f:
|
master_description = jsondesc.load(args.master_description)
|
||||||
master_description = json.load(f)
|
|
||||||
|
|
||||||
satellites = []
|
satellites = []
|
||||||
for destination, description in args.satellite:
|
for destination, description_path in args.satellite:
|
||||||
with open(description, "r") as f:
|
satellite_description = jsondesc.load(description_path)
|
||||||
satellites.append((int(destination, 0), json.load(f)))
|
satellites.append((int(destination, 0), satellite_description))
|
||||||
|
|
||||||
if args.output is not None:
|
if args.output is not None:
|
||||||
with open(args.output, "w") as f:
|
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
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
import json
|
|
||||||
|
|
||||||
from misoc.integration.builder import builder_args, builder_argdict
|
from misoc.integration.builder import builder_args, builder_argdict
|
||||||
from misoc.targets.kasli import soc_kasli_args, soc_kasli_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.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.gateware.targets.kasli import StandaloneBase, MasterBase, SatelliteBase
|
||||||
from artiq.build_soc import *
|
from artiq.build_soc import *
|
||||||
|
|
||||||
@ -20,7 +18,7 @@ def peripheral_dio(module, peripheral):
|
|||||||
}
|
}
|
||||||
if len(peripheral["ports"]) != 1:
|
if len(peripheral["ports"]) != 1:
|
||||||
raise ValueError("wrong number of ports")
|
raise ValueError("wrong number of ports")
|
||||||
if peripheral.get("edge_counter", False):
|
if peripheral["edge_counter"]:
|
||||||
edge_counter_cls = edge_counter.SimpleEdgeCounter
|
edge_counter_cls = edge_counter.SimpleEdgeCounter
|
||||||
else:
|
else:
|
||||||
edge_counter_cls = None
|
edge_counter_cls = None
|
||||||
@ -37,7 +35,7 @@ def peripheral_urukul(module, peripheral):
|
|||||||
port, port_aux = peripheral["ports"]
|
port, port_aux = peripheral["ports"]
|
||||||
else:
|
else:
|
||||||
raise ValueError("wrong number of ports")
|
raise ValueError("wrong number of ports")
|
||||||
if peripheral.get("synchronization", False):
|
if peripheral["synchronization"]:
|
||||||
sync_gen_cls = ttl_simple.ClockGen
|
sync_gen_cls = ttl_simple.ClockGen
|
||||||
else:
|
else:
|
||||||
sync_gen_cls = None
|
sync_gen_cls = None
|
||||||
@ -110,7 +108,7 @@ def peripheral_fastino(module, peripheral):
|
|||||||
if len(peripheral["ports"]) != 1:
|
if len(peripheral["ports"]) != 1:
|
||||||
raise ValueError("wrong number of ports")
|
raise ValueError("wrong number of ports")
|
||||||
eem.Fastino.add_std(module, peripheral["ports"][0],
|
eem.Fastino.add_std(module, peripheral["ports"][0],
|
||||||
peripheral.get("log2_width", 0))
|
peripheral["log2_width"])
|
||||||
|
|
||||||
|
|
||||||
def peripheral_phaser(module, peripheral):
|
def peripheral_phaser(module, peripheral):
|
||||||
@ -146,7 +144,7 @@ class GenericStandalone(StandaloneBase):
|
|||||||
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
||||||
|
|
||||||
self.config["SI5324_AS_SYNTHESIZER"] = None
|
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:
|
if "ext_ref_frequency" in description:
|
||||||
self.config["SI5324_EXT_REF"] = None
|
self.config["SI5324_EXT_REF"] = None
|
||||||
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
self.config["EXT_REF_FREQUENCY"] = "{:.1f}".format(
|
||||||
@ -189,8 +187,8 @@ class GenericMaster(MasterBase):
|
|||||||
self.class_name_override = description["variant"]
|
self.class_name_override = description["variant"]
|
||||||
MasterBase.__init__(self,
|
MasterBase.__init__(self,
|
||||||
hw_rev=hw_rev,
|
hw_rev=hw_rev,
|
||||||
rtio_clk_freq=description.get("rtio_frequency", 125e6),
|
rtio_clk_freq=description["rtio_frequency"],
|
||||||
enable_sata=description.get("enable_sata_drtio", False),
|
enable_sata=description["enable_sata_drtio"],
|
||||||
**kwargs)
|
**kwargs)
|
||||||
if "ext_ref_frequency" in description:
|
if "ext_ref_frequency" in description:
|
||||||
self.config["SI5324_EXT_REF"] = None
|
self.config["SI5324_EXT_REF"] = None
|
||||||
@ -226,8 +224,8 @@ class GenericSatellite(SatelliteBase):
|
|||||||
self.class_name_override = description["variant"]
|
self.class_name_override = description["variant"]
|
||||||
SatelliteBase.__init__(self,
|
SatelliteBase.__init__(self,
|
||||||
hw_rev=hw_rev,
|
hw_rev=hw_rev,
|
||||||
rtio_clk_freq=description.get("rtio_frequency", 125e6),
|
rtio_clk_freq=description["rtio_frequency"],
|
||||||
enable_sata=description.get("enable_sata_drtio", False),
|
enable_sata=description["enable_sata_drtio"],
|
||||||
**kwargs)
|
**kwargs)
|
||||||
if hw_rev == "v1.0":
|
if hw_rev == "v1.0":
|
||||||
# EEM clock fan-out from Si5324, not MMCX
|
# EEM clock fan-out from Si5324, not MMCX
|
||||||
@ -263,9 +261,7 @@ def main():
|
|||||||
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)
|
||||||
with open(args.description, "r") as f:
|
|
||||||
description = json.load(f)
|
|
||||||
|
|
||||||
if description["target"] != "kasli":
|
if description["target"] != "kasli":
|
||||||
raise ValueError("Description is for a different target")
|
raise ValueError("Description is for a different target")
|
||||||
|
@ -42,7 +42,8 @@
|
|||||||
"core_addr": {
|
"core_addr": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"format": "ipv4",
|
"format": "ipv4",
|
||||||
"description": "IPv4 address"
|
"description": "IPv4 address",
|
||||||
|
"default": "192.168.1.70"
|
||||||
},
|
},
|
||||||
"vendor": {
|
"vendor": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@ -262,7 +263,8 @@
|
|||||||
"maximum": 3
|
"maximum": 3
|
||||||
},
|
},
|
||||||
"pll_n": {
|
"pll_n": {
|
||||||
"type": "integer"
|
"type": "integer",
|
||||||
|
"default": 32
|
||||||
},
|
},
|
||||||
"pll_vco": {
|
"pll_vco": {
|
||||||
"type": "integer"
|
"type": "integer"
|
||||||
|
Loading…
Reference in New Issue
Block a user