Merge branch 'master' of github.com:m-labs/artiq

This commit is contained in:
Sebastien Bourdeauducq 2015-06-02 17:45:16 +08:00
commit 59b339462c
7 changed files with 91 additions and 43 deletions

View File

@ -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)

View File

@ -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())

View File

@ -1,6 +1,8 @@
Getting started Getting started
=============== ===============
.. _connecting-to-the-core-device:
Connecting to the core device Connecting to the core device
----------------------------- -----------------------------

View File

@ -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

View File

@ -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::

View File

@ -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);
} }
} }

View File

@ -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: {