From fd28bfbb7cdd7f84ffc9a6bbd64d9c8bcb20de4b Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Mon, 8 Dec 2014 16:11:31 +0800 Subject: [PATCH] artiq_run: reference module by filename --- artiq/management/file_import.py | 15 +++++++++++++++ doc/manual/getting_started.rst | 8 ++++---- frontend/artiq_run.py | 9 ++++----- 3 files changed, 23 insertions(+), 9 deletions(-) create mode 100644 artiq/management/file_import.py diff --git a/artiq/management/file_import.py b/artiq/management/file_import.py new file mode 100644 index 000000000..d1f59fdd1 --- /dev/null +++ b/artiq/management/file_import.py @@ -0,0 +1,15 @@ +import importlib.machinery + + +def file_import(filename): + modname = filename + i = modname.rfind("/") + if i > 0: + modname = modname[i+1:] + i = modname.find(".") + if i > 0: + modname = modname[:i] + modname = "file_import_" + modname + + loader = importlib.machinery.SourceFileLoader(modname, filename) + return loader.load_module() diff --git a/doc/manual/getting_started.rst b/doc/manual/getting_started.rst index a29caa60c..212f08acc 100644 --- a/doc/manual/getting_started.rst +++ b/doc/manual/getting_started.rst @@ -23,7 +23,7 @@ Copy the files ``ddb.pyon`` and ``pdb.pyon`` (containing the device and paramete Run your code using ``artiq_run.py``, which is part of the ARTIQ front-end tools: :: - $ artiq_run.py led + $ artiq_run.py led.py The LED of the device should turn on. Congratulations! You have a basic ARTIQ system up and running. @@ -49,9 +49,9 @@ Modify the code as follows: :: You can then turn the LED off and on by entering 0 or 1 at the prompt that appears: :: - $ artiq_run.py led + $ artiq_run.py led.py Enter desired LED state: 1 - $ artiq_run.py led + $ artiq_run.py 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. @@ -89,7 +89,7 @@ Create a new file ``rtio.py`` containing the following: :: delay(2*us) -Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Papilio Pro) and run ``artiq_run.py led``. 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. +Connect an oscilloscope or logic analyzer to TTL0 (pin C11 on the Papilio Pro) 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.runtime_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. diff --git a/frontend/artiq_run.py b/frontend/artiq_run.py index e10290a8a..9b261ad6b 100755 --- a/frontend/artiq_run.py +++ b/frontend/artiq_run.py @@ -1,11 +1,11 @@ #!/usr/bin/env python3 import argparse -import importlib import sys from inspect import isclass from operator import itemgetter +from artiq.management.file_import import file_import from artiq.language.context import * from artiq.management import pyon from artiq.management.dpdb import DeviceParamDB @@ -37,8 +37,8 @@ def _get_args(): help="function to run") parser.add_argument("-u", "--unit", default=None, help="unit to run") - parser.add_argument("module", - help="module containing the unit to run") + parser.add_argument("file", + help="file containing the unit to run") return parser.parse_args() @@ -54,8 +54,7 @@ def main(): unit_inst = ELFRunner(dpdb) unit_inst.run(args.file, args.function) else: - sys.path.append(".") - module = importlib.import_module(args.module) + module = file_import(args.file) if args.unit is None: units = [(k, v) for k, v in module.__dict__.items() if k[0] != "_" and isclass(v) and issubclass(v, AutoContext) and v is not AutoContext]