Merge branch 'master' into spimaster

* master:
  artiq_flash: use term 'gateware'
  targets/kc705-nist_clock: add clock generator on LA32 for testing purposes
  doc: insist that output() must be called on TTLInOut. Closes #297
  doc: update install instructions
  coredevice: do not give up on UTF-8 errors in log. Closes #300
  use m-labs setup for defaults
  fix indentation
This commit is contained in:
Robert Jördens 2016-02-29 20:47:52 +01:00
commit 7ab7f7d75d
11 changed files with 105 additions and 71 deletions

View File

@ -158,7 +158,7 @@ class CommGeneric:
return self._read_chunk(self._read_int32())
def _read_string(self):
return self._read_bytes()[:-1].decode('utf-8')
return self._read_bytes()[:-1].decode("utf-8")
#
# Writer interface
@ -242,7 +242,7 @@ class CommGeneric:
self._read_header()
self._read_expect(_D2HMsgType.LOG_REPLY)
return self._read_chunk(self._read_length).decode("utf-8")
return self._read_chunk(self._read_length).decode("utf-8", "replace")
def clear_log(self):
self._write_empty(_H2DMsgType.LOG_CLEAR)

View File

@ -91,6 +91,11 @@ class TTLInOut:
This should be used with bidirectional channels.
Note that the channel is in input mode by default. If you need to drive a
signal, you must call ``output``. If the channel is in output mode most of
the time in your setup, it is a good idea to call ``output`` in the
startup kernel.
:param channel: channel number
"""
def __init__(self, dmgr, channel):
@ -107,12 +112,18 @@ class TTLInOut:
@kernel
def output(self):
"""Set the direction to output."""
"""Set the direction to output.
There must be a delay of at least one RTIO clock cycle before any
other command can be issued."""
self.set_oe(True)
@kernel
def input(self):
"""Set the direction to input."""
"""Set the direction to input.
There must be a delay of at least one RTIO clock cycle before any
other command can be issued."""
self.set_oe(False)
@kernel

View File

@ -6,7 +6,6 @@ import os
import subprocess
import tempfile
import artiq
from artiq import __artiq_dir__ as artiq_dir
from artiq.frontend.bit2bin import bit2bin
@ -18,13 +17,13 @@ def get_argparser():
epilog="""\
Valid actions:
* proxy: load the flash proxy bitstream
* bitstream: write bitstream to flash
* proxy: load the flash proxy gateware bitstream
* gateware: write gateware bitstream to flash
* bios: write bios to flash
* runtime: write runtime to flash
* storage: write storage image to flash
* load: load bitstream into device (volatile but fast)
* start: trigger the target to (re)load its bitstream from flash
* load: load gateware bitstream into device (volatile but fast)
* start: trigger the target to (re)load its gateware bitstream from flash
Prerequisites:
@ -37,12 +36,12 @@ Prerequisites:
""")
parser.add_argument("-t", "--target", default="kc705",
help="target board, default: %(default)s")
parser.add_argument("-m", "--adapter", default="qc2",
parser.add_argument("-m", "--adapter", default="clock",
help="target adapter, default: %(default)s")
parser.add_argument("-f", "--storage", help="write file to storage area")
parser.add_argument("-d", "--dir", help="look for files in this directory")
parser.add_argument("ACTION", nargs="*",
default="proxy bitstream bios runtime start".split(),
default="proxy gateware bios runtime start".split(),
help="actions to perform, default: %(default)s")
return parser
@ -55,7 +54,7 @@ def main():
"kc705": {
"chip": "xc7k325t",
"start": "xc7_program xc7.tap",
"bitstream": 0x000000,
"gateware": 0x000000,
"bios": 0xaf0000,
"runtime": 0xb00000,
"storage": 0xb80000,
@ -63,7 +62,7 @@ def main():
"pipistrello": {
"chip": "xc6slx45",
"start": "xc6s_program xc6s.tap",
"bitstream": 0x000000,
"gateware": 0x000000,
"bios": 0x170000,
"runtime": 0x180000,
"storage": 0x200000,
@ -83,23 +82,23 @@ def main():
proxy_base = "bscan_spi_{}.bit".format(config["chip"])
proxy = None
for p in [opts.dir, os.path.expanduser("~/.migen"),
"/usr/local/share/migen", "/usr/share/migen"]:
"/usr/local/share/migen", "/usr/share/migen"]:
proxy_ = os.path.join(p, proxy_base)
if os.access(proxy_, os.R_OK):
proxy = "jtagspi_init 0 {}".format(proxy_)
break
if not proxy:
raise SystemExit(
"proxy bitstream {} not found".format(proxy_base))
"proxy gateware bitstream {} not found".format(proxy_base))
prog.append(proxy)
elif action == "bitstream":
elif action == "gateware":
bin = os.path.join(opts.dir, "top.bin")
if not os.access(bin, os.R_OK):
bin = tempfile.mkstemp()[1]
bit = os.path.join(opts.dir, "top.bit")
conv = True
prog.append("jtagspi_program {} 0x{:x}".format(
bin, config["bitstream"]))
bin, config["gateware"]))
elif action == "bios":
prog.append("jtagspi_program {} 0x{:x}".format(
os.path.join(opts.dir, "bios.bin"), config["bios"]))

View File

@ -48,10 +48,8 @@ fmc_adapter_io = [
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")),
("la32_p", 0, Pins("LPC:LA32_P"), IOStandard("LVTTL")),
("la32_n", 0, Pins("LPC:LA32_N"), IOStandard("LVTTL")),
("spi", 0,
Subsignal("clk", Pins("LPC:LA13_N")),

View File

@ -249,13 +249,12 @@ class NIST_CLOCK(_NIST_Ions):
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)
spi_pins = self.platform.request("ams101_dac", 0)
phy = ttl_simple.Output(spi_pins.ldac)
self.submodules += phy
self.config["RTIO_SPI_LDAC_CHANNEL"] = len(rtio_channels)
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels)
phy = spi.SPIMaster(spi_pins)
self.submodules += phy
@ -263,6 +262,10 @@ class NIST_CLOCK(_NIST_Ions):
rtio_channels.append(rtio.Channel.from_phy(
phy, ofifo_depth=4, ififo_depth=4))
phy = ttl_simple.ClockGen(platform.request("la32_p"))
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
self.config["RTIO_DDS_CHANNEL"] = len(rtio_channels)
self.config["DDS_CHANNEL_COUNT"] = 11
self.config["DDS_AD9914"] = True
@ -341,7 +344,7 @@ def main():
"+ NIST Ions QC1/CLOCK/QC2 hardware adapters")
builder_args(parser)
soc_kc705_args(parser)
parser.add_argument("-H", "--hw-adapter", default="qc1",
parser.add_argument("-H", "--hw-adapter", default="clock",
help="hardware adapter type: qc1/clock/qc2 "
"(default: %(default)s)")
args = parser.parse_args()

View File

@ -198,7 +198,7 @@ class PrepareStage(TaskObject):
await self.pool.state_changed.wait()
elif isinstance(run, float):
await asyncio_wait_or_cancel([self.pool.state_changed.wait()],
timeout=run)
timeout=run)
else:
if run.flush:
run.status = RunStatus.flushing

View File

@ -137,9 +137,9 @@ static void network_init(void)
struct ip4_addr gateway_ip;
init_macadr();
fsip_or_default(&local_ip, "ip", 192, 168, 0, 42);
fsip_or_default(&local_ip, "ip", 192, 168, 1, 50);
fsip_or_default(&netmask, "netmask", 255, 255, 255, 0);
fsip_or_default(&gateway_ip, "gateway", 192, 168, 0, 1);
fsip_or_default(&gateway_ip, "gateway", 192, 168, 1, 1);
lwip_init();

View File

@ -64,6 +64,8 @@ With the CLOCK hardware, the TTL lines are mapped as follows:
+--------------------+-----------------------+--------------+
| 19 | LED | Output |
+--------------------+-----------------------+--------------+
| 20 | LA32_P | Clock |
+--------------------+-----------------------+--------------+
Pipistrello

View File

@ -108,6 +108,10 @@ Create a new file ``rtio.py`` containing the following: ::
delay(2*us)
.. note::
If ``ttl0`` is a bidirectional channel (``TTLInOut``), it is in input (non-driving) mode by default. You need to call ``self.ttl0.output()`` as explained above for the LED.
Connect an oscilloscope or logic analyzer to TTL0 and run ``artiq_run.py led.py``. Notice that the generated signal's period is precisely 4 microseconds, and that it has a duty cycle of precisely 50%. This is not what you would expect if the delay and the pulse were implemented with CPU-controlled GPIO: overhead from the loop management, function calls, etc. would increase the signal's period, and asymmetry in the overhead would cause duty cycle distortion.
Instead, inside the core device, output timing is generated by the gateware and the CPU only programs switching commands with certain timestamps that the CPU computes. This guarantees precise timing as long as the CPU can keep generating timestamps that are increasing fast enough. In case it fails to do that (and attempts to program an event with a timestamp in the past), the :class:`artiq.coredevice.exceptions.RTIOUnderflow` exception is raised. The kernel causing it may catch it (using a regular ``try... except...`` construct), or it will be propagated to the host.

View File

@ -40,13 +40,16 @@ If your ``$PATH`` misses reference the ``miniconda3/bin`` or ``anaconda3/bin`` y
$ export PATH=$HOME/miniconda3/bin:$PATH
Installing the host side software
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Installing the ARTIQ packages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
For this, you need to add our Anaconda repository to your conda configuration::
$ conda config --add channels http://conda.anaconda.org/m-labs/channel/main
$ conda config --add channels http://conda.anaconda.org/m-labs/channel/dev
.. note::
To use the development versions of ARTIQ, also add the ``dev`` channel (http://conda.anaconda.org/m-labs/channel/dev).
Development versions contain more features, but are not as well-tested and are more likely to contain bugs or inconsistencies.
Then you can install the ARTIQ package, it will pull all the necessary dependencies.
@ -60,7 +63,12 @@ Then you can install the ARTIQ package, it will pull all the necessary dependenc
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_qc1; \
echo "Created environment $ENV for ARTIQ"
* For the KC705 board with the FMC backplane and AD9914 DDS chips::
* For the KC705 board with the "clock" FMC backplane and AD9914 DDS chips::
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_clock; \
echo "Created environment $ENV for ARTIQ"
* For the KC705 board with the QC2 FMC backplane and AD9914 DDS chips::
$ ENV=$(date +artiq-%Y-%m-%d); conda create -n $ENV artiq-kc705-nist_qc2; \
echo "Created environment $ENV for ARTIQ"
@ -89,7 +97,9 @@ You now need to flash 3 things on the FPGA board:
2. The BIOS
3. The ARTIQ runtime
First you need to :ref:`install openocd <install-openocd>`. Then, you can flash the board:
They are all shipped in our Conda packages, along with the required flash proxy bitstreams.
First you need to install OpenOCD. Then, you can flash the board:
* For the Pipistrello board::
@ -97,11 +107,9 @@ First you need to :ref:`install openocd <install-openocd>`. Then, you can flash
* For the KC705 board::
$ artiq_flash
$ artiq_flash -m [qc1/clock/qc2]
Next step (for KC705) is to flash MAC and IP addresses to the board:
* See :ref:`those instructions <flash-mac-ip-addr>` to flash MAC and IP addresses.
For the KC705, the next step is to flash the MAC and IP addresses to the board. See :ref:`those instructions <flash-mac-ip-addr>`.
.. _install-from-sources:

View File

@ -1,12 +1,12 @@
# This is an example device database that needs to be adapted to your setup.
# The RTIO channel numbers here are for NIST QC1 on KC705.
# The RTIO channel numbers here are for NIST CLOCK on KC705.
{
"comm": {
"type": "local",
"module": "artiq.coredevice.comm_tcp",
"class": "Comm",
"arguments": {"host": "192.168.0.42"}
"arguments": {"host": "kc705.lab.m-labs.hk"}
},
"core": {
"type": "local",
@ -15,73 +15,77 @@
"arguments": {"ref_period": 1e-9}
},
"pmt0": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLInOut",
"arguments": {"channel": 0}
},
"pmt1": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLInOut",
"arguments": {"channel": 1}
},
"ttl0": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 2},
"arguments": {"channel": 0},
"comment": "This is a fairly long comment to test word wrapping in GUI."
},
"ttl1": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 3},
"arguments": {"channel": 1},
"comment": "Hello World"
},
"ttl2": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 4}
"arguments": {"channel": 2}
},
"ttl3": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 5}
"class": "TTLInOut",
"arguments": {"channel": 3}
},
"ttl4": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 6}
"arguments": {"channel": 4}
},
"ttl5": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 5}
},
"ttl6": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 6}
},
"ttl7": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLInOut",
"arguments": {"channel": 7}
},
"ttl_sma": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLInOut",
"arguments": {"channel": 17}
"arguments": {"channel": 18}
},
"ttl_clock_la32_p": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLClockGen",
"arguments": {"channel": 20}
},
"led": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 18}
},
"ttl15": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLClockGen",
"arguments": {"channel": 19}
},
@ -94,21 +98,21 @@
"dds0": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9858",
"arguments": {"sysclk": 1e9, "channel": 0},
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 0},
"comment": "Comments work in DDS panel as well"
},
"dds1": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9858",
"arguments": {"sysclk": 1e9, "channel": 1}
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 1}
},
"dds2": {
"type": "local",
"module": "artiq.coredevice.dds",
"class": "AD9858",
"arguments": {"sysclk": 1e9, "channel": 2}
"class": "AD9914",
"arguments": {"sysclk": 3e9, "channel": 2}
},
"qc_q1_0": {
@ -160,7 +164,12 @@
"ttl_out": "ttl0",
"ttl_out_serdes": "ttl0",
"pmt": "pmt0",
"loop_out": "ttl0",
"loop_in": "ttl3",
"loop_clock_out": "ttl_clock_la32_p",
"loop_clock_in": "ttl7",
"pmt": "ttl3",
"bd_dds": "dds0",
"bd_sw": "ttl0",
"bdd_dds": "dds1",