Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/artiq
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: e01050b19a73
Choose a base ref
...
head repository: m-labs/artiq
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: dfd779c7c546
Choose a head ref
  • 3 commits
  • 12 files changed
  • 1 contributor

Commits on Nov 20, 2014

  1. Copy the full SHA
    1780759 View commit details
  2. Copy the full SHA
    96720d2 View commit details
  3. Copy the full SHA
    dfd779c View commit details
1 change: 1 addition & 0 deletions artiq/coredevice/comm_dummy.py
Original file line number Diff line number Diff line change
@@ -7,6 +7,7 @@
class _RuntimeEnvironment(LinkInterface):
def __init__(self, ref_period):
self.ref_period = ref_period
self.initial_time = 0

def emit_object(self):
return str(self.llvm_module)
9 changes: 8 additions & 1 deletion artiq/coredevice/core.py
Original file line number Diff line number Diff line change
@@ -11,6 +11,7 @@
from artiq.transforms.lower_time import lower_time
from artiq.transforms.unparse import unparse
from artiq.py2llvm import get_runtime_binary
from artiq.language.core import *


def _announce_unparse(label, node):
@@ -46,6 +47,7 @@ def __init__(self, comm, runtime_env=None):
runtime_env = comm.get_runtime_env()
self.runtime_env = runtime_env
self.comm = comm
self.core = self

def transform_stack(self, func_def, rpc_map, exception_map,
debug_unparse=_no_debug_unparse):
@@ -67,7 +69,7 @@ def transform_stack(self, func_def, rpc_map, exception_map,
interleave(func_def)
debug_unparse("interleave", func_def)

lower_time(func_def, getattr(self.runtime_env, "initial_time", 0))
lower_time(func_def, self.runtime_env.initial_time)
debug_unparse("lower_time", func_def)

remove_inter_assigns(func_def)
@@ -103,3 +105,8 @@ def run(self, k_function, k_args, k_kwargs):
self.comm.load(binary)
self.comm.run(func_def.name)
self.comm.serve(rpc_map, exception_map)

@kernel
def recover_underflow(self):
t = syscall("rtio_get_counter") + self.runtime_env.initial_time
at(cycles_to_time(t))
82 changes: 65 additions & 17 deletions artiq/coredevice/dds.py
Original file line number Diff line number Diff line change
@@ -3,6 +3,12 @@
from artiq.coredevice import rtio


PHASE_MODE_DEFAULT = -1
PHASE_MODE_CONTINUOUS = 0
PHASE_MODE_ABSOLUTE = 1
PHASE_MODE_TRACKING = 2


class DDS(AutoContext):
"""Core device Direct Digital Synthesis (DDS) driver.
@@ -21,6 +27,7 @@ class DDS(AutoContext):

def build(self):
self.previous_frequency = 0*MHz
self.set_phase_mode(PHASE_MODE_CONTINUOUS)
self.sw = rtio.RTIOOut(self, channel=self.rtio_switch)

@portable
@@ -40,33 +47,71 @@ def ftw_to_frequency(self, ftw):
return ftw*self.dds_sysclk/2**32

@kernel
def on(self, frequency):
def set_phase_mode(self, phase_mode):
"""Sets the phase mode of the DDS channel. Supported phase modes are:
* ``PHASE_MODE_CONTINUOUS``: the phase accumulator is unchanged when
switching frequencies. The DDS phase is the sum of the phase
accumulator and the phase offset. The only discrete jumps in the
DDS output phase come from changes to the phase offset.
* ``PHASE_MODE_ABSOLUTE``: the phase accumulator is reset when
switching frequencies. Thus, the phase of the DDS at the time of
the frequency change is equal to the phase offset.
* ``PHASE_MODE_TRACKING``: when switching frequencies, the phase
accumulator is set to the value it would have if the DDS had been
running at the specified frequency since the start of the
experiment.
"""
self.phase_mode = phase_mode
syscall("dds_phase_clear_en", self.reg_channel,
self.phase_mode != PHASE_MODE_CONTINUOUS)

@kernel
def on(self, frequency, phase_mode=PHASE_MODE_DEFAULT, phase_offset=0):
"""Sets the DDS channel to the specified frequency and turns it on.
If the DDS channel was already on, a real-time frequency update is
performed.
If the DDS channel was already on, a real-time frequency and phase
update is performed.
:param frequency: frequency to generate.
:param phase_mode: if specified, overrides the default phase mode set
by ``set_phase_mode`` for this call.
:param phase_offset: adds an offset, in turns, to the phase.
"""
if phase_mode != PHASE_MODE_DEFAULT:
old_phase_mode = self.phase_mode
self.set_phase_mode(phase_mode)

if self.previous_frequency != frequency:
merge = self.sw.previous_timestamp == time_to_cycles(now())
if not merge:
self.sw.sync()
if merge or bool(self.sw.previous_value):
# Channel is already on.
# Precise timing of frequency change is required.
fud_time = time_to_cycles(now())
# Channel is already on:
# Precise timing of frequency change is required.
# Channel is off:
# Use soft timing on FUD to prevent conflicts when reprogramming
# several channels that need to be turned on at the same time.
rt_fud = merge or bool(self.sw.previous_value)
ftw = self.frequency_to_ftw(frequency)
if self.phase_mode != PHASE_MODE_CONTINUOUS:
phase_per_microcycle = ftw*int64(
self.dds_sysclk.amount*self.core.runtime_env.ref_period)
else:
# Channel is off.
# Use soft timing on FUD to prevent conflicts when
# reprogramming several channels that need to be turned on at
# the same time.
fud_time = -1
syscall("dds_program", self.reg_channel,
self.frequency_to_ftw(frequency),
fud_time)
phase_per_microcycle = int64(0)
syscall("dds_program", time_to_cycles(now()), self.reg_channel,
ftw, int(phase_offset*2**14),
phase_per_microcycle,
rt_fud, self.phase_mode == PHASE_MODE_TRACKING)
self.previous_frequency = frequency
self.sw.on()

if phase_mode != PHASE_MODE_DEFAULT:
self.set_phase_mode(old_phase_mode)

@kernel
def off(self):
"""Turns the DDS channel off.
@@ -75,13 +120,16 @@ def off(self):
self.sw.off()

@kernel
def pulse(self, frequency, duration):
def pulse(self, frequency, duration,
phase_mode=PHASE_MODE_DEFAULT, phase_offset=0):
"""Pulses the DDS channel for the specified duration at the specified
frequency.
See ``on`` for a description of the parameters.
Equivalent to a ``on``, ``delay``, ``off`` sequence.
"""
self.on(frequency)
self.on(frequency, phase_mode, phase_offset)
delay(duration)
self.off()
8 changes: 6 additions & 2 deletions artiq/coredevice/runtime.py
Original file line number Diff line number Diff line change
@@ -17,19 +17,23 @@
"rtio_set": "Iii:n",
"rtio_replace": "Iii:n",
"rtio_sync": "i:n",
"rtio_get_counter": "n:I",
"rtio_get": "i:I",
"rtio_pileup_count": "i:i",
"dds_program": "iiI:n",
"dds_phase_clear_en": "ib:n",
"dds_program": "IiiiIbb:n",
}

_chr_to_type = {
"n": lambda: lc.Type.void(),
"b": lambda: lc.Type.int(1),
"i": lambda: lc.Type.int(32),
"I": lambda: lc.Type.int(64)
}

_chr_to_value = {
"n": lambda: base_types.VNone(),
"b": lambda: base_types.VBool(),
"i": lambda: base_types.VInt(),
"I": lambda: base_types.VInt(64)
}
@@ -45,7 +49,7 @@ def _str_to_functype(s):
if c == "+":
type_args.append(lc.Type.int())
var_arg_fixcount = n
else:
elif c != "n":
type_args.append(_chr_to_type[c]())
return (var_arg_fixcount,
lc.Type.function(type_ret, type_args,
50 changes: 0 additions & 50 deletions examples/compiler_test.py

This file was deleted.

2 changes: 1 addition & 1 deletion examples/pulse_performance.py
Original file line number Diff line number Diff line change
@@ -20,7 +20,7 @@ def run(self):
delay(cycles_to_time(T))
except RTIOUnderflow:
T += 1
delay(1*ms)
self.core.recover_underflow()
else:
print_min_period(int(cycles_to_time(2*T)/(1*ns)))
break
49 changes: 42 additions & 7 deletions soc/runtime/dds.c
Original file line number Diff line number Diff line change
@@ -9,6 +9,8 @@
#define DDS_FTW1 0x0b
#define DDS_FTW2 0x0c
#define DDS_FTW3 0x0d
#define DDS_POW0 0x0e
#define DDS_POW1 0x0f
#define DDS_GPIO 0x41

#define DDS_READ(addr) \
@@ -25,22 +27,55 @@ void dds_init(void)
DDS_WRITE(DDS_GPIO, i);
DDS_WRITE(DDS_GPIO, i | (1 << 7));
DDS_WRITE(DDS_GPIO, i);
DDS_WRITE(0x00, 0x78);
DDS_WRITE(0x01, 0x00);
DDS_WRITE(0x02, 0x00);
DDS_WRITE(0x03, 0x00);
rtio_fud(-1);
rtio_fud_sync();
dds_phase_clear_en(i, 0);
}
}

void dds_program(int channel, int ftw, long long int fud_time)
void dds_phase_clear_en(int channel, int phase_clear_en)
{
DDS_WRITE(0x00, 0x78);
DDS_WRITE(0x01, 0x00);
DDS_WRITE(0x02, phase_clear_en ? 0x40 : 0x00);
DDS_WRITE(0x03, 0x00);
}

/*
* DDS phase modes:
* - continuous: Set phase_per_microcycle=0 to disable POW alteration.
* phase_tracking is ignored, set to 0.
* Disable phase accumulator clearing prior to programming.
* - absolute: Set phase_per_microcycle to its nominal value
* and phase_tracking=0.
* Enable phase accumulator clearing prior to programming.
* - tracking: Set phase_per_microcycle to its nominal value
* and phase_tracking=1.
* Enable phase accumulator clearing prior to programming.
*/
void dds_program(long long int timestamp, int channel,
int ftw, int pow, long long int phase_per_microcycle,
int rt_fud, int phase_tracking)
{
long long int fud_time;
long long int phase_time_offset;

rtio_fud_sync();
DDS_WRITE(DDS_GPIO, channel);

DDS_WRITE(DDS_FTW0, ftw & 0xff);
DDS_WRITE(DDS_FTW1, (ftw >> 8) & 0xff);
DDS_WRITE(DDS_FTW2, (ftw >> 16) & 0xff);
DDS_WRITE(DDS_FTW3, (ftw >> 24) & 0xff);

phase_time_offset = phase_tracking ? timestamp : 0;
if(rt_fud)
fud_time = timestamp;
else {
fud_time = rtio_get_counter() + 8000;
phase_time_offset -= timestamp - fud_time;
}
pow += phase_time_offset*phase_per_microcycle;
DDS_WRITE(DDS_POW0, pow & 0xff);
DDS_WRITE(DDS_POW1, (pow >> 8) & 0x3f);

rtio_fud(fud_time);
}
5 changes: 4 additions & 1 deletion soc/runtime/dds.h
Original file line number Diff line number Diff line change
@@ -2,6 +2,9 @@
#define __DDS_H

void dds_init(void);
void dds_program(int channel, int ftw, long long int fud_time);
void dds_phase_clear_en(int channel, int phase_clear_en);
void dds_program(long long int timestamp, int channel,
int ftw, int pow, long long int phase_per_microcycle,
int rt_fud, int phase_tracking);

#endif /* __DDS_H */
1 change: 0 additions & 1 deletion soc/runtime/main.c
Original file line number Diff line number Diff line change
@@ -110,7 +110,6 @@ int main(void)
uart_init();

puts("ARTIQ runtime built "__DATE__" "__TIME__"\n");
rtio_init();
dds_init();
blink_led();
comm_serve(load_object, run_kernel);
13 changes: 7 additions & 6 deletions soc/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ void rtio_init(void)
previous_fud_end_time = 0;
rtio_reset_counter_write(1);
rtio_reset_logic_write(1);
rtio_reset_counter_write(0);
rtio_reset_logic_write(0);
}

@@ -21,7 +22,6 @@ void rtio_oe(int channel, int oe)

void rtio_set(long long int timestamp, int channel, int value)
{
rtio_reset_counter_write(0);
rtio_chan_sel_write(channel);
rtio_o_timestamp_write(timestamp);
rtio_o_value_write(value);
@@ -53,6 +53,12 @@ void rtio_sync(int channel)
while(rtio_o_level_read() != 0);
}

long long int rtio_get_counter(void)
{
rtio_counter_update_write(1);
return rtio_counter_read();
}

long long int rtio_get(int channel)
{
long long int r;
@@ -94,12 +100,7 @@ void rtio_fud(long long int fud_time)
{
long long int fud_end_time;

rtio_reset_counter_write(0);
rtio_chan_sel_write(RTIO_FUD_CHANNEL);
if(fud_time < 0) {
rtio_counter_update_write(1);
fud_time = rtio_counter_read() + 4000;
}
fud_end_time = fud_time + 3*8;
if(fud_time < previous_fud_end_time)
exception_raise(EID_RTIO_SEQUENCE_ERROR);
Loading