doc: add some tutorial steps

pull/231/head
Sebastien Bourdeauducq 2014-09-29 14:50:29 +08:00
parent 4e2c956f9c
commit 9f82ff81f2
3 changed files with 112 additions and 3 deletions

View File

@ -7,4 +7,5 @@ Contents:
:maxdepth: 2
installing
tutorial
core_reference

View File

@ -2,14 +2,14 @@ Installing ARTIQ
================
Preparing the core device FPGA board
************************************
------------------------------------
You may skip those steps if the board is already flashed.
You will need:
* FPGA vendor tools (e.g. Xilinx ISE or Vivado)
* OpenRISC GCC/binutils toolchain (or1k-elf-...)
* Python 3.3+ (note: in this document, the ``python`` command refers to Python 3)
* Python 3.3+
* Migen and MiSoC (http://m-labs.hk/gateware.html)
After these components are installed, build and flash the bitstream and BIOS by running `from the MiSoC top-level directory`: ::
@ -34,7 +34,7 @@ Check that the board boots by running a serial terminal program (you may need to
The communication parameters are 115200 8-N-1.
Installing the host-side software
*********************************
---------------------------------
The main dependency of ARTIQ is LLVM and its Python bindings (http://llvmpy.org). Currently, this installation is tedious because of the OpenRISC support not being merged upstream LLVM and because of incompatibilities between the versions of LLVM that support OpenRISC and the versions of LLVM that support the Python bindings. ::
@ -63,6 +63,9 @@ The main dependency of ARTIQ is LLVM and its Python bindings (http://llvmpy.org)
patch -p1 < /path_to/ARTIQ/patches/llvmpy/*
LLVM_CONFIG_PATH=/usr/local/llvm-or1k/bin/llvm-config sudo -E python setup.py install
.. note::
``python`` refers to Python 3. You may need to use the ``python3`` command instead of ``python`` on some distributions.
You may want to use ``checkinstall`` instead of ``make install`` (to register the installation with your package manager) and ``pip3 install --user .`` instead of ``sudo -E python setup.py install``.
You can then install ARTIQ itself: ::

105
doc/manual/tutorial.rst Normal file
View File

@ -0,0 +1,105 @@
Tutorial
========
Connecting to the core device
-----------------------------
As a very first step, we will turn on a LED on the core device. Create a file ``led.py`` containing the following: ::
from artiq.language.std import *
from artiq.devices import corecom_serial, core, gpio_core
class LED(AutoContext):
parameters = "led"
@kernel
def run(self):
self.led.set(1)
if __name__ == "__main__":
with corecom_serial.CoreCom() as com:
core_driver = core.Core(com)
led_driver = gpio_core.GPIOOut(core=core_driver, channel=0)
exp = LED(core=core_driver, led=led_driver)
exp.run()
The central part of our code is our ``LED`` class, that derives from :class:`artiq.language.core.AutoContext`. ``AutoContext`` is part of the mechanism that attaches device drivers and retrieves parameters according to a database. We are not using the database yet; instead, we import and create the device drivers and establish communication with the core device manually. The ``parameters`` string gives the list of devices (and parameters) that our class needs in order to operate. ``AutoContext`` sets them as object attributes, so our ``led`` parameter becomes accessible as ``self.led``. Finally, the ``@kernel`` decorator tells the system that the ``run`` method must be executed on the core device (instead of the host).
Run this example with: ::
python led.py
The LED of the device should turn on. Congratulations! You have a basic ARTIQ system up and running.
.. note::
ARTIQ requires Python 3, and you may need to use the ``python3`` command instead of ``python`` on some distributions.
Interaction with the host
-------------------------
A method or function running on the core device (which we call a "kernel") may communicate with the host by calling non-kernel functions that may accept parameters and may return a value. The "remote procedure call" (RPC) mechanisms handle automatically the communication between the host and the device of which function to call, with which parameters, and what the returned value is.
Modify the code as follows: ::
def input_led_state():
return int(input("Enter desired LED state: "))
class LED(AutoContext):
parameters = "led"
@kernel
def run(self):
self.led.set(input_led_state())
You can then turn the LED off and on by entering 0 or 1 at the prompt that appears: ::
$ python led.py
Enter desired LED state: 1
$ python led.py
Enter desired LED state: 0
What happens is the ARTIQ compiler notices that the ``input_led_state`` function does not have a ``@kernel`` decorator and thus must be executed on the host. When the core device calls it, it sends a request to the host to execute it. The host displays the prompt, collects user input, and sends the result back to the core device, which sets the LED state accordingly.
Algorithmic features
--------------------
A number of Python algorithmic features can be used inside a kernel for compilation and execution on the core device. They include ``for`` and ``while`` loops, conditionals (``if``, ``else``, ``elif``), functions, exceptions (without parameter), and statically typed variables of the following types:
* Booleans
* 32-bit signed integers (default size)
* 64-bit signed integers (:class:`artiq.language.core.int64`)
* Signed rational numbers with 64-bit numerator and 64-bit denominator
* Double-precision floating point numbers
* Arrays of the above types and arrays of arrays, at an arbitrary depth (:class:`artiq.language.core.array`)
For a demonstration of some of these features, see the ``mandelbrot.py`` example.
Real-time I/O
-------------
The point of running code on the core device is the ability to meet demanding real-time constraints. In particular, the core device can respond to an incoming stimulus or the result of a measurement with a low and predictable latency. We will see how to use inputs later; first, we must familiarize ourselves with how time is managed in kernels.
Create a new file ``rtio.py`` containing the following: ::
from artiq.language.std import *
from artiq.devices import corecom_serial, core, rtio_core
class Tutorial(AutoContext):
parameters = "o"
@kernel
def run(self):
for i in range(1000000):
self.o.pulse(2*us)
delay(2*us)
if __name__ == "__main__":
with corecom_serial.CoreCom() as com:
core_driver = core.Core(com)
out_driver = rtio_core.RTIOOut(core=core_driver, channel=1)
exp = Tutorial(core=core_driver, o=out_driver)
exp.run()
Connect an oscilloscope to the RTIO channel 1 (pin C11 on the Papilio Pro) and run ``python rtio.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.