forked from M-Labs/artiq
Compare commits
69 Commits
Author | SHA1 | Date | |
---|---|---|---|
351a682ebd | |||
abd3c2a0db | |||
b0661ec055 | |||
c60ea58e8d | |||
aeb114adfb | |||
|
80c0aa5bfa | ||
8c88ce8169 | |||
7cf25f8539 | |||
dd78c0e53d | |||
23832ca445 | |||
5fe37cad30 | |||
|
2183c06154 | ||
|
8b69babe8a | ||
|
3e49da3d39 | ||
|
ff1eb4858a | ||
|
56e14bfac7 | ||
|
2cbb2b970c | ||
|
debf64d1c2 | ||
|
cb326aca70 | ||
|
b89a67ef9d | ||
|
0c5fa373d5 | ||
|
01213e2381 | ||
6113ecb199 | |||
9bead085c7 | |||
b53d874c6a | |||
|
61f6619cb0 | ||
|
04952cb230 | ||
162ce813ea | |||
1555fcf4ab | |||
bcff533899 | |||
139e87de36 | |||
51ee9122f2 | |||
76f63b29ba | |||
222825d3a8 | |||
9bbb67c340 | |||
715dac5798 | |||
f0e4862d16 | |||
|
4933686dd0 | ||
|
6969c889d8 | ||
4f5f0538b7 | |||
ea39160006 | |||
|
56315203a9 | ||
|
ed6d927f6c | ||
|
cc811429f4 | ||
5b2e7cb7f3 | |||
41a816fd16 | |||
51239ebdb6 | |||
0303267d7e | |||
0ec01790fe | |||
f23d4e2762 | |||
6020b9c2f1 | |||
|
9b081737d4 | ||
|
17fa5026a5 | ||
|
3312a033eb | ||
a53065ffc8 | |||
|
8eee5dd414 | ||
371dda4a16 | |||
b1ea02ddf0 | |||
e4ddfb303c | |||
|
a7d7e91188 | ||
|
34d0f592f1 | ||
7358262ab3 | |||
6fdfd6103f | |||
e3624ca86d | |||
d6cc10b43c | |||
35f331f82c | |||
a3c5cdeb86 | |||
cc61ee9139 | |||
74371399de |
1
MAJOR_VERSION
Normal file
1
MAJOR_VERSION
Normal file
@ -0,0 +1 @@
|
||||
4
|
@ -29,7 +29,7 @@ Website: https://m-labs.hk/artiq
|
||||
License
|
||||
=======
|
||||
|
||||
Copyright (C) 2014-2018 M-Labs Limited.
|
||||
Copyright (C) 2014-2019 M-Labs Limited.
|
||||
|
||||
ARTIQ is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
|
@ -3,13 +3,6 @@
|
||||
Release notes
|
||||
=============
|
||||
|
||||
ARTIQ-5
|
||||
-------
|
||||
|
||||
5.0
|
||||
***
|
||||
|
||||
|
||||
|
||||
ARTIQ-4
|
||||
-------
|
||||
|
@ -481,6 +481,12 @@ def get_versions():
|
||||
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||
# case we can only use expanded keywords.
|
||||
|
||||
override = os.getenv("VERSIONEER_OVERRIDE")
|
||||
if override:
|
||||
return {"version": override, "full-revisionid": None,
|
||||
"dirty": None,
|
||||
"error": None, "date": None}
|
||||
|
||||
cfg = get_config()
|
||||
verbose = cfg.verbose
|
||||
|
||||
|
@ -221,6 +221,17 @@ class ASTSynthesizer:
|
||||
return asttyped.ListT(elts=elts, ctx=None, type=builtins.TList(),
|
||||
begin_loc=begin_loc, end_loc=end_loc,
|
||||
loc=begin_loc.join(end_loc))
|
||||
elif isinstance(value, tuple):
|
||||
begin_loc = self._add("(")
|
||||
elts = []
|
||||
for index, elt in enumerate(value):
|
||||
elts.append(self.quote(elt))
|
||||
self._add(", ")
|
||||
end_loc = self._add(")")
|
||||
return asttyped.TupleT(elts=elts, ctx=None,
|
||||
type=types.TTuple([e.type for e in elts]),
|
||||
begin_loc=begin_loc, end_loc=end_loc,
|
||||
loc=begin_loc.join(end_loc))
|
||||
elif isinstance(value, numpy.ndarray):
|
||||
begin_loc = self._add("numpy.array([")
|
||||
elts = []
|
||||
@ -1019,7 +1030,7 @@ class Stitcher:
|
||||
|
||||
function_type = types.TRPC(ret_type,
|
||||
service=self.embedding_map.store_object(host_function),
|
||||
async=is_async)
|
||||
is_async=is_async)
|
||||
self.functions[function] = function_type
|
||||
return function_type
|
||||
|
||||
|
@ -66,8 +66,8 @@ class Module:
|
||||
interleaver = transforms.Interleaver(engine=self.engine)
|
||||
invariant_detection = analyses.InvariantDetection(engine=self.engine)
|
||||
|
||||
cast_monomorphizer.visit(src.typedtree)
|
||||
int_monomorphizer.visit(src.typedtree)
|
||||
cast_monomorphizer.visit(src.typedtree)
|
||||
inferencer.visit(src.typedtree)
|
||||
monomorphism_validator.visit(src.typedtree)
|
||||
escape_validator.visit(src.typedtree)
|
||||
|
@ -1426,7 +1426,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||
for index in range(len(lhs.type.elts)):
|
||||
lhs_elt = self.append(ir.GetAttr(lhs, index))
|
||||
rhs_elt = self.append(ir.GetAttr(rhs, index))
|
||||
elt_result = self.append(ir.Compare(op, lhs_elt, rhs_elt))
|
||||
elt_result = self.polymorphic_compare_pair(op, lhs_elt, rhs_elt)
|
||||
if result is None:
|
||||
result = elt_result
|
||||
else:
|
||||
@ -1453,6 +1453,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||
lhs_elt = self.append(ir.GetElem(lhs, index_phi))
|
||||
rhs_elt = self.append(ir.GetElem(rhs, index_phi))
|
||||
body_result = self.polymorphic_compare_pair(op, lhs_elt, rhs_elt)
|
||||
body_end = self.current_block
|
||||
|
||||
loop_body2 = self.add_block("compare.body2")
|
||||
self.current_block = loop_body2
|
||||
@ -1468,8 +1469,8 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||
phi.add_incoming(compare_length, head)
|
||||
loop_head.append(ir.BranchIf(loop_cond, loop_body, tail))
|
||||
phi.add_incoming(ir.Constant(True, builtins.TBool()), loop_head)
|
||||
loop_body.append(ir.BranchIf(body_result, loop_body2, tail))
|
||||
phi.add_incoming(body_result, loop_body)
|
||||
body_end.append(ir.BranchIf(body_result, loop_body2, tail))
|
||||
phi.add_incoming(body_result, body_end)
|
||||
|
||||
if isinstance(op, ast.NotEq):
|
||||
result = self.append(ir.Select(phi,
|
||||
|
@ -11,13 +11,12 @@ class CastMonomorphizer(algorithm.Visitor):
|
||||
self.engine = engine
|
||||
|
||||
def visit_CallT(self, node):
|
||||
self.generic_visit(node)
|
||||
|
||||
if (types.is_builtin(node.func.type, "int") or
|
||||
types.is_builtin(node.func.type, "int32") or
|
||||
types.is_builtin(node.func.type, "int64")):
|
||||
typ = node.type.find()
|
||||
if (not types.is_var(typ["width"]) and
|
||||
len(node.args) == 1 and
|
||||
builtins.is_int(node.args[0].type) and
|
||||
types.is_var(node.args[0].type.find()["width"])):
|
||||
if isinstance(node.args[0], asttyped.BinOpT):
|
||||
@ -29,3 +28,20 @@ class CastMonomorphizer(algorithm.Visitor):
|
||||
|
||||
node.args[0].type.unify(typ)
|
||||
|
||||
if types.is_builtin(node.func.type, "int") or \
|
||||
types.is_builtin(node.func.type, "round"):
|
||||
typ = node.type.find()
|
||||
if types.is_var(typ["width"]):
|
||||
typ["width"].unify(types.TValue(32))
|
||||
|
||||
self.generic_visit(node)
|
||||
|
||||
def visit_CoerceT(self, node):
|
||||
if isinstance(node.value, asttyped.NumT) and \
|
||||
builtins.is_int(node.type) and \
|
||||
builtins.is_int(node.value.type) and \
|
||||
not types.is_var(node.type["width"]) and \
|
||||
types.is_var(node.value.type["width"]):
|
||||
node.value.type.unify(node.type)
|
||||
|
||||
self.generic_visit(node)
|
||||
|
@ -26,22 +26,3 @@ class IntMonomorphizer(algorithm.Visitor):
|
||||
return
|
||||
|
||||
node.type["width"].unify(types.TValue(width))
|
||||
|
||||
def visit_CallT(self, node):
|
||||
self.generic_visit(node)
|
||||
|
||||
if types.is_builtin(node.func.type, "int") or \
|
||||
types.is_builtin(node.func.type, "round"):
|
||||
typ = node.type.find()
|
||||
if types.is_var(typ["width"]):
|
||||
typ["width"].unify(types.TValue(32))
|
||||
|
||||
def visit_CoerceT(self, node):
|
||||
if isinstance(node.value, asttyped.NumT) and \
|
||||
builtins.is_int(node.type) and \
|
||||
builtins.is_int(node.value.type) and \
|
||||
not types.is_var(node.type["width"]) and \
|
||||
types.is_var(node.value.type["width"]):
|
||||
node.value.type.unify(node.type)
|
||||
|
||||
self.generic_visit(node)
|
||||
|
@ -1332,7 +1332,7 @@ class LLVMIRGenerator:
|
||||
llargptr = self.llbuilder.gep(llargs, [ll.Constant(lli32, index)])
|
||||
self.llbuilder.store(llargslot, llargptr)
|
||||
|
||||
if fun_type.async:
|
||||
if fun_type.is_async:
|
||||
self.llbuilder.call(self.llbuiltin("rpc_send_async"),
|
||||
[llservice, lltagptr, llargs])
|
||||
else:
|
||||
@ -1342,7 +1342,7 @@ class LLVMIRGenerator:
|
||||
# Don't waste stack space on saved arguments.
|
||||
self.llbuilder.call(self.llbuiltin("llvm.stackrestore"), [llstackptr])
|
||||
|
||||
if fun_type.async:
|
||||
if fun_type.is_async:
|
||||
# If this RPC is called using an `invoke` ARTIQ IR instruction, there will be
|
||||
# no other instructions in this basic block. Since this RPC is async, it cannot
|
||||
# possibly raise an exception, so add an explicit jump to the normal successor.
|
||||
@ -1556,6 +1556,11 @@ class LLVMIRGenerator:
|
||||
lleltsptr = llglobal.bitcast(lleltsary.type.element.as_pointer())
|
||||
llconst = ll.Constant(llty, [lleltsptr, ll.Constant(lli32, len(llelts))])
|
||||
return llconst
|
||||
elif types.is_tuple(typ):
|
||||
assert isinstance(value, tuple), fail_msg
|
||||
llelts = [self._quote(v, t, lambda: path() + [str(i)])
|
||||
for i, (v, t) in enumerate(zip(value, typ.elts))]
|
||||
return ll.Constant(llty, llelts)
|
||||
elif types.is_rpc(typ) or types.is_c_function(typ) or types.is_builtin_function(typ):
|
||||
# RPC, C and builtin functions have no runtime representation.
|
||||
return ll.Constant(llty, ll.Undefined)
|
||||
|
@ -311,14 +311,14 @@ class TRPC(Type):
|
||||
:ivar ret: (:class:`Type`)
|
||||
return type
|
||||
:ivar service: (int) RPC service number
|
||||
:ivar async: (bool) whether the RPC blocks until return
|
||||
:ivar is_async: (bool) whether the RPC blocks until return
|
||||
"""
|
||||
|
||||
attributes = OrderedDict()
|
||||
|
||||
def __init__(self, ret, service, async=False):
|
||||
def __init__(self, ret, service, is_async=False):
|
||||
assert isinstance(ret, Type)
|
||||
self.ret, self.service, self.async = ret, service, async
|
||||
self.ret, self.service, self.is_async = ret, service, is_async
|
||||
|
||||
def find(self):
|
||||
return self
|
||||
@ -326,7 +326,7 @@ class TRPC(Type):
|
||||
def unify(self, other):
|
||||
if isinstance(other, TRPC) and \
|
||||
self.service == other.service and \
|
||||
self.async == other.async:
|
||||
self.is_async == other.is_async:
|
||||
self.ret.unify(other.ret)
|
||||
elif isinstance(other, TVar):
|
||||
other.unify(self)
|
||||
@ -343,7 +343,7 @@ class TRPC(Type):
|
||||
def __eq__(self, other):
|
||||
return isinstance(other, TRPC) and \
|
||||
self.service == other.service and \
|
||||
self.async == other.async
|
||||
self.is_async == other.is_async
|
||||
|
||||
def __ne__(self, other):
|
||||
return not (self == other)
|
||||
@ -742,7 +742,7 @@ class TypePrinter(object):
|
||||
return signature
|
||||
elif isinstance(typ, TRPC):
|
||||
return "[rpc{} #{}](...)->{}".format(typ.service,
|
||||
" async" if typ.async else "",
|
||||
" async" if typ.is_async else "",
|
||||
self.name(typ.ret, depth + 1))
|
||||
elif isinstance(typ, TBuiltinFunction):
|
||||
return "<function {}>".format(typ.name)
|
||||
|
@ -51,10 +51,6 @@ class Region:
|
||||
(other.range.begin_pos <= self.range.begin_pos <= other.range.end_pos and \
|
||||
self.range.end_pos > other.range.end_pos)
|
||||
|
||||
def contract(self, other):
|
||||
if not self.range:
|
||||
self.range = other.range
|
||||
|
||||
def outlives(lhs, rhs):
|
||||
if not isinstance(lhs, Region): # lhs lives nonlexically
|
||||
return True
|
||||
@ -69,8 +65,11 @@ class Region:
|
||||
|
||||
class RegionOf(algorithm.Visitor):
|
||||
"""
|
||||
Visit an expression and return the list of regions that must
|
||||
be alive for the expression to execute.
|
||||
Visit an expression and return the region that must be alive for the
|
||||
expression to execute.
|
||||
|
||||
For expressions involving multiple regions, the shortest-lived one is
|
||||
returned.
|
||||
"""
|
||||
|
||||
def __init__(self, env_stack, youngest_region):
|
||||
@ -301,17 +300,20 @@ class EscapeValidator(algorithm.Visitor):
|
||||
def visit_assignment(self, target, value):
|
||||
value_region = self._region_of(value)
|
||||
|
||||
# If this is a variable, we might need to contract the live range.
|
||||
if isinstance(value_region, Region):
|
||||
for name in self._names_of(target):
|
||||
region = self._region_of(name)
|
||||
if isinstance(region, Region):
|
||||
region.contract(value_region)
|
||||
|
||||
# If we assign to an attribute of a quoted value, there will be no names
|
||||
# in the assignment lhs.
|
||||
target_names = self._names_of(target) or []
|
||||
|
||||
# Adopt the value region for any variables declared on the lhs.
|
||||
for name in target_names:
|
||||
region = self._region_of(name)
|
||||
if isinstance(region, Region) and not region.present():
|
||||
# Find the name's environment to overwrite the region.
|
||||
for env in self.env_stack[::-1]:
|
||||
if name.id in env:
|
||||
env[name.id] = value_region
|
||||
break
|
||||
|
||||
# The assigned value should outlive the assignee
|
||||
target_regions = [self._region_of(name) for name in target_names]
|
||||
for target_region in target_regions:
|
||||
|
@ -176,7 +176,7 @@ class AD53xx:
|
||||
(AD53XX_CMD_SPECIAL | AD53XX_SPECIAL_CONTROL | 0b0010) << 8)
|
||||
if not blind:
|
||||
ctrl = self.read_reg(channel=0, op=AD53XX_READ_CONTROL)
|
||||
if ctrl != 0b0010:
|
||||
if (ctrl & 0b10111) != 0b00010:
|
||||
raise ValueError("DAC CONTROL readback mismatch")
|
||||
delay(15*us)
|
||||
|
||||
|
@ -256,9 +256,11 @@ class AD9910:
|
||||
self.write32(_AD9910_REG_CFR1, 0x00000002 | (bits << 4))
|
||||
self.cpld.io_update.pulse(1*us)
|
||||
|
||||
# KLUDGE: ref_time default argument is explicitly marked int64() to avoid
|
||||
# silent truncation of explicitly passed timestamps. (Compiler bug?)
|
||||
@kernel
|
||||
def set_mu(self, ftw, pow=0, asf=0x3fff, phase_mode=_PHASE_MODE_DEFAULT,
|
||||
ref_time=-1, profile=0):
|
||||
ref_time=int64(-1), profile=0):
|
||||
"""Set profile 0 data in machine units.
|
||||
|
||||
This uses machine units (FTW, POW, ASF). The frequency tuning word
|
||||
@ -285,8 +287,9 @@ class AD9910:
|
||||
"""
|
||||
if phase_mode == _PHASE_MODE_DEFAULT:
|
||||
phase_mode = self.phase_mode
|
||||
# Align to coarse RTIO which aligns SYNC_CLK
|
||||
at_mu(now_mu() & ~0xf)
|
||||
# Align to coarse RTIO which aligns SYNC_CLK. I.e. clear fine TSC
|
||||
# This will not cause a collision or sequence error.
|
||||
at_mu(now_mu() & ~7)
|
||||
if phase_mode != PHASE_MODE_CONTINUOUS:
|
||||
# Auto-clear phase accumulator on IO_UPDATE.
|
||||
# This is active already for the next IO_UPDATE
|
||||
@ -302,8 +305,8 @@ class AD9910:
|
||||
pow += dt*ftw*self.sysclk_per_mu >> 16
|
||||
self.write64(_AD9910_REG_PROFILE0 + profile, (asf << 16) | pow, ftw)
|
||||
delay_mu(int64(self.io_update_delay))
|
||||
self.cpld.io_update.pulse_mu(8) # assumes 8 mu > t_SYSCLK
|
||||
at_mu(now_mu() & ~0xf)
|
||||
self.cpld.io_update.pulse_mu(8) # assumes 8 mu > t_SYN_CCLK
|
||||
at_mu(now_mu() & ~7) # clear fine TSC again
|
||||
if phase_mode != PHASE_MODE_CONTINUOUS:
|
||||
self.write32(_AD9910_REG_CFR1, 0x00000002)
|
||||
# future IO_UPDATE will activate
|
||||
@ -335,7 +338,7 @@ class AD9910:
|
||||
|
||||
@kernel
|
||||
def set(self, frequency, phase=0.0, amplitude=1.0,
|
||||
phase_mode=_PHASE_MODE_DEFAULT, ref_time=-1, profile=0):
|
||||
phase_mode=_PHASE_MODE_DEFAULT, ref_time=int64(-1), profile=0):
|
||||
"""Set profile 0 data in SI units.
|
||||
|
||||
.. seealso:: :meth:`set_mu`
|
||||
@ -424,10 +427,12 @@ class AD9910:
|
||||
This method first locates a valid SYNC_IN delay at zero validation
|
||||
window size (setup/hold margin) by scanning around `search_seed`. It
|
||||
then looks for similar valid delays at successively larger validation
|
||||
window sizes until none can be found. It then deacreses the validation
|
||||
window sizes until none can be found. It then decreases the validation
|
||||
window a bit to provide some slack and stability and returns the
|
||||
optimal values.
|
||||
|
||||
This method and :meth:`tune_io_update_delay` can be run in any order.
|
||||
|
||||
:param search_seed: Start value for valid SYNC_IN delay search.
|
||||
Defaults to 15 (half range).
|
||||
:return: Tuple of optimal delay and window size.
|
||||
@ -453,7 +458,7 @@ class AD9910:
|
||||
# integrate SMP_ERR statistics for a few hundred cycles
|
||||
delay(100*us)
|
||||
err = urukul_sta_smp_err(self.cpld.sta_read())
|
||||
delay(40*us) # slack
|
||||
delay(100*us) # slack
|
||||
if not (err >> (self.chip_select - 4)) & 1:
|
||||
next_seed = in_delay
|
||||
break
|
||||
@ -496,16 +501,17 @@ class AD9910:
|
||||
self.write32(_AD9910_REG_RAMP_RATE, 0x00010000)
|
||||
# dFTW = 1, (work around negative slope)
|
||||
self.write64(_AD9910_REG_RAMP_STEP, -1, 0)
|
||||
# delay io_update after RTIO/2 edge
|
||||
t = now_mu() + 0x10 & ~0xf
|
||||
# delay io_update after RTIO edge
|
||||
t = now_mu() + 8 & ~7
|
||||
at_mu(t + delay_start)
|
||||
self.cpld.io_update.pulse_mu(32 - delay_start) # realign
|
||||
# assumes a maximum t_SYNC_CLK period
|
||||
self.cpld.io_update.pulse_mu(16 - delay_start) # realign
|
||||
# disable DRG autoclear and LRR on io_update
|
||||
self.write32(_AD9910_REG_CFR1, 0x00000002)
|
||||
# stop DRG
|
||||
self.write64(_AD9910_REG_RAMP_STEP, 0, 0)
|
||||
at_mu(t + 0x1000 + delay_stop)
|
||||
self.cpld.io_update.pulse_mu(32 - delay_stop) # realign
|
||||
self.cpld.io_update.pulse_mu(16 - delay_stop) # realign
|
||||
ftw = self.read32(_AD9910_REG_FTW) # read out effective FTW
|
||||
delay(100*us) # slack
|
||||
# disable DRG
|
||||
@ -525,6 +531,8 @@ class AD9910:
|
||||
This method assumes that the IO_UPDATE TTLOut device has one machine
|
||||
unit resolution (SERDES).
|
||||
|
||||
This method and :meth:`tune_sync_delay` can be run in any order.
|
||||
|
||||
:return: Stable IO_UPDATE delay to be passed to the constructor
|
||||
:class:`AD9910` via the device database.
|
||||
"""
|
||||
|
@ -1,7 +1,7 @@
|
||||
from numpy import int32, int64
|
||||
|
||||
from artiq.language.core import kernel, delay, portable
|
||||
from artiq.language.units import us, ns
|
||||
from artiq.language.units import ms, us, ns
|
||||
from artiq.coredevice.ad9912_reg import *
|
||||
|
||||
from artiq.coredevice import spi2 as spi
|
||||
@ -107,6 +107,7 @@ class AD9912:
|
||||
# I_cp = 375 µA, VCO high range
|
||||
self.write(AD9912_PLLCFG, 0b00000101, length=1)
|
||||
self.cpld.io_update.pulse(2*us)
|
||||
delay(1*ms)
|
||||
|
||||
@kernel
|
||||
def set_att_mu(self, att):
|
||||
@ -135,7 +136,7 @@ class AD9912:
|
||||
After the SPI transfer, the shared IO update pin is pulsed to
|
||||
activate the data.
|
||||
|
||||
:param ftw: Frequency tuning word: 32 bit unsigned.
|
||||
:param ftw: Frequency tuning word: 48 bit unsigned.
|
||||
:param pow: Phase tuning word: 16 bit unsigned.
|
||||
"""
|
||||
# streaming transfer of FTW and POW
|
||||
|
@ -360,8 +360,8 @@ class SPIMaster2Handler(WishboneHandler):
|
||||
def process_message(self, message):
|
||||
self.stb.set_value("1")
|
||||
self.stb.set_value("0")
|
||||
data = message.data
|
||||
if isinstance(message, OutputMessage):
|
||||
data = message.data
|
||||
address = message.address
|
||||
if address == 1:
|
||||
logger.debug("SPI config @%d data=0x%08x",
|
||||
@ -462,7 +462,7 @@ def get_ref_period(devices):
|
||||
|
||||
def get_dds_sysclk(devices):
|
||||
return get_single_device_argument(devices, "artiq.coredevice.ad9914",
|
||||
("ad9914",), "sysclk")
|
||||
("AD9914",), "sysclk")
|
||||
|
||||
|
||||
def create_channel_handlers(vcd_manager, devices, ref_period,
|
||||
@ -485,8 +485,7 @@ def create_channel_handlers(vcd_manager, devices, ref_period,
|
||||
if dds_bus_channel in channel_handlers:
|
||||
dds_handler = channel_handlers[dds_bus_channel]
|
||||
else:
|
||||
dds_handler = DDSHandler(vcd_manager, desc["class"],
|
||||
dds_onehot_sel, dds_sysclk)
|
||||
dds_handler = DDSHandler(vcd_manager, dds_onehot_sel, dds_sysclk)
|
||||
channel_handlers[dds_bus_channel] = dds_handler
|
||||
dds_handler.add_dds_channel(name, dds_channel)
|
||||
if (desc["module"] == "artiq.coredevice.spi2" and
|
||||
|
@ -307,7 +307,7 @@ class CommKernel:
|
||||
args.append(value)
|
||||
|
||||
def _skip_rpc_value(self, tags):
|
||||
tag = tags.pop(0)
|
||||
tag = chr(tags.pop(0))
|
||||
if tag == "t":
|
||||
length = tags.pop(0)
|
||||
for _ in range(length):
|
||||
@ -403,7 +403,7 @@ class CommKernel:
|
||||
return msg
|
||||
|
||||
def _serve_rpc(self, embedding_map):
|
||||
async = self._read_bool()
|
||||
is_async = self._read_bool()
|
||||
service_id = self._read_int32()
|
||||
args, kwargs = self._receive_rpc_args(embedding_map)
|
||||
return_tags = self._read_bytes()
|
||||
@ -413,9 +413,9 @@ class CommKernel:
|
||||
else:
|
||||
service = embedding_map.retrieve_object(service_id)
|
||||
logger.debug("rpc service: [%d]%r%s %r %r -> %s", service_id, service,
|
||||
(" (async)" if async else ""), args, kwargs, return_tags)
|
||||
(" (async)" if is_async else ""), args, kwargs, return_tags)
|
||||
|
||||
if async:
|
||||
if is_async:
|
||||
service(*args, **kwargs)
|
||||
return
|
||||
|
||||
|
@ -23,7 +23,7 @@ class Grabber:
|
||||
count_width = min(31, 2*res_width + 16 - count_shift)
|
||||
# This value is inserted by the gateware to mark the start of a series of
|
||||
# ROI engine outputs for one video frame.
|
||||
self.sentinel = int32(2**count_width)
|
||||
self.sentinel = int32(int64(2**count_width))
|
||||
|
||||
@kernel
|
||||
def setup_roi(self, n, x0, y0, x1, y1):
|
||||
|
@ -1,7 +1,7 @@
|
||||
from artiq.language.core import kernel, delay, portable, at_mu, now_mu
|
||||
from artiq.language.units import us, ms
|
||||
|
||||
from numpy import int32
|
||||
from numpy import int32, int64
|
||||
|
||||
from artiq.coredevice import spi2 as spi
|
||||
|
||||
@ -175,7 +175,7 @@ class CPLD:
|
||||
self.cfg_reg = urukul_cfg(rf_sw=rf_sw, led=0, profile=0,
|
||||
io_update=0, mask_nu=0, clk_sel=clk_sel,
|
||||
sync_sel=sync_sel, rst=0, io_rst=0)
|
||||
self.att_reg = int32(att)
|
||||
self.att_reg = int32(int64(att))
|
||||
self.sync_div = sync_div
|
||||
|
||||
@kernel
|
||||
@ -327,7 +327,7 @@ class CPLD:
|
||||
and align it to the current RTIO timestamp.
|
||||
|
||||
The SYNC_IN signal is derived from the coarse RTIO clock
|
||||
and the divider must be a power of two two.
|
||||
and the divider must be a power of two.
|
||||
Configure ``sync_sel == 0``.
|
||||
|
||||
:param div: SYNC_IN frequency divider. Must be a power of two.
|
||||
|
@ -243,7 +243,7 @@ def setup_from_ddb(ddb):
|
||||
class _DeviceManager:
|
||||
def __init__(self):
|
||||
self.core_addr = None
|
||||
self.new_core_addr = asyncio.Event()
|
||||
self.reconnect_core = asyncio.Event()
|
||||
self.core_connection = None
|
||||
self.core_connector_task = asyncio.ensure_future(self.core_connector())
|
||||
|
||||
@ -268,7 +268,7 @@ class _DeviceManager:
|
||||
|
||||
if core_addr != self.core_addr:
|
||||
self.core_addr = core_addr
|
||||
self.new_core_addr.set()
|
||||
self.reconnect_core.set()
|
||||
|
||||
self.dds_sysclk = dds_sysclk
|
||||
|
||||
@ -383,19 +383,25 @@ class _DeviceManager:
|
||||
widget.cur_override_level = bool(value)
|
||||
widget.refresh_display()
|
||||
|
||||
def disconnect_cb(self):
|
||||
logger.error("lost connection to core device moninj")
|
||||
self.reconnect_core.set()
|
||||
|
||||
async def core_connector(self):
|
||||
while True:
|
||||
await self.new_core_addr.wait()
|
||||
self.new_core_addr.clear()
|
||||
await self.reconnect_core.wait()
|
||||
self.reconnect_core.clear()
|
||||
if self.core_connection is not None:
|
||||
await self.core_connection.close()
|
||||
self.core_connection = None
|
||||
new_core_connection = CommMonInj(self.monitor_cb, self.injection_status_cb,
|
||||
lambda: logger.error("lost connection to core device moninj"))
|
||||
self.disconnect_cb)
|
||||
try:
|
||||
await new_core_connection.connect(self.core_addr, 1383)
|
||||
except:
|
||||
logger.error("failed to connect to core device moninj", exc_info=True)
|
||||
await asyncio.sleep(10.)
|
||||
self.reconnect_core.set()
|
||||
else:
|
||||
self.core_connection = new_core_connection
|
||||
for ttl_channel in self.ttl_widgets.keys():
|
||||
|
@ -178,13 +178,17 @@ class Controllers:
|
||||
raise ValueError
|
||||
|
||||
def __setitem__(self, k, v):
|
||||
if (isinstance(v, dict) and v["type"] == "controller" and
|
||||
self.host_filter in get_ip_addresses(v["host"])):
|
||||
v["command"] = v["command"].format(name=k,
|
||||
bind=self.host_filter,
|
||||
port=v["port"])
|
||||
self.queue.put_nowait(("set", (k, v)))
|
||||
self.active_or_queued.add(k)
|
||||
try:
|
||||
if (isinstance(v, dict) and v["type"] == "controller" and
|
||||
self.host_filter in get_ip_addresses(v["host"])):
|
||||
v["command"] = v["command"].format(name=k,
|
||||
bind=self.host_filter,
|
||||
port=v["port"])
|
||||
self.queue.put_nowait(("set", (k, v)))
|
||||
self.active_or_queued.add(k)
|
||||
except:
|
||||
logger.error("Failed to process device database entry %s", k,
|
||||
exc_info=True)
|
||||
|
||||
def __delitem__(self, k):
|
||||
if k in self.active_or_queued:
|
||||
|
234
artiq/examples/kasli_basic/device_db_berkeley.py
Normal file
234
artiq/examples/kasli_basic/device_db_berkeley.py
Normal file
@ -0,0 +1,234 @@
|
||||
core_addr = "kasli-1.lab.m-labs.hk"
|
||||
|
||||
device_db = {
|
||||
"core": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.core",
|
||||
"class": "Core",
|
||||
"arguments": {"host": core_addr, "ref_period": 1e-9}
|
||||
},
|
||||
"core_log": {
|
||||
"type": "controller",
|
||||
"host": "::1",
|
||||
"port": 1068,
|
||||
"command": "aqctl_corelog -p {port} --bind {bind} " + core_addr
|
||||
},
|
||||
"core_cache": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.cache",
|
||||
"class": "CoreCache"
|
||||
},
|
||||
"core_dma": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.dma",
|
||||
"class": "CoreDMA"
|
||||
},
|
||||
|
||||
"i2c_switch0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.i2c",
|
||||
"class": "PCA9548",
|
||||
"arguments": {"address": 0xe0}
|
||||
},
|
||||
"i2c_switch1": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.i2c",
|
||||
"class": "PCA9548",
|
||||
"arguments": {"address": 0xe2}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
device_db.update({
|
||||
"ttl" + str(i): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut" if i < 4 else "TTLOut",
|
||||
"arguments": {"channel": i},
|
||||
} for i in range(16)
|
||||
})
|
||||
|
||||
|
||||
for j in range(3):
|
||||
device_db.update({
|
||||
"spi_urukul{}".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 16 + 7*j}
|
||||
},
|
||||
"ttl_urukul{}_sync".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLClockGen",
|
||||
"arguments": {"channel": 17 + 7*j, "acc_width": 4}
|
||||
},
|
||||
"ttl_urukul{}_io_update".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 18 + 7*j}
|
||||
},
|
||||
"ttl_urukul{}_sw0".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 19 + 7*j}
|
||||
},
|
||||
"ttl_urukul{}_sw1".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 20 + 7*j}
|
||||
},
|
||||
"ttl_urukul{}_sw2".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 21 + 7*j}
|
||||
},
|
||||
"ttl_urukul{}_sw3".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 22 + 7*j}
|
||||
},
|
||||
"urukul{}_cpld".format(j): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.urukul",
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul{}".format(j),
|
||||
"sync_device": "ttl_urukul{}_sync".format(j),
|
||||
"io_update_device": "ttl_urukul{}_io_update".format(j),
|
||||
"refclk": 125e6,
|
||||
"clk_sel": 2
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
device_db.update({
|
||||
"urukul{}_ch{}".format(j, i): {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 32,
|
||||
"chip_select": 4 + i,
|
||||
"cpld_device": "urukul{}_cpld".format(j),
|
||||
"sw_device": "ttl_urukul{}_sw{}".format(j, i)
|
||||
}
|
||||
} for i in range(4)
|
||||
})
|
||||
|
||||
|
||||
device_db.update(
|
||||
spi_urukul3={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 37}
|
||||
},
|
||||
ttl_urukul3_io_update={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 38}
|
||||
},
|
||||
ttl_urukul3_sw0={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 39}
|
||||
},
|
||||
ttl_urukul3_sw1={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 40}
|
||||
},
|
||||
ttl_urukul3_sw2={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 41}
|
||||
},
|
||||
ttl_urukul3_sw3={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 42}
|
||||
},
|
||||
urukul3_cpld={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.urukul",
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul3",
|
||||
"io_update_device": "ttl_urukul3_io_update",
|
||||
"refclk": 125e6,
|
||||
"clk_sel": 0
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
for i in range(4):
|
||||
device_db["urukul3_ch" + str(i)] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9912",
|
||||
"class": "AD9912",
|
||||
"arguments": {
|
||||
"pll_n": 8,
|
||||
"chip_select": 4 + i,
|
||||
"cpld_device": "urukul3_cpld",
|
||||
"sw_device": "ttl_urukul3_sw" + str(i)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
device_db.update({
|
||||
"spi_zotino0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 43}
|
||||
},
|
||||
"ttl_zotino0_ldac": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 44}
|
||||
},
|
||||
"ttl_zotino0_clr": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 45}
|
||||
},
|
||||
"zotino0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.zotino",
|
||||
"class": "Zotino",
|
||||
"arguments": {
|
||||
"spi_device": "spi_zotino0",
|
||||
"ldac_device": "ttl_zotino0_ldac",
|
||||
"clr_device": "ttl_zotino0_clr"
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
device_db.update({
|
||||
"led0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 46}
|
||||
},
|
||||
"led1": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 47}
|
||||
}
|
||||
})
|
449
artiq/examples/kasli_basic/device_db_nrc.py
Normal file
449
artiq/examples/kasli_basic/device_db_nrc.py
Normal file
@ -0,0 +1,449 @@
|
||||
|
||||
# Autogenerated for the nrc variant
|
||||
core_addr = "192.168.1.75"
|
||||
|
||||
device_db = {
|
||||
"core": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.core",
|
||||
"class": "Core",
|
||||
"arguments": {"host": core_addr, "ref_period": 1e-09}
|
||||
},
|
||||
"core_log": {
|
||||
"type": "controller",
|
||||
"host": "::1",
|
||||
"port": 1068,
|
||||
"command": "aqctl_corelog -p {port} --bind {bind} " + core_addr
|
||||
},
|
||||
"core_cache": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.cache",
|
||||
"class": "CoreCache"
|
||||
},
|
||||
"core_dma": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.dma",
|
||||
"class": "CoreDMA"
|
||||
},
|
||||
|
||||
"i2c_switch0": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.i2c",
|
||||
"class": "PCA9548",
|
||||
"arguments": {"address": 0xe0}
|
||||
},
|
||||
"i2c_switch1": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.i2c",
|
||||
"class": "PCA9548",
|
||||
"arguments": {"address": 0xe2}
|
||||
},
|
||||
}
|
||||
|
||||
# standalone peripherals
|
||||
|
||||
device_db["ttl0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 0x000000},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 0x000001},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl2"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 0x000002},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl3"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLInOut",
|
||||
"arguments": {"channel": 0x000003},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl4"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000004},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl5"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000005},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl6"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000006},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl7"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000007},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl8"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000008},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl9"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000009},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl10"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000a},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl11"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000b},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl12"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000c},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl13"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000d},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl14"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000e},
|
||||
}
|
||||
|
||||
|
||||
device_db["ttl15"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00000f},
|
||||
}
|
||||
|
||||
|
||||
device_db["spi_urukul0"]={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 0x000010}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul0_io_update"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000011}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul0_sw0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000012}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul0_sw1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000013}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul0_sw2"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000014}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul0_sw3"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000015}
|
||||
}
|
||||
|
||||
device_db["urukul0_cpld"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.urukul",
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul0",
|
||||
"sync_device": None,
|
||||
"io_update_device": "ttl_urukul0_io_update",
|
||||
"refclk": 125000000.0,
|
||||
"clk_sel": 2
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul0_ch0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 32,
|
||||
"chip_select": 4,
|
||||
"cpld_device": "urukul0_cpld",
|
||||
"sw_device": "ttl_urukul0_sw0"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul0_ch1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 32,
|
||||
"chip_select": 5,
|
||||
"cpld_device": "urukul0_cpld",
|
||||
"sw_device": "ttl_urukul0_sw1"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul0_ch2"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 32,
|
||||
"chip_select": 6,
|
||||
"cpld_device": "urukul0_cpld",
|
||||
"sw_device": "ttl_urukul0_sw2"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul0_ch3"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 32,
|
||||
"chip_select": 7,
|
||||
"cpld_device": "urukul0_cpld",
|
||||
"sw_device": "ttl_urukul0_sw3"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["spi_urukul1"]={
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 0x000016}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul1_io_update"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000017}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul1_sw0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000018}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul1_sw1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000019}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul1_sw2"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00001a}
|
||||
}
|
||||
|
||||
device_db["ttl_urukul1_sw3"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00001b}
|
||||
}
|
||||
|
||||
device_db["urukul1_cpld"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.urukul",
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul1",
|
||||
"sync_device": None,
|
||||
"io_update_device": "ttl_urukul1_io_update",
|
||||
"refclk": 125000000.0,
|
||||
"clk_sel": 2
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul1_ch0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9912",
|
||||
"class": "AD9912",
|
||||
"arguments": {
|
||||
"pll_n": 8,
|
||||
"chip_select": 4,
|
||||
"cpld_device": "urukul1_cpld",
|
||||
"sw_device": "ttl_urukul1_sw0"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul1_ch1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9912",
|
||||
"class": "AD9912",
|
||||
"arguments": {
|
||||
"pll_n": 8,
|
||||
"chip_select": 5,
|
||||
"cpld_device": "urukul1_cpld",
|
||||
"sw_device": "ttl_urukul1_sw1"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul1_ch2"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9912",
|
||||
"class": "AD9912",
|
||||
"arguments": {
|
||||
"pll_n": 8,
|
||||
"chip_select": 6,
|
||||
"cpld_device": "urukul1_cpld",
|
||||
"sw_device": "ttl_urukul1_sw2"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["urukul1_ch3"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9912",
|
||||
"class": "AD9912",
|
||||
"arguments": {
|
||||
"pll_n": 8,
|
||||
"chip_select": 7,
|
||||
"cpld_device": "urukul1_cpld",
|
||||
"sw_device": "ttl_urukul1_sw3"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["spi_sampler0_adc"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 0x00001c}
|
||||
}
|
||||
device_db["spi_sampler0_pgia"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 0x00001d}
|
||||
}
|
||||
device_db["spi_sampler0_cnv"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x00001e},
|
||||
}
|
||||
device_db["sampler0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.sampler",
|
||||
"class": "Sampler",
|
||||
"arguments": {
|
||||
"spi_adc_device": "spi_sampler0_adc",
|
||||
"spi_pgia_device": "spi_sampler0_pgia",
|
||||
"cnv_device": "spi_sampler0_cnv"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["spi_zotino0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.spi2",
|
||||
"class": "SPIMaster",
|
||||
"arguments": {"channel": 0x00001f}
|
||||
}
|
||||
device_db["ttl_zotino0_ldac"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000020}
|
||||
}
|
||||
device_db["ttl_zotino0_clr"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000021}
|
||||
}
|
||||
device_db["zotino0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.zotino",
|
||||
"class": "Zotino",
|
||||
"arguments": {
|
||||
"spi_device": "spi_zotino0",
|
||||
"ldac_device": "ttl_zotino0_ldac",
|
||||
"clr_device": "ttl_zotino0_clr"
|
||||
}
|
||||
}
|
||||
|
||||
device_db["led0"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000022}
|
||||
}
|
||||
|
||||
device_db["led1"] = {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ttl",
|
||||
"class": "TTLOut",
|
||||
"arguments": {"channel": 0x000023}
|
||||
}
|
@ -1,8 +1,12 @@
|
||||
import sys
|
||||
import os
|
||||
import select
|
||||
|
||||
from artiq.experiment import *
|
||||
|
||||
if os.name == "nt":
|
||||
import msvcrt
|
||||
|
||||
|
||||
def chunker(seq, size):
|
||||
res = []
|
||||
@ -16,11 +20,17 @@ def chunker(seq, size):
|
||||
|
||||
|
||||
def is_enter_pressed() -> TBool:
|
||||
if select.select([sys.stdin,], [], [], 0.0)[0]:
|
||||
sys.stdin.read(1)
|
||||
return True
|
||||
if os.name == "nt":
|
||||
if msvcrt.kbhit() and msvcrt.getch() == b"\r":
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
else:
|
||||
return False
|
||||
if select.select([sys.stdin, ], [], [], 0.0)[0]:
|
||||
sys.stdin.read(1)
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class KasliTester(EnvExperiment):
|
||||
@ -270,14 +280,15 @@ class KasliTester(EnvExperiment):
|
||||
zotino.load()
|
||||
|
||||
def test_zotinos(self):
|
||||
print("*** Testing Zotino DACs.")
|
||||
print("Voltages:")
|
||||
for card_n, (card_name, card_dev) in enumerate(self.zotinos):
|
||||
voltages = [2*card_n + (-1)**i*0.1*(i//2+1) for i in range(32)]
|
||||
print(card_name, " ".join(["{:.1f}".format(x) for x in voltages]))
|
||||
self.set_zotino_voltages(card_dev, voltages)
|
||||
print("Press ENTER when done.")
|
||||
input()
|
||||
if self.zotinos:
|
||||
print("*** Testing Zotino DACs.")
|
||||
print("Voltages:")
|
||||
for card_n, (card_name, card_dev) in enumerate(self.zotinos):
|
||||
voltages = [2*card_n + (-1)**i*0.1*(i//2+1) for i in range(32)]
|
||||
print(card_name, " ".join(["{:.1f}".format(x) for x in voltages]))
|
||||
self.set_zotino_voltages(card_dev, voltages)
|
||||
print("Press ENTER when done.")
|
||||
input()
|
||||
|
||||
@kernel
|
||||
def grabber_capture(self, card_dev, rois):
|
||||
@ -297,21 +308,22 @@ class KasliTester(EnvExperiment):
|
||||
card_dev.input_mu(n)
|
||||
self.core.break_realtime()
|
||||
card_dev.gate_roi(0)
|
||||
print("ROI sums: {}".format(n))
|
||||
print("ROI sums:", n)
|
||||
|
||||
def test_grabbers(self):
|
||||
print("*** Testing Grabber Frame Grabbers.")
|
||||
print("Activate the camera's frame grabber output, type 'g', press "
|
||||
"ENTER, and trigger the camera.")
|
||||
print("Just press ENTER to skip the test.")
|
||||
if input().strip().lower() != "g":
|
||||
print("skipping...")
|
||||
return
|
||||
rois = [[0, 0, 0, 2, 2], [1, 0, 0, 2048, 2048]]
|
||||
print("ROIs: {}".format(rois))
|
||||
for card_n, (card_name, card_dev) in enumerate(self.grabbers):
|
||||
print(card_name)
|
||||
self.grabber_capture(card_dev, rois)
|
||||
if self.grabbers:
|
||||
print("*** Testing Grabber Frame Grabbers.")
|
||||
print("Activate the camera's frame grabber output, type 'g', press "
|
||||
"ENTER, and trigger the camera.")
|
||||
print("Just press ENTER to skip the test.")
|
||||
if input().strip().lower() != "g":
|
||||
print("skipping...")
|
||||
return
|
||||
rois = [[0, 0, 0, 2, 2], [1, 0, 0, 2048, 2048]]
|
||||
print("ROIs:", rois)
|
||||
for card_n, (card_name, card_dev) in enumerate(self.grabbers):
|
||||
print(card_name)
|
||||
self.grabber_capture(card_dev, rois)
|
||||
|
||||
def run(self):
|
||||
print("****** Kasli system tester ******")
|
||||
|
@ -6,9 +6,9 @@ class DDSTest(EnvExperiment):
|
||||
|
||||
def build(self):
|
||||
self.setattr_device("core")
|
||||
self.setattr_device("dds0")
|
||||
self.setattr_device("dds1")
|
||||
self.setattr_device("dds2")
|
||||
self.dds0 = self.get_device("ad9914dds0")
|
||||
self.dds1 = self.get_device("ad9914dds1")
|
||||
self.dds2 = self.get_device("ad9914dds2")
|
||||
self.setattr_device("ttl0")
|
||||
self.setattr_device("ttl1")
|
||||
self.setattr_device("ttl2")
|
||||
|
@ -44,7 +44,7 @@ class TDR(EnvExperiment):
|
||||
try:
|
||||
self.many(n, self.core.seconds_to_mu(pulse))
|
||||
except PulseNotReceivedError:
|
||||
print("to few edges: cable too long or wiring bad")
|
||||
print("too few edges: cable too long or wiring bad")
|
||||
else:
|
||||
print(self.t)
|
||||
t_rise = mu_to_seconds(self.t[0], self.core)/n - latency
|
||||
|
@ -207,7 +207,7 @@ pub extern fn main() -> i32 {
|
||||
println!(r"|_| |_|_|____/ \___/ \____|");
|
||||
println!("");
|
||||
println!("MiSoC Bootloader");
|
||||
println!("Copyright (c) 2017-2018 M-Labs Limited");
|
||||
println!("Copyright (c) 2017-2019 M-Labs Limited");
|
||||
println!("");
|
||||
|
||||
if startup() {
|
||||
|
@ -68,6 +68,7 @@ static mut API: &'static [(&'static str, *const ())] = &[
|
||||
api!(sqrt),
|
||||
api!(round),
|
||||
api!(floor),
|
||||
api!(fmod),
|
||||
|
||||
/* exceptions */
|
||||
api!(_Unwind_Resume = ::unwind::_Unwind_Resume),
|
||||
|
@ -9,6 +9,7 @@ enum State {
|
||||
Watch
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct Info {
|
||||
state: State,
|
||||
frame_size: (u16, u16),
|
||||
|
@ -7,7 +7,8 @@ pub enum Error {
|
||||
Truncated { offset: usize },
|
||||
InvalidSize { offset: usize, size: usize },
|
||||
MissingSeparator { offset: usize },
|
||||
Utf8Error(str::Utf8Error)
|
||||
Utf8Error(str::Utf8Error),
|
||||
NoFlash,
|
||||
}
|
||||
|
||||
impl fmt::Display for Error {
|
||||
@ -24,40 +25,13 @@ impl fmt::Display for Error {
|
||||
&Error::MissingSeparator { offset } =>
|
||||
write!(f, "missing separator at offset {}", offset),
|
||||
&Error::Utf8Error(err) =>
|
||||
write!(f, "{}", err)
|
||||
write!(f, "{}", err),
|
||||
&Error::NoFlash =>
|
||||
write!(f, "flash memory is not present"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FmtWrapper<'a> {
|
||||
buf: &'a mut [u8],
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> FmtWrapper<'a> {
|
||||
fn new(buf: &'a mut [u8]) -> Self {
|
||||
FmtWrapper {
|
||||
buf: buf,
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn contents(&self) -> &[u8] {
|
||||
&self.buf[..self.offset]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for FmtWrapper<'a> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
let bytes = s.as_bytes();
|
||||
let remainder = &mut self.buf[self.offset..];
|
||||
let remainder = &mut remainder[..bytes.len()];
|
||||
remainder.copy_from_slice(bytes);
|
||||
self.offset += bytes.len();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(has_spiflash)]
|
||||
mod imp {
|
||||
use core::str;
|
||||
@ -65,8 +39,37 @@ mod imp {
|
||||
use cache;
|
||||
use spiflash;
|
||||
use super::Error;
|
||||
use core::fmt;
|
||||
use core::fmt::Write;
|
||||
use super::FmtWrapper;
|
||||
|
||||
struct FmtWrapper<'a> {
|
||||
buf: &'a mut [u8],
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
impl<'a> FmtWrapper<'a> {
|
||||
fn new(buf: &'a mut [u8]) -> Self {
|
||||
FmtWrapper {
|
||||
buf: buf,
|
||||
offset: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn contents(&self) -> &[u8] {
|
||||
&self.buf[..self.offset]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Write for FmtWrapper<'a> {
|
||||
fn write_str(&mut self, s: &str) -> fmt::Result {
|
||||
let bytes = s.as_bytes();
|
||||
let remainder = &mut self.buf[self.offset..];
|
||||
let remainder = &mut remainder[..bytes.len()];
|
||||
remainder.copy_from_slice(bytes);
|
||||
self.offset += bytes.len();
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// One flash sector immediately before the firmware.
|
||||
const ADDR: usize = ::mem::FLASH_BOOT_ADDRESS - spiflash::SECTOR_SIZE;
|
||||
@ -284,24 +287,26 @@ mod imp {
|
||||
|
||||
#[cfg(not(has_spiflash))]
|
||||
mod imp {
|
||||
use super::Error;
|
||||
|
||||
pub fn read<F: FnOnce(Result<&[u8], Error>) -> R, R>(_key: &str, f: F) -> R {
|
||||
f(Err(()))
|
||||
f(Err(Error::NoFlash))
|
||||
}
|
||||
|
||||
pub fn read_str<F: FnOnce(Result<&str, Error>) -> R, R>(_key: &str, f: F) -> R {
|
||||
f(Err(()))
|
||||
f(Err(Error::NoFlash))
|
||||
}
|
||||
|
||||
pub fn write(_key: &str, _value: &[u8]) -> Result<(), Error> {
|
||||
Err(())
|
||||
Err(Error::NoFlash)
|
||||
}
|
||||
|
||||
pub fn remove(_key: &str) -> Result<(), Error> {
|
||||
Err(())
|
||||
Err(Error::NoFlash)
|
||||
}
|
||||
|
||||
pub fn erase() -> Result<(), Error> {
|
||||
Err(())
|
||||
Err(Error::NoFlash)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -255,13 +255,14 @@ mod tag {
|
||||
Tag::Int32 => 4,
|
||||
Tag::Int64 => 8,
|
||||
Tag::Float64 => 8,
|
||||
Tag::String => 4,
|
||||
Tag::String => 8,
|
||||
Tag::Bytes => 8,
|
||||
Tag::ByteArray => 8,
|
||||
Tag::Tuple(it, arity) => {
|
||||
let mut size = 0;
|
||||
let mut it = it.clone();
|
||||
for _ in 0..arity {
|
||||
let tag = it.clone().next().expect("truncated tag");
|
||||
let tag = it.next().expect("truncated tag");
|
||||
size += tag.size();
|
||||
}
|
||||
size
|
||||
|
@ -223,7 +223,7 @@ unsafe fn kern_load(io: &Io, session: &mut Session, library: &[u8])
|
||||
Err(Error::Load(format!("{}", error)))
|
||||
}
|
||||
other =>
|
||||
unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
unexpected!("unexpected kernel CPU reply to load request: {:?}", other)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -274,15 +274,22 @@ fn process_host_message(io: &Io,
|
||||
let slot = kern_recv(io, |reply| {
|
||||
match reply {
|
||||
&kern::RpcRecvRequest(slot) => Ok(slot),
|
||||
other => unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
other => unexpected!(
|
||||
"expected root value slot from kernel CPU, not {:?}", other)
|
||||
}
|
||||
})?;
|
||||
rpc::recv_return(stream, &tag, slot, &|size| -> Result<_, Error<SchedError>> {
|
||||
if size == 0 {
|
||||
// Don't try to allocate zero-length values, as RpcRecvReply(0) is
|
||||
// used to terminate the kernel-side receive loop.
|
||||
return Ok(0 as *mut ())
|
||||
}
|
||||
kern_send(io, &kern::RpcRecvReply(Ok(size)))?;
|
||||
Ok(kern_recv(io, |reply| {
|
||||
match reply {
|
||||
&kern::RpcRecvRequest(slot) => Ok(slot),
|
||||
other => unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
other => unexpected!(
|
||||
"expected nested value slot from kernel CPU, not {:?}", other)
|
||||
}
|
||||
})?)
|
||||
})?;
|
||||
@ -301,8 +308,8 @@ fn process_host_message(io: &Io,
|
||||
kern_recv(io, |reply| {
|
||||
match reply {
|
||||
&kern::RpcRecvRequest(_) => Ok(()),
|
||||
other =>
|
||||
unexpected!("unexpected reply from kernel CPU: {:?}", other)
|
||||
other => unexpected!(
|
||||
"expected (ignored) root value slot from kernel CPU, not {:?}", other)
|
||||
}
|
||||
})?;
|
||||
|
||||
|
@ -302,6 +302,7 @@ pub extern fn main() -> i32 {
|
||||
unsafe {
|
||||
csr::drtio_transceiver::stable_clkin_write(1);
|
||||
}
|
||||
clock::spin_us(1500); // wait for CPLL/QPLL lock
|
||||
init_rtio_crg();
|
||||
|
||||
#[cfg(has_allaki_atts)]
|
||||
|
@ -175,7 +175,7 @@ def _action_scan_devices(remote, args):
|
||||
|
||||
|
||||
def _action_scan_repository(remote, args):
|
||||
if args.async:
|
||||
if getattr(args, "async"):
|
||||
remote.scan_repository_async(args.revision)
|
||||
else:
|
||||
remote.scan_repository(args.revision)
|
||||
|
@ -213,6 +213,10 @@ def main():
|
||||
smgr.start()
|
||||
atexit_register_coroutine(smgr.stop)
|
||||
|
||||
# work around for https://github.com/m-labs/artiq/issues/1307
|
||||
d_ttl_dds.ttl_dock.show()
|
||||
d_ttl_dds.dds_dock.show()
|
||||
|
||||
# create first log dock if not already in state
|
||||
d_log0 = logmgr.first_log_dock()
|
||||
if d_log0 is not None:
|
||||
|
@ -175,7 +175,7 @@ def _build_experiment(device_mgr, dataset_mgr, args):
|
||||
file = getattr(module, "__file__")
|
||||
expid = {
|
||||
"file": file,
|
||||
"experiment": args.experiment,
|
||||
"class_name": args.experiment,
|
||||
"arguments": arguments
|
||||
}
|
||||
device_mgr.virtual_devices["scheduler"].expid = expid
|
||||
|
@ -493,6 +493,7 @@ class SUServo(_EEM):
|
||||
sampler_pads = servo_pads.SamplerPads(target.platform, eem_sampler)
|
||||
urukul_pads = servo_pads.UrukulPads(
|
||||
target.platform, eem_urukul0, eem_urukul1)
|
||||
target.submodules += sampler_pads, urukul_pads
|
||||
# timings in units of RTIO coarse period
|
||||
adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4,
|
||||
# account for SCK DDR to CONV latency
|
||||
@ -505,7 +506,9 @@ class SUServo(_EEM):
|
||||
channels=adc_p.channels, clk=clk)
|
||||
su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p)
|
||||
su = ClockDomainsRenamer("rio_phy")(su)
|
||||
target.submodules += sampler_pads, urukul_pads, su
|
||||
# explicitly name the servo submodule to enable the migen namer to derive
|
||||
# a name for the adc return clock domain
|
||||
setattr(target.submodules, "suservo_eem{}".format(eems_sampler[0]), su)
|
||||
|
||||
ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl]
|
||||
target.submodules += ctrls
|
||||
|
@ -532,6 +532,76 @@ class NUDT(_StandaloneBase):
|
||||
self.add_rtio(self.rtio_channels)
|
||||
|
||||
|
||||
class Berkeley(_StandaloneBase):
|
||||
def __init__(self, hw_rev=None, **kwargs):
|
||||
if hw_rev is None:
|
||||
hw_rev = "v1.1"
|
||||
_StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
||||
|
||||
self.config["SI5324_AS_SYNTHESIZER"] = None
|
||||
# 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, 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)
|
||||
eem.Urukul.add_std(self, 2, 3, ttl_serdes_7series.Output_8X,
|
||||
ttl_simple.ClockGen)
|
||||
eem.Urukul.add_std(self, 4, 5, ttl_serdes_7series.Output_8X,
|
||||
ttl_simple.ClockGen)
|
||||
eem.Urukul.add_std(self, 6, 7, ttl_serdes_7series.Output_8X,
|
||||
ttl_simple.ClockGen)
|
||||
eem.Urukul.add_std(self, 9, 8, ttl_serdes_7series.Output_8X)
|
||||
eem.Zotino.add_std(self, 10, ttl_serdes_7series.Output_8X)
|
||||
|
||||
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 NRC(_StandaloneBase):
|
||||
def __init__(self, hw_rev=None, **kwargs):
|
||||
if hw_rev is None:
|
||||
hw_rev = "v1.1"
|
||||
_StandaloneBase.__init__(self, hw_rev=hw_rev, **kwargs)
|
||||
|
||||
self.config["SI5324_AS_SYNTHESIZER"] = None
|
||||
self.config["RTIO_FREQUENCY"] = "125.0"
|
||||
|
||||
self.rtio_channels = []
|
||||
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)
|
||||
eem.Urukul.add_std(self, 2, 3, ttl_serdes_7series.Output_8X)
|
||||
eem.Urukul.add_std(self, 4, 5, ttl_serdes_7series.Output_8X)
|
||||
eem.Sampler.add_std(self, 6, 7, ttl_serdes_7series.Output_8X)
|
||||
eem.Zotino.add_std(self, 8, ttl_serdes_7series.Output_8X)
|
||||
|
||||
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 PTB(_StandaloneBase):
|
||||
"""PTB Kasli variant
|
||||
|
||||
@ -1125,7 +1195,7 @@ class VLBAISatellite(_SatelliteBase):
|
||||
|
||||
VARIANTS = {cls.__name__.lower(): cls for cls in [
|
||||
Opticlock, SUServo, PTB, PTB2, HUB, LUH,
|
||||
SYSU, MITLL, MITLL2, USTC, Tsinghua, Tsinghua2, WIPM, NUDT,
|
||||
SYSU, MITLL, MITLL2, USTC, Tsinghua, Tsinghua2, WIPM, NUDT, Berkeley, NRC,
|
||||
VLBAIMaster, VLBAISatellite, Tester, Master, Satellite]}
|
||||
|
||||
|
||||
|
@ -321,7 +321,6 @@ class AppletsDock(QtWidgets.QDockWidget):
|
||||
|
||||
self.main_window = main_window
|
||||
self.datasets_sub = datasets_sub
|
||||
self.dock_to_item = dict()
|
||||
self.applet_uids = set()
|
||||
|
||||
self.table = QtWidgets.QTreeWidget()
|
||||
@ -414,12 +413,12 @@ class AppletsDock(QtWidgets.QDockWidget):
|
||||
finally:
|
||||
self.table.itemChanged.connect(self.item_changed)
|
||||
|
||||
def create(self, uid, name, spec):
|
||||
dock = _AppletDock(self.datasets_sub, uid, name, spec)
|
||||
def create(self, item, name, spec):
|
||||
dock = _AppletDock(self.datasets_sub, item.applet_uid, name, spec)
|
||||
self.main_window.addDockWidget(QtCore.Qt.RightDockWidgetArea, dock)
|
||||
dock.setFloating(True)
|
||||
asyncio.ensure_future(dock.start())
|
||||
dock.sigClosed.connect(partial(self.on_dock_closed, dock))
|
||||
dock.sigClosed.connect(partial(self.on_dock_closed, item, dock))
|
||||
return dock
|
||||
|
||||
def item_changed(self, item, column):
|
||||
@ -437,15 +436,15 @@ class AppletsDock(QtWidgets.QDockWidget):
|
||||
if item.applet_dock is None:
|
||||
name = item.text(0)
|
||||
spec = self.get_spec(item)
|
||||
dock = self.create(item.applet_uid, name, spec)
|
||||
dock = self.create(item, name, spec)
|
||||
item.applet_dock = dock
|
||||
if item.applet_geometry is not None:
|
||||
dock.restoreGeometry(item.applet_geometry)
|
||||
# geometry is now handled by main window state
|
||||
item.applet_geometry = None
|
||||
self.dock_to_item[dock] = item
|
||||
else:
|
||||
dock = item.applet_dock
|
||||
item.applet_dock = None
|
||||
if dock is not None:
|
||||
# This calls self.on_dock_closed
|
||||
dock.close()
|
||||
@ -455,12 +454,9 @@ class AppletsDock(QtWidgets.QDockWidget):
|
||||
else:
|
||||
raise ValueError
|
||||
|
||||
def on_dock_closed(self, dock):
|
||||
item = self.dock_to_item[dock]
|
||||
item.applet_dock = None
|
||||
def on_dock_closed(self, item, dock):
|
||||
item.applet_geometry = dock.saveGeometry()
|
||||
asyncio.ensure_future(dock.terminate())
|
||||
del self.dock_to_item[dock]
|
||||
item.setCheckState(0, QtCore.Qt.Unchecked)
|
||||
|
||||
def get_untitled(self):
|
||||
|
@ -118,7 +118,7 @@ def syscall(arg=None, flags={}):
|
||||
def inner_decorator(function):
|
||||
function.artiq_embedded = \
|
||||
_ARTIQEmbeddedInfo(core_name=None, portable=False, function=None,
|
||||
syscall=function.__name__, forbidden=False,
|
||||
syscall=arg, forbidden=False,
|
||||
flags=set(flags))
|
||||
return function
|
||||
return inner_decorator
|
||||
|
@ -214,7 +214,7 @@ class PrepareStage(TaskObject):
|
||||
if run.worker.closed.is_set():
|
||||
break
|
||||
if run.worker.closed.is_set():
|
||||
continue
|
||||
continue
|
||||
run.status = RunStatus.preparing
|
||||
try:
|
||||
await run.build()
|
||||
|
@ -5,7 +5,7 @@ import socket
|
||||
__all__ = []
|
||||
|
||||
|
||||
if sys.version_info[:3] >= (3, 5, 2):
|
||||
if sys.version_info[:3] >= (3, 5, 2) and sys.version_info[:3] <= (3, 6, 6):
|
||||
import asyncio
|
||||
|
||||
# See https://github.com/m-labs/artiq/issues/506
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
This module provide serialization and deserialization functions for Python
|
||||
This module provides serialization and deserialization functions for Python
|
||||
objects. Its main features are:
|
||||
|
||||
* Human-readable format compatible with the Python syntax.
|
||||
@ -193,6 +193,7 @@ _eval_dict = {
|
||||
"null": None,
|
||||
"false": False,
|
||||
"true": True,
|
||||
"inf": numpy.inf,
|
||||
"slice": slice,
|
||||
"nan": numpy.nan,
|
||||
|
||||
|
@ -244,7 +244,7 @@ class Publisher(AsyncioServer):
|
||||
await writer.drain()
|
||||
finally:
|
||||
self._recipients[notifier_name].remove(queue)
|
||||
except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError):
|
||||
except (ConnectionResetError, ConnectionAbortedError, BrokenPipeError, TimeoutError):
|
||||
# subscribers disconnecting are a normal occurrence
|
||||
pass
|
||||
finally:
|
||||
|
@ -180,7 +180,7 @@ class AD9910Test(ExperimentCase):
|
||||
self.execute(AD9910Exp, "set_speed_mu")
|
||||
dt = self.dataset_mgr.get("dt")
|
||||
print(dt)
|
||||
self.assertLess(dt, 10*us)
|
||||
self.assertLess(dt, 11*us)
|
||||
|
||||
def test_sync_window(self):
|
||||
self.execute(AD9910Exp, "sync_window")
|
||||
@ -201,8 +201,8 @@ class AD9910Test(ExperimentCase):
|
||||
n = max(bins2)
|
||||
# no edge at optimal delay
|
||||
self.assertEqual(bins2[(dly + 1) & 3], 0)
|
||||
# edge at expected position
|
||||
self.assertEqual(bins2[(dly + 3) & 3], n)
|
||||
# many edges near expected position
|
||||
self.assertGreater(bins2[(dly + 3) & 3], n*.9)
|
||||
|
||||
def test_sw_readback(self):
|
||||
self.execute(AD9910Exp, "sw_readback")
|
||||
|
@ -61,6 +61,9 @@ class RoundtripTest(ExperimentCase):
|
||||
def test_list_tuple(self):
|
||||
self.assertRoundtrip(([1, 2], [3, 4]))
|
||||
|
||||
def test_list_mixed_tuple(self):
|
||||
self.assertRoundtrip([(0x12345678, [("foo", [0.0, 1.0], [0, 1])])])
|
||||
|
||||
|
||||
class _DefaultArg(EnvExperiment):
|
||||
def build(self):
|
||||
@ -344,7 +347,43 @@ class _ListTuple(EnvExperiment):
|
||||
[numpy.int32(base_b + i) for i in range(n)]
|
||||
|
||||
|
||||
class _NestedTupleList(EnvExperiment):
|
||||
def build(self):
|
||||
self.setattr_device("core")
|
||||
self.data = [(0x12345678, [("foo", [0.0, 1.0], [2, 3])]),
|
||||
(0x76543210, [("bar", [4.0, 5.0], [6, 7])])]
|
||||
|
||||
def get_data(self) -> TList(TTuple(
|
||||
[TInt32, TList(TTuple([TStr, TList(TFloat), TList(TInt32)]))])):
|
||||
return self.data
|
||||
|
||||
@kernel
|
||||
def run(self):
|
||||
a = self.get_data()
|
||||
if a != self.data:
|
||||
raise ValueError
|
||||
|
||||
|
||||
class _EmptyList(EnvExperiment):
|
||||
def build(self):
|
||||
self.setattr_device("core")
|
||||
|
||||
def get_empty(self) -> TList(TInt32):
|
||||
return []
|
||||
|
||||
@kernel
|
||||
def run(self):
|
||||
a = self.get_empty()
|
||||
if a != []:
|
||||
raise ValueError
|
||||
|
||||
|
||||
class ListTupleTest(ExperimentCase):
|
||||
def test_list_tuple(self):
|
||||
exp = self.create(_ListTuple)
|
||||
exp.run()
|
||||
self.create(_ListTuple).run()
|
||||
|
||||
def test_nested_tuple_list(self):
|
||||
self.create(_NestedTupleList).run()
|
||||
|
||||
def test_empty_list(self):
|
||||
self.create(_EmptyList).run()
|
||||
|
@ -248,12 +248,13 @@ class LoopbackGateTiming(EnvExperiment):
|
||||
gate_end_mu = now_mu()
|
||||
|
||||
# gateware latency offset between gate and input
|
||||
lat_offset = 12*8
|
||||
lat_offset = 11*8
|
||||
out_mu = gate_start_mu - loop_delay_mu + lat_offset
|
||||
at_mu(out_mu)
|
||||
self.loop_out.pulse_mu(24)
|
||||
|
||||
in_mu = self.loop_in.timestamp_mu(gate_end_mu)
|
||||
print("timings: ", gate_start_mu, in_mu - lat_offset, gate_end_mu)
|
||||
if in_mu < 0:
|
||||
raise PulseNotReceived()
|
||||
if not (gate_start_mu <= (in_mu - lat_offset) <= gate_end_mu):
|
||||
|
9
artiq/test/lit/embedding/tuple.py
Normal file
9
artiq/test/lit/embedding/tuple.py
Normal file
@ -0,0 +1,9 @@
|
||||
# RUN: %python -m artiq.compiler.testbench.embedding %s
|
||||
|
||||
from artiq.language.core import *
|
||||
|
||||
values = (1, 2)
|
||||
|
||||
@kernel
|
||||
def entrypoint():
|
||||
assert values == (1, 2)
|
@ -9,3 +9,7 @@ def foo():
|
||||
@kernel
|
||||
def entrypoint():
|
||||
foo()
|
||||
|
||||
# Test reassigning strings.
|
||||
a = "a"
|
||||
b = a
|
||||
|
@ -7,3 +7,10 @@ assert (x, y) == (1, 2)
|
||||
|
||||
lst = [1, 2, 3]
|
||||
assert [x*x for x in lst] == [1, 4, 9]
|
||||
|
||||
assert [0] == [0]
|
||||
assert [0] != [1]
|
||||
assert [[0]] == [[0]]
|
||||
assert [[0]] != [[1]]
|
||||
assert [[[0]]] == [[[0]]]
|
||||
assert [[[0]]] != [[[1]]]
|
||||
|
@ -5,3 +5,9 @@ x, y = 2, 1
|
||||
x, y = y, x
|
||||
assert x == 1 and y == 2
|
||||
assert (1, 2) + (3.0,) == (1, 2, 3.0)
|
||||
|
||||
assert (0,) == (0,)
|
||||
assert (0,) != (1,)
|
||||
|
||||
assert ([0],) == ([0],)
|
||||
assert ([0],) != ([1],)
|
||||
|
8
artiq/test/lit/monomorphism/bug_1242.py
Normal file
8
artiq/test/lit/monomorphism/bug_1242.py
Normal file
@ -0,0 +1,8 @@
|
||||
# RUN: %python -m artiq.compiler.testbench.signature %s >%t
|
||||
# RUN: OutputCheck %s --file-to-check=%t
|
||||
|
||||
x = 0x100000000
|
||||
# CHECK-L: x: numpy.int64
|
||||
|
||||
y = int32(x)
|
||||
# CHECK-L: y: numpy.int32
|
@ -40,7 +40,7 @@ requirements:
|
||||
- quamash
|
||||
- pyqtgraph 0.10.0
|
||||
- pygit2
|
||||
- aiohttp
|
||||
- aiohttp >=3
|
||||
- pythonparser >=1.1
|
||||
- levenshtein
|
||||
|
||||
|
@ -42,7 +42,7 @@ requirements:
|
||||
- quamash
|
||||
- pyqtgraph 0.10.0
|
||||
- pygit2
|
||||
- aiohttp
|
||||
- aiohttp >=3
|
||||
- levenshtein
|
||||
|
||||
test:
|
||||
|
@ -84,7 +84,7 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = 'ARTIQ'
|
||||
copyright = '2014-2018, M-Labs Limited'
|
||||
copyright = '2014-2019, M-Labs Limited'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
|
@ -56,7 +56,7 @@ Preparing the build environment for the core device
|
||||
---------------------------------------------------
|
||||
|
||||
These steps are required to generate code that can run on the core
|
||||
device. They are necessary both for building the MiSoC BIOS
|
||||
device. They are necessary both for building the firmware
|
||||
and the ARTIQ kernels.
|
||||
|
||||
* Install required host packages: ::
|
||||
@ -117,6 +117,7 @@ and the ARTIQ kernels.
|
||||
$ sudo mkdir /usr/local/rust-or1k
|
||||
$ sudo chown $USER.$USER /usr/local/rust-or1k
|
||||
$ make install
|
||||
$ cd ..
|
||||
|
||||
$ destdir="/usr/local/rust-or1k/lib/rustlib/or1k-unknown-none/lib/"
|
||||
$ rustc="rustc --out-dir ${destdir} -L ${destdir} --target or1k-unknown-none -g -C target-feature=+mul,+div,+ffl1,+cmov,+addc -C opt-level=s --crate-type rlib"
|
||||
@ -225,6 +226,10 @@ These steps are required to generate gateware bitstream (``.bit``) files, build
|
||||
|
||||
.. _build-target-binaries:
|
||||
|
||||
* For Kasli::
|
||||
|
||||
$ python3 -m artiq.gateware.targets.kasli -V <your_variant>
|
||||
|
||||
* For KC705::
|
||||
|
||||
$ python3 -m artiq.gateware.targets.kc705 -V nist_clock # or nist_qc2
|
||||
@ -233,13 +238,9 @@ These steps are required to generate gateware bitstream (``.bit``) files, build
|
||||
|
||||
.. _flash-target-binaries:
|
||||
|
||||
* Then, gather the binaries and flash them: ::
|
||||
* Then, flash the binaries: ::
|
||||
|
||||
$ mkdir binaries
|
||||
$ cp misoc_nist_qcX_<board>/gateware/top.bit binaries
|
||||
$ cp misoc_nist_qcX_<board>/software/bios/bios.bin binaries
|
||||
$ cp misoc_nist_qcX_<board>/software/runtime/runtime.fbi binaries
|
||||
$ artiq_flash -d binaries
|
||||
$ artiq_flash --srcbuild artiq_kasli -V <your_variant>
|
||||
|
||||
* Check that the board boots by running a serial terminal program (you may need to press its FPGA reconfiguration button or power-cycle it to load the gateware bitstream that was newly written into the flash): ::
|
||||
|
||||
|
@ -74,7 +74,7 @@ As part of the DRTIO link initialization, a real-time packet is sent by the core
|
||||
RTIO outputs
|
||||
++++++++++++
|
||||
|
||||
Controlling a remote RTIO output involves placing the RTIO event into the FIFO of the remote device. The core device maintains a cache of the space available in each channel FIFO of the remote device. If, according to the cache, there is space available, then a packet containing the event information (timestamp, address, channel, data) is sent immediately and the cached value is decremented by one. If, according to the cache, no space is available, then the core device sends a request for the space available in the remote FIFO and updates the cache. The process repeats until at least one FIFO entry is available for the event, at which point a packet containing the event information is sent as before.
|
||||
Controlling a remote RTIO output involves placing the RTIO event into the buffer of the destination. The core device maintains a cache of the buffer space available in each destination. If, according to the cache, there is space available, then a packet containing the event information (timestamp, address, channel, data) is sent immediately and the cached value is decremented by one. If, according to the cache, no space is available, then the core device sends a request for the space available in the destination and updates the cache. The process repeats until at least one remote buffer entry is available for the event, at which point a packet containing the event information is sent as before.
|
||||
|
||||
Detecting underflow conditions is the responsibility of the core device; should an underflow occur then no DRTIO packet is transmitted. Sequence errors are handled similarly.
|
||||
|
||||
|
@ -21,7 +21,7 @@ The conda package contains pre-built binaries that you can directly flash to you
|
||||
Installing Anaconda or Miniconda
|
||||
--------------------------------
|
||||
|
||||
You can either install Anaconda (choose Python 3.5) from https://store.continuum.io/cshop/anaconda/ or install the more minimalistic Miniconda (choose Python 3.5) from http://conda.pydata.org/miniconda.html
|
||||
You can either install Anaconda from https://www.anaconda.com/download/ or install the more minimalistic Miniconda from https://conda.io/miniconda.html
|
||||
|
||||
After installing either Anaconda or Miniconda, open a new terminal (also known as command line, console, or shell and denoted here as lines starting with ``$``) and verify the following command works::
|
||||
|
||||
@ -35,17 +35,17 @@ Installing the ARTIQ packages
|
||||
.. note::
|
||||
On a system with a pre-existing conda installation, it is recommended to update conda to the latest version prior to installing ARTIQ.
|
||||
|
||||
First add the conda-forge repository containing ARTIQ dependencies to your conda configuration::
|
||||
Add the M-Labs ``main`` Anaconda package repository containing stable releases and release candidates::
|
||||
|
||||
$ conda config --prepend channels http://conda.anaconda.org/conda-forge/label/main
|
||||
|
||||
Then add the M-Labs ``main`` Anaconda package repository containing stable releases and release candidates::
|
||||
|
||||
$ conda config --prepend channels http://conda.anaconda.org/m-labs/label/main
|
||||
$ conda config --prepend channels m-labs
|
||||
|
||||
.. note::
|
||||
To use the development versions of ARTIQ, also add the ``dev`` label (http://conda.anaconda.org/m-labs/label/dev).
|
||||
Development versions are built for every change and contain more features, but are not as well-tested and are more likely to contain more bugs or inconsistencies than the releases in the ``main`` label.
|
||||
To use the development versions of ARTIQ, also add the ``dev`` label (m-labs/label/dev).
|
||||
Development versions are built for every change and contain more features, but are not as well-tested and are more likely to contain more bugs or inconsistencies than the releases in the default ``main`` label.
|
||||
|
||||
Add the conda-forge repository containing ARTIQ dependencies to your conda configuration::
|
||||
|
||||
$ conda config --add channels conda-forge
|
||||
|
||||
Then prepare to create a new conda environment with the ARTIQ package and the matching binaries for your hardware:
|
||||
choose a suitable name for the environment, for example ``artiq-main`` if you intend to track the main label, ``artiq-3`` for the 3.x release series, or ``artiq-2016-04-01`` if you consider the environment a snapshot of ARTIQ on 2016-04-01.
|
||||
@ -117,7 +117,7 @@ Configuring OpenOCD
|
||||
|
||||
Some additional steps are necessary to ensure that OpenOCD can communicate with the FPGA board.
|
||||
|
||||
On Linux, first ensure that the current user belongs to the ``plugdev`` group. If it does not, run ``sudo adduser $USER plugdev`` and relogin. If you installed OpenOCD using conda and are using the conda environment ``artiq-main``, then execute the statements below. If you are using a different environment, you will have to replace ``artiq-main`` with the name of your environment::
|
||||
On Linux, first ensure that the current user belongs to the ``plugdev`` group (i.e. `plugdev` shown when you run `$ groups`). If it does not, run ``sudo adduser $USER plugdev`` and relogin. If you installed OpenOCD using conda and are using the conda environment ``artiq-main``, then execute the statements below. If you are using a different environment, you will have to replace ``artiq-main`` with the name of your environment::
|
||||
|
||||
$ sudo cp ~/.conda/envs/artiq-main/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d
|
||||
$ sudo udevadm trigger
|
||||
@ -147,7 +147,7 @@ Then, you can flash the board:
|
||||
|
||||
* For the KC705 board (selecting the appropriate hardware peripheral)::
|
||||
|
||||
$ artiq_flash -t kc705 -m [nist_clock/nist_qc2]
|
||||
$ artiq_flash -t kc705 -V [nist_clock/nist_qc2]
|
||||
|
||||
The SW13 switches also need to be set to 00001.
|
||||
|
||||
@ -162,10 +162,10 @@ This should be done after either installation method (conda or source).
|
||||
|
||||
.. _flash-mac-ip-addr:
|
||||
|
||||
* Set the MAC and IP address in the :ref:`core device configuration flash storage <core-device-flash-storage>` (see above for the ``-t`` and ``-m`` options to ``artiq_flash`` that may be required): ::
|
||||
* Set the MAC and IP address in the :ref:`core device configuration flash storage <core-device-flash-storage>` (see above for the ``-t`` and ``-V`` options to ``artiq_flash`` that may be required): ::
|
||||
|
||||
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
||||
$ artiq_flash -t [board] -m [adapter] -f flash_storage.img storage start
|
||||
$ artiq_flash -t [board] -V [adapter] -f flash_storage.img storage start
|
||||
|
||||
* (optional) Flash the idle kernel
|
||||
|
||||
|
@ -27,4 +27,4 @@ Website: https://m-labs.hk/artiq
|
||||
|
||||
`Cite ARTIQ <http://dx.doi.org/10.5281/zenodo.51303>`_ as ``Bourdeauducq, Sébastien et al. (2016). ARTIQ 1.0. Zenodo. 10.5281/zenodo.51303``.
|
||||
|
||||
Copyright (C) 2014-2018 M-Labs Limited. Licensed under GNU LGPL version 3+.
|
||||
Copyright (C) 2014-2019 M-Labs Limited. Licensed under GNU LGPL version 3+.
|
||||
|
@ -40,7 +40,7 @@ Experiment scheduling
|
||||
Basics
|
||||
------
|
||||
|
||||
To use hardware resources more efficiently, potentially compute-intensive pre-computation and analysis phases of other experiments is executed in parallel with the body of the current experiment that accesses the hardware.
|
||||
To use hardware resources more efficiently, potentially compute-intensive pre-computation and analysis phases of other experiments are executed in parallel with the body of the current experiment that accesses the hardware.
|
||||
|
||||
.. seealso:: These steps are implemented in :class:`~artiq.language.environment.Experiment`. However, user-written experiments should usually derive from (sub-class) :class:`artiq.language.environment.EnvExperiment`.
|
||||
|
||||
@ -83,7 +83,7 @@ Multiple pipelines
|
||||
|
||||
Multiple pipelines can operate in parallel inside the same master. It is the responsibility of the user to ensure that experiments scheduled in one pipeline will never conflict with those of another pipeline over resources (e.g. same devices).
|
||||
|
||||
Pipelines are identified by their name, and are automatically created (when an experiment is scheduled with a pipeline name that does not exist) and destroyed (when it runs empty).
|
||||
Pipelines are identified by their name, and are automatically created (when an experiment is scheduled with a pipeline name that does not exist) and destroyed (when they run empty).
|
||||
|
||||
|
||||
Git integration
|
||||
|
@ -55,21 +55,22 @@ Then later, when the wall clock reaches the respective timestamps the RTIO gatew
|
||||
The following diagram shows what is going on at the different levels of the software and gateware stack (assuming one machine unit of time is 1 ns):
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{
|
||||
signal: [
|
||||
{name: 'kernel', wave: 'x32.3x', data: ['on()', 'delay(2*us)', 'off()'], node: '..A.XB'},
|
||||
{name: 'now', wave: '2...2.', data: ['7000', '9000'], node: '..P..Q'},
|
||||
"signal": [
|
||||
{"name": "kernel", "wave": "x32.3x", "data": ["on()", "delay(2*us)", "off()"], "node": "..A.XB"},
|
||||
{"name": "now", "wave": "2...2.", "data": ["7000", "9000"], "node": "..P..Q"},
|
||||
{},
|
||||
{name: 'slack', wave: 'x2x.2x', data: ['4400', '5800']},
|
||||
{"name": "slack", "wave": "x2x.2x", "data": ["4400", "5800"]},
|
||||
{},
|
||||
{name: 'rtio_counter', wave: 'x2x|2x|2x2x', data: ['2600', '3200', '7000', '9000'], node: ' V.W'},
|
||||
{name: 'ttl', wave: 'x1.0', node: ' R.S', phase: -6.5},
|
||||
{ node: ' T.U', phase: -6.5}
|
||||
],
|
||||
edge: [
|
||||
'A~>R', 'P~>R', 'V~>R', 'B~>S', 'Q~>S', 'W~>S',
|
||||
'R-T', 'S-U', 'T<->U 2µs'
|
||||
{"name": "rtio_counter", "wave": "x2x|2x|2x2x", "data": ["2600", "3200", "7000", "9000"], "node": " V.W"},
|
||||
{"name": "ttl", "wave": "x1.0", "node": " R.S", "phase": -6.5},
|
||||
{ "node": " T.U", "phase": -6.5}
|
||||
],
|
||||
"edge": [
|
||||
"A~>R", "P~>R", "V~>R", "B~>S", "Q~>S", "W~>S",
|
||||
"R-T", "S-U", "T<->U 2µs"
|
||||
]
|
||||
}
|
||||
|
||||
The sequence is exactly equivalent to::
|
||||
@ -95,19 +96,20 @@ The experiment attempts to handle the exception by moving the cursor forward and
|
||||
ttl.on()
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{
|
||||
signal: [
|
||||
{name: 'kernel', wave: 'x34..2.3x', data: ['on()', 'RTIOUnderflow', 'delay()', 'on()'], node: '..AB....C', phase: -3},
|
||||
{name: 'now_mu', wave: '2.....2', data: ['t0', 't1'], node: '.D.....E', phase: -4},
|
||||
"signal": [
|
||||
{"name": "kernel", "wave": "x34..2.3x", "data": ["on()", "RTIOUnderflow", "delay()", "on()"], "node": "..AB....C", "phase": -3},
|
||||
{"name": "now_mu", "wave": "2.....2", "data": ["t0", "t1"], "node": ".D.....E", "phase": -4},
|
||||
{},
|
||||
{name: 'slack', wave: '2x....2', data: ['< 0', '> 0'], node: '.T', phase: -4},
|
||||
{"name": "slack", "wave": "2x....2", "data": ["< 0", "> 0"], "node": ".T", "phase": -4},
|
||||
{},
|
||||
{name: 'rtio_counter', wave: 'x2x.2x....2x2', data: ['t0', '> t0', '< t1', 't1'], node: '............P'},
|
||||
{name: 'tll', wave: 'x...........1', node: '.R..........S', phase: -.5}
|
||||
{"name": "rtio_counter", "wave": "x2x.2x....2x2", "data": ["t0", "> t0", "< t1", "t1"], "node": "............P"},
|
||||
{"name": "tll", "wave": "x...........1", "node": ".R..........S", "phase": -0.5}
|
||||
],
|
||||
edge: [
|
||||
'A-~>R forbidden', 'D-~>R', 'T-~B exception',
|
||||
'C~>S allowed', 'E~>S', 'P~>S'
|
||||
"edge": [
|
||||
"A-~>R forbidden", "D-~>R", "T-~B exception",
|
||||
"C~>S allowed", "E~>S", "P~>S"
|
||||
]
|
||||
}
|
||||
|
||||
@ -170,17 +172,18 @@ In these situations where ``count()`` leads to a synchronization of timeline cur
|
||||
Similar situations arise with methods such as :meth:`artiq.coredevice.ttl.TTLInOut.sample_get` and :meth:`artiq.coredevice.ttl.TTLInOut.watch_done`.
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{
|
||||
signal: [
|
||||
{name: 'kernel', wave: '3..5.|2.3..x..', data: ['gate_rising()', 'count()', 'delay()', 'pulse()'], node: '.A.B..C.ZD.E'},
|
||||
{name: 'now_mu', wave: '2.2..|..2.2.', node: '.P.Q....XV.W'},
|
||||
"signal": [
|
||||
{"name": "kernel", "wave": "3..5.|2.3..x..", "data": ["gate_rising()", "count()", "delay()", "pulse()"], "node": ".A.B..C.ZD.E"},
|
||||
{"name": "now_mu", "wave": "2.2..|..2.2.", "node": ".P.Q....XV.W"},
|
||||
{},
|
||||
{},
|
||||
{name: 'input gate', wave: 'x1.0', node: '.T.U', phase: -2.5},
|
||||
{name: 'output', wave: 'x1.0', node: '.R.S', phase: -10.5}
|
||||
{"name": "input gate", "wave": "x1.0", "node": ".T.U", "phase": -2.5},
|
||||
{"name": "output", "wave": "x1.0", "node": ".R.S", "phase": -10.5}
|
||||
],
|
||||
edge: [
|
||||
'A~>T', 'P~>T', 'B~>U', 'Q~>U', 'U~>C', 'D~>R', 'E~>S', 'V~>R', 'W~>S'
|
||||
"edge": [
|
||||
"A~>T", "P~>T", "B~>U", "Q~>U", "U~>C", "D~>R", "E~>S", "V~>R", "W~>S"
|
||||
]
|
||||
}
|
||||
|
||||
@ -214,20 +217,21 @@ This is demonstrated in the following example where a pulse is split across two
|
||||
Here, ``run()`` calls ``k1()`` which exits leaving the cursor one second after the rising edge and ``k2()`` then submits a falling edge at that position.
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{
|
||||
signal: [
|
||||
{name: 'kernel', wave: '3.2..2..|3.', data: ['k1: on()', 'k1: delay(dt)', 'k1->k2 swap', 'k2: off()'], node: '..A........B'},
|
||||
{name: 'now', wave: '2....2...|.', data: ['t', 't+dt'], node: '..P........Q'},
|
||||
"signal": [
|
||||
{"name": "kernel", "wave": "3.2..2..|3.", "data": ["k1: on()", "k1: delay(dt)", "k1->k2 swap", "k2: off()"], "node": "..A........B"},
|
||||
{"name": "now", "wave": "2....2...|.", "data": ["t", "t+dt"], "node": "..P........Q"},
|
||||
{},
|
||||
{},
|
||||
{name: 'rtio_counter', wave: 'x......|2xx|2', data: ['t', 't+dt'], node: '........V...W'},
|
||||
{name: 'ttl', wave: 'x1...0', node: '.R...S', phase: -7.5},
|
||||
{ node: ' T...U', phase: -7.5}
|
||||
],
|
||||
edge: [
|
||||
'A~>R', 'P~>R', 'V~>R', 'B~>S', 'Q~>S', 'W~>S',
|
||||
'R-T', 'S-U', 'T<->U dt'
|
||||
{"name": "rtio_counter", "wave": "x......|2xx|2", "data": ["t", "t+dt"], "node": "........V...W"},
|
||||
{"name": "ttl", "wave": "x1...0", "node": ".R...S", "phase": -7.5},
|
||||
{ "node": " T...U", "phase": -7.5}
|
||||
],
|
||||
"edge": [
|
||||
"A~>R", "P~>R", "V~>R", "B~>S", "Q~>S", "W~>S",
|
||||
"R-T", "S-U", "T<->U dt"
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@ -239,18 +243,19 @@ If a previous kernel sets timeline cursor far in the future this effectively loc
|
||||
When a kernel should wait until all the events on a particular channel have been executed, use the :meth:`artiq.coredevice.ttl.TTLOut.sync` method of a channel:
|
||||
|
||||
.. wavedrom::
|
||||
|
||||
{
|
||||
signal: [
|
||||
{name: 'kernel', wave: 'x3x.|5.|x', data: ['on()', 'sync()'], node: '..A.....Y'},
|
||||
{name: 'now', wave: '2..', data: ['7000'], node: '..P'},
|
||||
"signal": [
|
||||
{"name": "kernel", "wave": "x3x.|5.|x", "data": ["on()", "sync()"], "node": "..A.....Y"},
|
||||
{"name": "now", "wave": "2..", "data": ["7000"], "node": "..P"},
|
||||
{},
|
||||
{},
|
||||
{name: 'rtio_counter', wave: 'x2x.|..2x', data: ['2000', '7000'], node: ' ....V'},
|
||||
{name: 'ttl', wave: 'x1', node: ' R', phase: -6.5},
|
||||
],
|
||||
edge: [
|
||||
'A~>R', 'P~>R', 'V~>R', 'V~>Y'
|
||||
{"name": "rtio_counter", "wave": "x2x.|..2x", "data": ["2000", "7000"], "node": " ....V"},
|
||||
{"name": "ttl", "wave": "x1", "node": " R", "phase": -6.5}
|
||||
],
|
||||
"edge": [
|
||||
"A~>R", "P~>R", "V~>R", "V~>Y"
|
||||
]
|
||||
}
|
||||
|
||||
RTIO reset
|
||||
|
@ -901,6 +901,12 @@ def get_versions():
|
||||
# py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
|
||||
# case we can only use expanded keywords.
|
||||
|
||||
override = os.getenv("VERSIONEER_OVERRIDE")
|
||||
if override:
|
||||
return {"version": override, "full-revisionid": None,
|
||||
"dirty": None,
|
||||
"error": None, "date": None}
|
||||
|
||||
cfg = get_config()
|
||||
verbose = cfg.verbose
|
||||
|
||||
@ -1404,6 +1410,12 @@ def get_versions(verbose=False):
|
||||
|
||||
Returns dict with two keys: 'version' and 'full'.
|
||||
"""
|
||||
override = os.getenv("VERSIONEER_OVERRIDE")
|
||||
if override:
|
||||
return {"version": override, "full-revisionid": None,
|
||||
"dirty": None,
|
||||
"error": None, "date": None}
|
||||
|
||||
if "versioneer" in sys.modules:
|
||||
# see the discussion in cmdclass.py:get_cmdclass()
|
||||
del sys.modules["versioneer"]
|
||||
|
Loading…
Reference in New Issue
Block a user