mirror of https://github.com/m-labs/artiq.git
Merge branch 'master' of github.com:m-labs/artiq
This commit is contained in:
commit
59b339462c
|
@ -43,9 +43,8 @@ class _D2HMsgType(Enum):
|
||||||
RPC_REQUEST = 10
|
RPC_REQUEST = 10
|
||||||
|
|
||||||
FLASH_READ_REPLY = 11
|
FLASH_READ_REPLY = 11
|
||||||
FLASH_WRITE_REPLY = 12
|
FLASH_OK_REPLY = 12
|
||||||
FLASH_OK_REPLY = 13
|
FLASH_ERROR_REPLY = 13
|
||||||
FLASH_ERROR_REPLY = 14
|
|
||||||
|
|
||||||
|
|
||||||
class UnsupportedDevice(Exception):
|
class UnsupportedDevice(Exception):
|
||||||
|
@ -148,14 +147,11 @@ class CommGeneric:
|
||||||
self.write(b"\x00")
|
self.write(b"\x00")
|
||||||
self.write(value)
|
self.write(value)
|
||||||
_, ty = self._read_header()
|
_, ty = self._read_header()
|
||||||
if ty != _D2HMsgType.FLASH_WRITE_REPLY:
|
if ty != _D2HMsgType.FLASH_OK_REPLY:
|
||||||
if ty == _D2HMsgType.FLASH_ERROR_REPLY:
|
if ty == _D2HMsgType.FLASH_ERROR_REPLY:
|
||||||
raise IOError("Invalid key: not a null-terminated string")
|
raise IOError("Flash storage is full")
|
||||||
else:
|
else:
|
||||||
raise IOError("Incorrect reply from device: {}".format(ty))
|
raise IOError("Incorrect reply from device: {}".format(ty))
|
||||||
ret = self.read(1)
|
|
||||||
if ret != b"\x01":
|
|
||||||
raise IOError("Flash storage is full")
|
|
||||||
|
|
||||||
def flash_storage_erase(self):
|
def flash_storage_erase(self):
|
||||||
self._write_header(9, _H2DMsgType.FLASH_ERASE_REQUEST)
|
self._write_header(9, _H2DMsgType.FLASH_ERASE_REQUEST)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
import asyncio
|
import asyncio
|
||||||
import sys
|
import sys
|
||||||
from time import sleep
|
from time import time, sleep
|
||||||
|
|
||||||
from artiq import *
|
from artiq import *
|
||||||
from artiq.master.scheduler import Scheduler
|
from artiq.master.scheduler import Scheduler
|
||||||
|
@ -27,11 +27,11 @@ def _get_expid(name):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def _get_basic_steps(rid, expid):
|
def _get_basic_steps(rid, expid, priority=0, flush=False):
|
||||||
return [
|
return [
|
||||||
{"action": "setitem", "key": rid, "value":
|
{"action": "setitem", "key": rid, "value":
|
||||||
{"pipeline": "main", "status": "pending", "priority": 0,
|
{"pipeline": "main", "status": "pending", "priority": priority,
|
||||||
"expid": expid, "due_date": None, "flush": False},
|
"expid": expid, "due_date": None, "flush": flush},
|
||||||
"path": []},
|
"path": []},
|
||||||
{"action": "setitem", "key": "status", "value": "preparing",
|
{"action": "setitem", "key": "status", "value": "preparing",
|
||||||
"path": [rid]},
|
"path": [rid]},
|
||||||
|
@ -59,7 +59,7 @@ class SchedulerCase(unittest.TestCase):
|
||||||
scheduler = Scheduler(0, _handlers)
|
scheduler = Scheduler(0, _handlers)
|
||||||
expid = _get_expid("EmptyExperiment")
|
expid = _get_expid("EmptyExperiment")
|
||||||
|
|
||||||
expect = _get_basic_steps(0, expid)
|
expect = _get_basic_steps(1, expid)
|
||||||
done = asyncio.Event()
|
done = asyncio.Event()
|
||||||
expect_idx = 0
|
expect_idx = 0
|
||||||
def notify(notifier, mod):
|
def notify(notifier, mod):
|
||||||
|
@ -72,8 +72,22 @@ class SchedulerCase(unittest.TestCase):
|
||||||
|
|
||||||
loop = asyncio.get_event_loop()
|
loop = asyncio.get_event_loop()
|
||||||
scheduler.start()
|
scheduler.start()
|
||||||
|
|
||||||
|
# Verify that a timed experiment far in the future does not
|
||||||
|
# get run, even if it has high priority.
|
||||||
|
late = time() + 100000
|
||||||
|
expect.insert(0,
|
||||||
|
{"action": "setitem", "key": 0, "value":
|
||||||
|
{"pipeline": "main", "status": "pending", "priority": 99,
|
||||||
|
"expid": expid, "due_date": late, "flush": False},
|
||||||
|
"path": []})
|
||||||
|
scheduler.submit("main", expid, 99, late, False)
|
||||||
|
|
||||||
|
# This one (RID 1) gets run instead.
|
||||||
scheduler.submit("main", expid, 0, None, False)
|
scheduler.submit("main", expid, 0, None, False)
|
||||||
|
|
||||||
loop.run_until_complete(done.wait())
|
loop.run_until_complete(done.wait())
|
||||||
|
scheduler.notifier.publish = None
|
||||||
loop.run_until_complete(scheduler.stop())
|
loop.run_until_complete(scheduler.stop())
|
||||||
|
|
||||||
def test_pause(self):
|
def test_pause(self):
|
||||||
|
@ -106,3 +120,37 @@ class SchedulerCase(unittest.TestCase):
|
||||||
scheduler.submit("main", expid, 0, None, False)
|
scheduler.submit("main", expid, 0, None, False)
|
||||||
loop.run_until_complete(done.wait())
|
loop.run_until_complete(done.wait())
|
||||||
loop.run_until_complete(scheduler.stop())
|
loop.run_until_complete(scheduler.stop())
|
||||||
|
|
||||||
|
def test_flush(self):
|
||||||
|
scheduler = Scheduler(0, _handlers)
|
||||||
|
expid = _get_expid("EmptyExperiment")
|
||||||
|
|
||||||
|
expect = _get_basic_steps(1, expid, 1, True)
|
||||||
|
expect.insert(1, {"key": "status",
|
||||||
|
"path": [1],
|
||||||
|
"value": "flushing",
|
||||||
|
"action": "setitem"})
|
||||||
|
first_preparing = asyncio.Event()
|
||||||
|
done = asyncio.Event()
|
||||||
|
expect_idx = 0
|
||||||
|
def notify(notifier, mod):
|
||||||
|
nonlocal expect_idx
|
||||||
|
if mod == {"path": [0],
|
||||||
|
"value": "preparing",
|
||||||
|
"key": "status",
|
||||||
|
"action": "setitem"}:
|
||||||
|
first_preparing.set()
|
||||||
|
if mod["path"] == [1] or (mod["path"] == [] and mod["key"] == 1):
|
||||||
|
self.assertEqual(mod, expect[expect_idx])
|
||||||
|
expect_idx += 1
|
||||||
|
if expect_idx >= len(expect):
|
||||||
|
done.set()
|
||||||
|
scheduler.notifier.publish = notify
|
||||||
|
|
||||||
|
loop = asyncio.get_event_loop()
|
||||||
|
scheduler.start()
|
||||||
|
scheduler.submit("main", expid, 0, None, False)
|
||||||
|
loop.run_until_complete(first_preparing.wait())
|
||||||
|
scheduler.submit("main", expid, 1, None, True)
|
||||||
|
loop.run_until_complete(done.wait())
|
||||||
|
loop.run_until_complete(scheduler.stop())
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
Getting started
|
Getting started
|
||||||
===============
|
===============
|
||||||
|
|
||||||
|
.. _connecting-to-the-core-device:
|
||||||
|
|
||||||
Connecting to the core device
|
Connecting to the core device
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|
|
@ -128,7 +128,7 @@ The communication parameters are 115200 8-N-1.
|
||||||
|
|
||||||
* You can either set it by generating a flash storage image and then flash it: ::
|
* You can either set it by generating a flash storage image and then flash it: ::
|
||||||
|
|
||||||
$ ~/artiq-dev/artiq/frontend/artiq_mkfs.py flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
$ artiq_mkfs flash_storage.img -s mac xx:xx:xx:xx:xx:xx -s ip xx.xx.xx.xx
|
||||||
$ ~/artiq-dev/artiq/frontend/artiq_flash.sh -f flash_storage.img
|
$ ~/artiq-dev/artiq/frontend/artiq_flash.sh -f flash_storage.img
|
||||||
|
|
||||||
* Or you can set it via the runtime test mode command line
|
* Or you can set it via the runtime test mode command line
|
||||||
|
@ -168,6 +168,26 @@ The communication parameters are 115200 8-N-1.
|
||||||
.. note:: The reset button of the KC705 board is the "CPU_RST" labeled button.
|
.. note:: The reset button of the KC705 board is the "CPU_RST" labeled button.
|
||||||
.. warning:: Both those instructions will result in the flash storage being wiped out. However you can use the test mode to change the IP/MAC without erasing everything if you skip the "fserase" command.
|
.. warning:: Both those instructions will result in the flash storage being wiped out. However you can use the test mode to change the IP/MAC without erasing everything if you skip the "fserase" command.
|
||||||
|
|
||||||
|
* (optional) Flash the ``idle`` kernel
|
||||||
|
|
||||||
|
The ``idle`` kernel is the kernel (some piece of code running on the core device) which the core device runs whenever it is not connected to a PC via ethernet.
|
||||||
|
This kernel is therefore stored in the :ref:`core device configuration flash storage <core-device-flash-storage>`.
|
||||||
|
To flash the ``idle`` kernel:
|
||||||
|
|
||||||
|
* Compile the ``idle`` experiment:
|
||||||
|
The ``idle`` experiment's ``run()`` method must be a kernel: it must be decorated with the ``@kernel`` decorator (see :ref:`next topic <connecting-to-the-core-device>` for more information about kernels).
|
||||||
|
|
||||||
|
Moreover, since the core device is not connected to the PC: RPC are forbidden in this ``idle`` experiment.
|
||||||
|
::
|
||||||
|
|
||||||
|
$ artiq_compile idle.py
|
||||||
|
|
||||||
|
* Write it into the core device configuration flash storage: ::
|
||||||
|
|
||||||
|
$ artiq_coreconfig -f idle_kernel idle.elf
|
||||||
|
|
||||||
|
.. note:: You can find more information about how to use the ``artiq_coreconfig`` tool on the :ref:`Utilities <core-device-configuration-tool>` page.
|
||||||
|
|
||||||
Installing the host-side software
|
Installing the host-side software
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
|
@ -197,31 +217,13 @@ Installing the host-side software
|
||||||
.. note::
|
.. note::
|
||||||
Compilation of LLVM can take more than 30 min on some machines.
|
Compilation of LLVM can take more than 30 min on some machines.
|
||||||
|
|
||||||
* Install ARTIQ (without the GUI): ::
|
* Install ARTIQ: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
$ cd ~/artiq-dev
|
||||||
$ git clone https://github.com/m-labs/artiq # if not already done
|
$ git clone https://github.com/m-labs/artiq # if not already done
|
||||||
$ cd artiq
|
$ cd artiq
|
||||||
$ python3 setup.py develop --user
|
$ python3 setup.py develop --user
|
||||||
|
|
||||||
* Install ARTIQ (with the GUI): ::
|
|
||||||
|
|
||||||
$ cd ~/artiq-dev
|
|
||||||
$ git clone https://github.com/m-labs/cairoplot3
|
|
||||||
$ cd cairoplot3
|
|
||||||
$ python3 setup.py install --user
|
|
||||||
$ cd -
|
|
||||||
$ git clone https://github.com/m-labs/gbulb
|
|
||||||
$ cd gbulb
|
|
||||||
$ python3 setup.py install --user
|
|
||||||
$ cd -
|
|
||||||
$ git clone https://github.com/m-labs/artiq # if not already done
|
|
||||||
$ cd artiq
|
|
||||||
$ ARTIQ_GUI=1 python3 setup.py develop --user
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
Use ARTIQ_GUI=1 to install GUI dependencies which are only supported on Linux for now, to install ARTIQ on Windows do not set ARTIQ_GUI.
|
|
||||||
|
|
||||||
* Build the documentation: ::
|
* Build the documentation: ::
|
||||||
|
|
||||||
$ cd ~/artiq-dev/artiq/doc/manual
|
$ cd ~/artiq-dev/artiq/doc/manual
|
||||||
|
|
|
@ -117,12 +117,11 @@ To write the value ``test_value`` in the key ``my_key``::
|
||||||
$ artiq_coreconfig -r my_key
|
$ artiq_coreconfig -r my_key
|
||||||
b'test_value'
|
b'test_value'
|
||||||
|
|
||||||
You can also write entire files in a record using the ``-f`` parameter::
|
You can also write entire files in a record using the ``-f`` parameter. This is useful for instance to write the ``idle`` kernel in the flash storage::
|
||||||
|
|
||||||
$ echo "this_is_a_test" > my_filename
|
$ artiq_coreconfig -f idle_kernel idle.elf
|
||||||
$ artiq_coreconfig -f my_key my_filename
|
$ artiq_coreconfig -r idle_kernel | head -c9
|
||||||
$ artiq_coreconfig -r my_key
|
b'\x7fELF
|
||||||
b'this_is_a_test\n'
|
|
||||||
|
|
||||||
You can write several records at once::
|
You can write several records at once::
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,7 @@ unsigned int fs_read(char *key, void *buffer, unsigned int buf_len, unsigned int
|
||||||
memcpy(buffer, record.value, min(record.value_len, buf_len));
|
memcpy(buffer, record.value, min(record.value_len, buf_len));
|
||||||
read_length = min(record.value_len, buf_len);
|
read_length = min(record.value_len, buf_len);
|
||||||
if(remain)
|
if(remain)
|
||||||
*remain = max(0, (int)(record.value_len) - (int)buf_len);
|
*remain = max(0, (int)record.value_len - (int)buf_len);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,6 @@ enum {
|
||||||
REMOTEMSG_TYPE_RPC_REQUEST,
|
REMOTEMSG_TYPE_RPC_REQUEST,
|
||||||
|
|
||||||
REMOTEMSG_TYPE_FLASH_READ_REPLY,
|
REMOTEMSG_TYPE_FLASH_READ_REPLY,
|
||||||
REMOTEMSG_TYPE_FLASH_WRITE_REPLY,
|
|
||||||
REMOTEMSG_TYPE_FLASH_OK_REPLY,
|
REMOTEMSG_TYPE_FLASH_OK_REPLY,
|
||||||
REMOTEMSG_TYPE_FLASH_ERROR_REPLY
|
REMOTEMSG_TYPE_FLASH_ERROR_REPLY
|
||||||
};
|
};
|
||||||
|
@ -259,9 +258,11 @@ static int process_input(void)
|
||||||
value = key + key_len;
|
value = key + key_len;
|
||||||
ret = fs_write(key, value, value_len);
|
ret = fs_write(key, value, value_len);
|
||||||
|
|
||||||
buffer_out[8] = REMOTEMSG_TYPE_FLASH_WRITE_REPLY;
|
if(ret)
|
||||||
buffer_out[9] = ret;
|
buffer_out[8] = REMOTEMSG_TYPE_FLASH_OK_REPLY;
|
||||||
submit_output(10);
|
else
|
||||||
|
buffer_out[8] = REMOTEMSG_TYPE_FLASH_ERROR_REPLY;
|
||||||
|
submit_output(9);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case REMOTEMSG_TYPE_FLASH_ERASE_REQUEST: {
|
case REMOTEMSG_TYPE_FLASH_ERASE_REQUEST: {
|
||||||
|
|
Loading…
Reference in New Issue