Merge remote-tracking branch 'm-labs/master' into ppp2

* m-labs/master:
  test/worker: update
  gui/log: display level and date information in tooltips
  master: add filename in worker log entries. Closes #226
  master: finer control of worker exception reporting. Closes #233
  conda: add artiq-kc705-nist_clock
  gateware: add QC1 docstring
  gateware: add clock target from David
  gateware: clean up and integrate QC2 modifications from Daniel
  add information about CLOCK hardware
This commit is contained in:
Robert Jördens 2016-01-25 12:17:04 -07:00
commit 2832d200f2
13 changed files with 289 additions and 81 deletions

View File

@ -0,0 +1,76 @@
from migen.build.generic_platform import *
fmc_adapter_io = [
("ttl", 0, Pins("LPC:LA00_CC_N"), IOStandard("LVTTL")),
("ttl", 1, Pins("LPC:LA02_P"), IOStandard("LVTTL")),
("ttl", 2, Pins("LPC:LA00_CC_P"), IOStandard("LVTTL")),
("ttl", 3, Pins("LPC:LA02_N"), IOStandard("LVTTL")),
("ttl", 4, Pins("LPC:LA01_CC_N"), IOStandard("LVTTL")),
("ttl", 5, Pins("LPC:LA06_P"), IOStandard("LVTTL")),
("ttl", 6, Pins("LPC:LA06_N"), IOStandard("LVTTL")),
("ttl", 7, Pins("LPC:LA27_P"), IOStandard("LVTTL")),
("ttl", 8, Pins("LPC:LA10_P"), IOStandard("LVTTL")),
("ttl", 9, Pins("LPC:LA05_N"), IOStandard("LVTTL")),
("ttl", 10, Pins("LPC:LA05_P"), IOStandard("LVTTL")),
("ttl", 11, Pins("LPC:LA09_P"), IOStandard("LVTTL")),
("ttl", 12, Pins("LPC:LA09_N"), IOStandard("LVTTL")),
("ttl", 13, Pins("LPC:LA13_P"), IOStandard("LVTTL")),
("ttl", 14, Pins("LPC:LA14_P"), IOStandard("LVTTL")),
("ttl", 15, Pins("LPC:LA10_N"), IOStandard("LVTTL")),
("pmt", 0, Pins("LPC:CLK0_M2C_P"), IOStandard("LVTTL")),
("pmt", 1, Pins("LPC:CLK0_M2C_N"), IOStandard("LVTTL")),
("dds", 0,
Subsignal("a", Pins("LPC:LA22_N LPC:LA21_P LPC:LA22_P LPC:LA19_N "
"LPC:LA20_N LPC:LA19_P LPC:LA20_P")),
Subsignal("d", Pins("LPC:LA15_N LPC:LA16_N LPC:LA15_P LPC:LA16_P "
"LPC:LA11_N LPC:LA12_N LPC:LA11_P LPC:LA12_P "
"LPC:LA07_N LPC:LA08_N LPC:LA07_P LPC:LA08_P "
"LPC:LA04_N LPC:LA03_N LPC:LA04_P LPC:LA03_P")),
Subsignal("sel_n", Pins("LPC:LA24_N LPC:LA29_P LPC:LA28_P LPC:LA29_N "
"LPC:LA28_N LPC:LA31_P LPC:LA30_P LPC:LA31_N "
"LPC:LA30_N LPC:LA33_P LPC:LA33_N")),
Subsignal("fud", Pins("LPC:LA21_N")),
Subsignal("wr_n", Pins("LPC:LA24_P")),
Subsignal("rd_n", Pins("LPC:LA25_N")),
Subsignal("rst", Pins("LPC:LA25_P")),
IOStandard("LVTTL")),
("i2c", 0,
Subsignal("scl", Pins("LPC:IIC_SLC")),
Subsignal("sda", Pins("LPC:IIC_SDA")),
IOStandard("LVCMOS25")),
("clk_m2c", 1,
Subsignal("p", Pins("LPC:CLK1_M2C_P")),
Subsignal("n", Pins("LPC:CLK1_M2C_N")),
IOStandard("LVDS")),
("la32", 0,
Subsignal("p", Pins("LPC:LA32_P")),
Subsignal("n", Pins("LPC:LA32_N")),
IOStandard("LVDS")),
("spi", 0,
Subsignal("clk", Pins("LPC:LA13_N")),
Subsignal("ce", Pins("LPC:LA14_N")),
Subsignal("mosi", Pins("LPC:LA17_CC_P")),
Subsignal("miso", Pins("LPC:LA17_CC_N")),
IOStandard("LVTTL")),
("spi", 1,
Subsignal("clk", Pins("LPC:LA23_N")),
Subsignal("ce", Pins("LPC:LA23_P")),
Subsignal("mosi", Pins("LPC:LA18_CC_N")),
Subsignal("miso", Pins("LPC:LA18_CC_P")),
IOStandard("LVTTL")),
("spi", 2,
Subsignal("clk", Pins("LPC:LA27_P")),
Subsignal("ce", Pins("LPC:LA26_P")),
Subsignal("mosi", Pins("LPC:LA27_N")),
Subsignal("miso", Pins("LPC:LA26_N")),
IOStandard("LVTTL")),
]

View File

@ -18,6 +18,19 @@ fmc_adapter_io = [
("ttl", 13, Pins("LPC:LA09_N"), IOStandard("LVTTL")), ("ttl", 13, Pins("LPC:LA09_N"), IOStandard("LVTTL")),
("ttl", 14, Pins("LPC:LA13_P"), IOStandard("LVTTL")), ("ttl", 14, Pins("LPC:LA13_P"), IOStandard("LVTTL")),
("ttl", 15, Pins("LPC:LA14_P"), IOStandard("LVTTL")), ("ttl", 15, Pins("LPC:LA14_P"), IOStandard("LVTTL")),
("ttl", 16, Pins("LPC:LA13_N"), IOStandard("LVTTL")),
("ttl", 17, Pins("LPC:LA14_N"), IOStandard("LVTTL")),
("ttl", 18, Pins("LPC:LA17_CC_P"), IOStandard("LVTTL")),
("ttl", 19, Pins("LPC:LA17_CC_N"), IOStandard("LVTTL")),
("ttl", 20, Pins("LPC:LA18_CC_P"), IOStandard("LVTTL")),
("ttl", 21, Pins("LPC:LA18_CC_N"), IOStandard("LVTTL")),
("ttl", 22, Pins("LPC:LA23_P"), IOStandard("LVTTL")),
("ttl", 23, Pins("LPC:LA23_N"), IOStandard("LVTTL")),
("ttl", 24, Pins("LPC:LA27_P"), IOStandard("LVTTL")),
("ttl", 25, Pins("LPC:LA26_P"), IOStandard("LVTTL")),
("ttl", 26, Pins("LPC:LA27_N"), IOStandard("LVTTL")),
("ttl", 27, Pins("LPC:LA26_N"), IOStandard("LVTTL")),
("dds", 0, ("dds", 0,
Subsignal("a", Pins("LPC:LA22_N LPC:LA21_P LPC:LA22_P LPC:LA19_N " Subsignal("a", Pins("LPC:LA22_N LPC:LA21_P LPC:LA22_P LPC:LA19_N "
@ -28,7 +41,7 @@ fmc_adapter_io = [
"LPC:LA04_N LPC:LA03_N LPC:LA04_P LPC:LA03_P")), "LPC:LA04_N LPC:LA03_N LPC:LA04_P LPC:LA03_P")),
Subsignal("sel_n", Pins("LPC:LA24_N LPC:LA29_P LPC:LA28_P LPC:LA29_N " Subsignal("sel_n", Pins("LPC:LA24_N LPC:LA29_P LPC:LA28_P LPC:LA29_N "
"LPC:LA28_N LPC:LA31_P LPC:LA30_P LPC:LA31_N " "LPC:LA28_N LPC:LA31_P LPC:LA30_P LPC:LA31_N "
"LPC:LA30_N LPC:LA33_P LPC:LA33_N")), "LPC:LA30_N LPC:LA33_P LPC:LA33_N LPC:LA32_P")),
Subsignal("fud", Pins("LPC:LA21_N")), Subsignal("fud", Pins("LPC:LA21_N")),
Subsignal("wr_n", Pins("LPC:LA24_P")), Subsignal("wr_n", Pins("LPC:LA24_P")),
Subsignal("rd_n", Pins("LPC:LA25_N")), Subsignal("rd_n", Pins("LPC:LA25_N")),
@ -36,7 +49,7 @@ fmc_adapter_io = [
IOStandard("LVTTL")), IOStandard("LVTTL")),
("i2c", 0, ("i2c", 0,
Subsignal("scl", Pins("LPC:IIC_SLC")), Subsignal("scl", Pins("LPC:IIC_SCL")),
Subsignal("sda", Pins("LPC:IIC_SDA")), Subsignal("sda", Pins("LPC:IIC_SDA")),
IOStandard("LVCMOS25")), IOStandard("LVCMOS25")),
@ -50,29 +63,4 @@ fmc_adapter_io = [
Subsignal("n", Pins("LPC:CLK1_M2C_N")), Subsignal("n", Pins("LPC:CLK1_M2C_N")),
IOStandard("LVDS")), IOStandard("LVDS")),
("la32", 0,
Subsignal("p", Pins("LPC:LA32_P")),
Subsignal("n", Pins("LPC:LA32_N")),
IOStandard("LVDS")),
("spi", 0,
Subsignal("clk", Pins("LPC:LA13_N")),
Subsignal("ce", Pins("LPC:LA14_N")),
Subsignal("mosi", Pins("LPC:LA17_CC_P")),
Subsignal("miso", Pins("LPC:LA17_CC_N")),
IOStandard("LVTTL")),
("spi", 1,
Subsignal("clk", Pins("LPC:LA18_CC_P")),
Subsignal("ce", Pins("LPC:LA18_CC_N")),
Subsignal("mosi", Pins("LPC:LA23_P")),
Subsignal("miso", Pins("LPC:LA23_N")),
IOStandard("LVTTL")),
("spi", 2,
Subsignal("clk", Pins("LPC:LA27_P")),
Subsignal("ce", Pins("LPC:LA26_P")),
Subsignal("mosi", Pins("LPC:LA27_N")),
Subsignal("miso", Pins("LPC:LA26_N")),
IOStandard("LVTTL")),
] ]

View File

@ -18,7 +18,7 @@ from misoc.integration.builder import *
from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict
from artiq.gateware.soc import AMPSoC from artiq.gateware.soc import AMPSoC
from artiq.gateware import rtio, nist_qc1, nist_qc2 from artiq.gateware import rtio, nist_qc1, nist_clock, nist_qc2
from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds
from artiq.tools import artiq_dir from artiq.tools import artiq_dir
from artiq import __version__ as artiq_version from artiq import __version__ as artiq_version
@ -94,7 +94,7 @@ class _RTIOCRG(Module, AutoCSR):
] ]
class _NIST_QCx(MiniSoC, AMPSoC): class _NIST_Ions(MiniSoC, AMPSoC):
csr_map = { csr_map = {
"rtio": None, # mapped on Wishbone instead "rtio": None, # mapped on Wishbone instead
"rtio_crg": 13, "rtio_crg": 13,
@ -161,9 +161,13 @@ TIMESPEC "TSfix_cdc2" = FROM "GRPrio_clk" TO "GRPrsys_clk" TIG;
self.get_native_sdram_if()) self.get_native_sdram_if())
class NIST_QC1(_NIST_QCx): class NIST_QC1(_NIST_Ions):
"""
NIST QC1 hardware, as used in the Penning lab, with FMC to SCSI cables
adapter.
"""
def __init__(self, cpu_type="or1k", **kwargs): def __init__(self, cpu_type="or1k", **kwargs):
_NIST_QCx.__init__(self, cpu_type, **kwargs) _NIST_Ions.__init__(self, cpu_type, **kwargs)
platform = self.platform platform = self.platform
platform.add_extension(nist_qc1.fmc_adapter_io) platform.add_extension(nist_qc1.fmc_adapter_io)
@ -212,18 +216,18 @@ class NIST_QC1(_NIST_QCx):
self.config["DDS_RTIO_CLK_RATIO"] = 8 >> self.rtio.fine_ts_width self.config["DDS_RTIO_CLK_RATIO"] = 8 >> self.rtio.fine_ts_width
class NIST_QC2(_NIST_QCx): class NIST_CLOCK(_NIST_Ions):
"""
NIST clock hardware, with old backplane and 11 DDS channels
"""
def __init__(self, cpu_type="or1k", **kwargs): def __init__(self, cpu_type="or1k", **kwargs):
_NIST_QCx.__init__(self, cpu_type, **kwargs) _NIST_Ions.__init__(self, cpu_type, **kwargs)
platform = self.platform platform = self.platform
platform.add_extension(nist_qc2.fmc_adapter_io) platform.add_extension(nist_clock.fmc_adapter_io)
rtio_channels = [] rtio_channels = []
for i in range(16): for i in range(16):
if i == 14:
# TTL14 is for the clock generator
continue
if i % 4 == 3: if i % 4 == 3:
phy = ttl_serdes_7series.Inout_8X(platform.request("ttl", i)) phy = ttl_serdes_7series.Inout_8X(platform.request("ttl", i))
self.submodules += phy self.submodules += phy
@ -233,18 +237,20 @@ class NIST_QC2(_NIST_QCx):
self.submodules += phy self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy)) rtio_channels.append(rtio.Channel.from_phy(phy))
for i in range(2):
phy = ttl_serdes_7series.Inout_8X(platform.request("pmt", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512))
phy = ttl_simple.Inout(platform.request("user_sma_gpio_n")) phy = ttl_simple.Inout(platform.request("user_sma_gpio_n"))
self.submodules += phy self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy)) rtio_channels.append(rtio.Channel.from_phy(phy))
phy = ttl_simple.Output(platform.request("user_led", 2)) phy = ttl_simple.Output(platform.request("user_led", 2))
self.submodules += phy self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy)) rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels) self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
phy = ttl_simple.ClockGen(platform.request("ttl", 14))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels) self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 11 self.config["DDS_CHANNEL_COUNT"] = 11
self.config["DDS_AD9914"] = True self.config["DDS_AD9914"] = True
@ -263,25 +269,81 @@ class NIST_QC2(_NIST_QCx):
self.config["DDS_RTIO_CLK_RATIO"] = 24 >> self.rtio.fine_ts_width self.config["DDS_RTIO_CLK_RATIO"] = 24 >> self.rtio.fine_ts_width
class NIST_QC2(_NIST_Ions):
"""
NIST QC2 hardware, as used in Quantum I and Quantum II, with new backplane
and 12 DDS channels. Current implementation for single backplane.
"""
def __init__(self, cpu_type="or1k", **kwargs):
_NIST_Ions.__init__(self, cpu_type, **kwargs)
platform = self.platform
platform.add_extension(nist_qc2.fmc_adapter_io)
rtio_channels = []
# TTL0-23 are In+Out capable
for i in range(24):
phy = ttl_serdes_7series.Inout_8X(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=512))
# TTL24-26 are output only
for i in range(24, 27):
phy = ttl_serdes_7series.Output_8X(platform.request("ttl", i))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
phy = ttl_simple.Inout(platform.request("user_sma_gpio_n"))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
phy = ttl_simple.Output(platform.request("user_led", 2))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
# TTL27 is for the clock generator
phy = ttl_simple.ClockGen(platform.request("ttl", 27))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 12
self.config["DDS_AD9914"] = True
self.config["DDS_ONEHOT_SEL"] = True
phy = dds.AD9914(platform.request("dds"), 12, onehot=True)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy,
ofifo_depth=512,
ififo_depth=4))
self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels)
rtio_channels.append(rtio.LogChannel())
self.add_rtio(rtio_channels)
assert self.rtio.fine_ts_width <= 3
self.config["DDS_RTIO_CLK_RATIO"] = 24 >> self.rtio.fine_ts_width
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="ARTIQ core device builder / KC705 " description="ARTIQ core device builder / KC705 "
"+ NIST Ions QC1/QC2 hardware adapters") "+ NIST Ions QC1/CLOCK/QC2 hardware adapters")
builder_args(parser) builder_args(parser)
soc_kc705_args(parser) soc_kc705_args(parser)
parser.add_argument("-H", "--hw-adapter", default="qc1", parser.add_argument("-H", "--hw-adapter", default="qc1",
help="hardware adapter type: qc1/qc2 " help="hardware adapter type: qc1/clock/qc2 "
"(default: %(default)s)") "(default: %(default)s)")
args = parser.parse_args() args = parser.parse_args()
hw_adapter = args.hw_adapter.lower() hw_adapter = args.hw_adapter.lower()
if hw_adapter == "qc1": if hw_adapter == "qc1":
cls = NIST_QC1 cls = NIST_QC1
elif hw_adapter == "clock":
cls = NIST_CLOCK
elif hw_adapter == "qc2": elif hw_adapter == "qc2":
cls = NIST_QC2 cls = NIST_QC2
else: else:
print("Invalid hardware adapter string (-H/--hw-adapter), " print("Invalid hardware adapter string (-H/--hw-adapter), "
"choose from qc1 or qc2") "choose from qc1, clock or qc2")
sys.exit(1) sys.exit(1)
soc = cls(**soc_kc705_argdict(args)) soc = cls(**soc_kc705_argdict(args))

View File

@ -25,7 +25,7 @@ class Model(QtCore.QAbstractTableModel):
def __init__(self, init): def __init__(self, init):
QtCore.QAbstractTableModel.__init__(self) QtCore.QAbstractTableModel.__init__(self)
self.headers = ["Level", "Source", "Time", "Message"] self.headers = ["Source", "Message"]
self.entries = list(map(_make_wrappable, init)) self.entries = list(map(_make_wrappable, init))
self.pending_entries = [] self.pending_entries = []
@ -85,7 +85,7 @@ class Model(QtCore.QAbstractTableModel):
def data(self, index, role): def data(self, index, role):
if index.isValid(): if index.isValid():
if (role == QtCore.Qt.FontRole if (role == QtCore.Qt.FontRole
and index.column() == 3): and index.column() == 1):
return self.fixed_font return self.fixed_font
elif role == QtCore.Qt.BackgroundRole: elif role == QtCore.Qt.BackgroundRole:
level = self.entries[index.row()][0] level = self.entries[index.row()][0]
@ -105,13 +105,13 @@ class Model(QtCore.QAbstractTableModel):
v = self.entries[index.row()] v = self.entries[index.row()]
column = index.column() column = index.column()
if column == 0: if column == 0:
return log_level_to_name(v[0])
elif column == 1:
return v[1] return v[1]
elif column == 2:
return time.strftime("%m/%d %H:%M:%S", time.localtime(v[2]))
else: else:
return v[3] return v[3]
elif role == QtCore.Qt.ToolTipRole:
v = self.entries[index.row()]
return (log_level_to_name(v[0]) + ", " +
time.strftime("%m/%d %H:%M:%S", time.localtime(v[2])))
class _LogFilterProxyModel(QSortFilterProxyModel): class _LogFilterProxyModel(QSortFilterProxyModel):
@ -123,15 +123,11 @@ class _LogFilterProxyModel(QSortFilterProxyModel):
def filterAcceptsRow(self, sourceRow, sourceParent): def filterAcceptsRow(self, sourceRow, sourceParent):
model = self.sourceModel() model = self.sourceModel()
index = model.index(sourceRow, 0, sourceParent) accepted_level = model.entries[sourceRow][0] >= self.min_level
data = model.data(index, QtCore.Qt.DisplayRole)
accepted_level = getattr(logging, data) >= self.min_level
if self.freetext: if self.freetext:
index = model.index(sourceRow, 1, sourceParent) data_source = model.entries[sourceRow][1]
data_source = model.data(index, QtCore.Qt.DisplayRole) data_message = model.entries[sourceRow][3]
index = model.index(sourceRow, 3, sourceParent)
data_message = model.data(index, QtCore.Qt.DisplayRole)
accepted_freetext = (self.freetext in data_source accepted_freetext = (self.freetext in data_source
or self.freetext in data_message) or self.freetext in data_message)
else: else:

View File

@ -6,7 +6,8 @@ import logging
from functools import partial from functools import partial
from artiq.protocols.sync_struct import Notifier from artiq.protocols.sync_struct import Notifier
from artiq.master.worker import Worker from artiq.master.worker import (Worker, WorkerInternalException,
log_worker_exception)
from artiq.tools import get_windows_drives, exc_to_warning from artiq.tools import get_windows_drives, exc_to_warning
@ -17,10 +18,13 @@ async def _get_repository_entries(entry_dict,
root, filename, get_device_db, log): root, filename, get_device_db, log):
worker = Worker({ worker = Worker({
"get_device_db": get_device_db, "get_device_db": get_device_db,
"log": partial(log, "scan") "log": partial(log, "scan", os.path.basename(filename))
}) })
try: try:
description = await worker.examine(os.path.join(root, filename)) description = await worker.examine(os.path.join(root, filename))
except:
log_worker_exception()
raise
finally: finally:
await worker.close() await worker.close()
for class_name, class_desc in description.items(): for class_name, class_desc in description.items():
@ -55,8 +59,9 @@ async def _scan_experiments(root, get_device_db, log, subdir=""):
try: try:
await _get_repository_entries( await _get_repository_entries(
entry_dict, root, filename, get_device_db, log) entry_dict, root, filename, get_device_db, log)
except: except Exception as exc:
logger.warning("Skipping file '%s'", filename, exc_info=True) logger.warning("Skipping file '%s'", filename,
exc_info=not isinstance(exc, WorkerInternalException))
if de.is_dir(): if de.is_dir():
subentries = await _scan_experiments( subentries = await _scan_experiments(
root, get_device_db, log, root, get_device_db, log,
@ -119,7 +124,7 @@ class ExperimentDB:
filename = os.path.join(wd, filename) filename = os.path.join(wd, filename)
worker = Worker({ worker = Worker({
"get_device_db": self.get_device_db_fn, "get_device_db": self.get_device_db_fn,
"log": partial(self.log_fn, "examine") "log": partial(self.log_fn, "examine", os.path.basename(filename))
}) })
try: try:
description = await worker.examine(filename) description = await worker.examine(filename)

View File

@ -29,11 +29,11 @@ class LogBufferHandler(logging.Handler):
part) part)
def log_worker(rid, message): def log_worker(rid, filename, message):
level, name, message = parse_log_message(message) level, name, message = parse_log_message(message)
log_with_name(name, level, message, log_with_name(name, level, message,
extra={"source": "worker({})".format(rid)}) extra={"source": "worker({},{})".format(rid, filename)})
log_worker.worker_pass_rid = True log_worker.worker_pass_runinfo = True
def log_args(parser): def log_args(parser):

View File

@ -3,7 +3,7 @@ import logging
from enum import Enum from enum import Enum
from time import time from time import time
from artiq.master.worker import Worker from artiq.master.worker import Worker, log_worker_exception
from artiq.tools import asyncio_wait_or_cancel, TaskObject, Condition from artiq.tools import asyncio_wait_or_cancel, TaskObject, Condition
from artiq.protocols.sync_struct import Notifier from artiq.protocols.sync_struct import Notifier
@ -231,7 +231,7 @@ class PrepareStage(TaskObject):
except: except:
logger.error("got worker exception in prepare stage, " logger.error("got worker exception in prepare stage, "
"deleting RID %d", run.rid) "deleting RID %d", run.rid)
logger.error("worker exception details", exc_info=True) log_worker_exception()
self.delete_cb(run.rid) self.delete_cb(run.rid)
else: else:
run.status = RunStatus.prepare_done run.status = RunStatus.prepare_done
@ -281,7 +281,7 @@ class RunStage(TaskObject):
except: except:
logger.error("got worker exception in run stage, " logger.error("got worker exception in run stage, "
"deleting RID %d", run.rid) "deleting RID %d", run.rid)
logger.error("worker exception details", exc_info=True) log_worker_exception()
self.delete_cb(run.rid) self.delete_cb(run.rid)
else: else:
if completed: if completed:
@ -319,7 +319,7 @@ class AnalyzeStage(TaskObject):
except: except:
logger.error("got worker exception in analyze stage, " logger.error("got worker exception in analyze stage, "
"deleting RID %d", run.rid) "deleting RID %d", run.rid)
logger.error("worker exception details", exc_info=True) log_worker_exception()
self.delete_cb(run.rid) self.delete_cb(run.rid)
else: else:
self.delete_cb(run.rid) self.delete_cb(run.rid)

View File

@ -1,4 +1,5 @@
import sys import sys
import os
import asyncio import asyncio
import logging import logging
import subprocess import subprocess
@ -25,12 +26,27 @@ class WorkerError(Exception):
pass pass
class WorkerInternalException(Exception):
"""Exception raised inside the worker, information has been printed
through logging."""
pass
def log_worker_exception():
exc, _, _ = sys.exc_info()
if exc is WorkerInternalException:
logger.debug("worker exception details", exc_info=True)
else:
logger.error("worker exception details", exc_info=True)
class Worker: class Worker:
def __init__(self, handlers=dict(), send_timeout=0.5): def __init__(self, handlers=dict(), send_timeout=0.5):
self.handlers = handlers self.handlers = handlers
self.send_timeout = send_timeout self.send_timeout = send_timeout
self.rid = None self.rid = None
self.filename = None
self.process = None self.process = None
self.watchdogs = dict() # wid -> expiration (using time.monotonic) self.watchdogs = dict() # wid -> expiration (using time.monotonic)
@ -167,6 +183,8 @@ class Worker:
return True return True
elif action == "pause": elif action == "pause":
return False return False
elif action == "exception":
raise WorkerInternalException
elif action == "create_watchdog": elif action == "create_watchdog":
func = self.create_watchdog func = self.create_watchdog
elif action == "delete_watchdog": elif action == "delete_watchdog":
@ -175,8 +193,8 @@ class Worker:
func = self.register_experiment func = self.register_experiment
else: else:
func = self.handlers[action] func = self.handlers[action]
if getattr(func, "worker_pass_rid", False): if getattr(func, "worker_pass_runinfo", False):
func = partial(func, self.rid) func = partial(func, self.rid, self.filename)
try: try:
data = func(*obj["args"], **obj["kwargs"]) data = func(*obj["args"], **obj["kwargs"])
reply = {"status": "ok", "data": data} reply = {"status": "ok", "data": data}
@ -211,6 +229,7 @@ class Worker:
async def build(self, rid, pipeline_name, wd, expid, priority, timeout=15.0): async def build(self, rid, pipeline_name, wd, expid, priority, timeout=15.0):
self.rid = rid self.rid = rid
self.filename = os.path.basename(expid["file"])
await self._create_process(expid["log_level"]) await self._create_process(expid["log_level"])
await self._worker_action( await self._worker_action(
{"action": "build", {"action": "build",

View File

@ -264,15 +264,17 @@ def main():
put_object({"action": "completed"}) put_object({"action": "completed"})
elif action == "terminate": elif action == "terminate":
break break
except CompileError:
pass
except Exception as exc: except Exception as exc:
# When we get CompileError, a more suitable diagnostic has already
# been printed.
if not isinstance(exc, CompileError):
lines = ["Terminating with exception\n"] lines = ["Terminating with exception\n"]
lines += traceback.format_exception_only(type(exc), exc) lines += traceback.format_exception_only(type(exc), exc)
if hasattr(exc, "parent_traceback"): if hasattr(exc, "parent_traceback"):
lines += exc.parent_traceback lines += exc.parent_traceback
logging.error("".join(lines).rstrip(), logging.error("".join(lines).rstrip(),
exc_info=not hasattr(exc, "parent_traceback")) exc_info=not hasattr(exc, "parent_traceback"))
put_object({"action": "exception"})
finally: finally:
device_mgr.close_devices() device_mgr.close_devices()

View File

@ -87,7 +87,7 @@ class WorkerCase(unittest.TestCase):
_run_experiment("SimpleExperiment") _run_experiment("SimpleExperiment")
def test_exception(self): def test_exception(self):
with self.assertRaises(WorkerError): with self.assertRaises(WorkerInternalException):
_run_experiment("ExceptionTermination") _run_experiment("ExceptionTermination")
def test_watchdog_no_timeout(self): def test_watchdog_no_timeout(self):

View File

@ -0,0 +1,14 @@
#!/bin/bash
BUILD_SETTINGS_FILE=$HOME/.m-labs/build_settings.sh
[ -f $BUILD_SETTINGS_FILE ] && . $BUILD_SETTINGS_FILE
SOC_PREFIX=$PREFIX/lib/python3.5/site-packages/artiq/binaries/kc705-clock
mkdir -p $SOC_PREFIX
$PYTHON -m artiq.gateware.targets.kc705 -H clock --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE
cp misoc_nist_clock_kc705/gateware/top.bit $SOC_PREFIX
cp misoc_nist_clock_kc705/software/bios/bios.bin $SOC_PREFIX
cp misoc_nist_clock_kc705/software/runtime/runtime.fbi $SOC_PREFIX
wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/master/bscan_spi_xc7k325t.bit

View File

@ -0,0 +1,27 @@
package:
name: artiq-kc705-nist_clock
version: {{ environ.get("GIT_DESCRIBE_TAG", "") }}
source:
path: ../..
build:
noarch_python: true
number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}
string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_DESCRIBE_HASH", "")[1:] }}
requirements:
build:
# We don't get meaningful GIT_DESCRIBE_* values until before conda installs build dependencies.
- artiq 0.0
- migen 0.2
- misoc 0.1
- llvm-or1k
- binutils-or1k-linux
run:
- artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }}
about:
home: http://m-labs.hk/artiq
license: GPL
summary: 'Bitstream, BIOS and runtime for NIST_QC2 on the KC705 board'

View File

@ -27,7 +27,7 @@ FPGA board ports
KC705 KC705
----- -----
The main target board for the ARTIQ core device is the KC705 development board from Xilinx. It supports the NIST QC1 hardware via an adapter, and the NIST QC2 hardware (FMC). The main target board for the ARTIQ core device is the KC705 development board from Xilinx. It supports the NIST QC1 hardware via an adapter, and the NIST CLOCK and QC2 hardware (FMC).
With the QC1 hardware, the TTL lines are mapped as follows: With the QC1 hardware, the TTL lines are mapped as follows:
@ -47,6 +47,25 @@ With the QC1 hardware, the TTL lines are mapped as follows:
| 19 | TTL15 | Clock | | 19 | TTL15 | Clock |
+--------------+------------+--------------+ +--------------+------------+--------------+
With the CLOCK hardware, the TTL lines are mapped as follows:
+--------------------+-----------------------+--------------+
| RTIO channel | TTL line | Capability |
+====================+=======================+==============+
| 3,7,11,15 | TTL3,7,11,15 | Input+Output |
+--------------------+-----------------------+--------------+
| 0-2,4-6,8-10,12-14 | TTL0-2,4-6,8-10,12-14 | Output |
+--------------------+-----------------------+--------------+
| 16 | PMT0 | Input |
+--------------------+-----------------------+--------------+
| 17 | PMT1 | Input |
+--------------------+-----------------------+--------------+
| 18 | SMA_GPIO_N | Input+Output |
+--------------------+-----------------------+--------------+
| 19 | LED | Output |
+--------------------+-----------------------+--------------+
Pipistrello Pipistrello
----------- -----------