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: 2146e58d202b
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: 57d633f48ef3
Choose a head ref
  • 4 commits
  • 10 files changed
  • 1 contributor

Commits on Dec 1, 2014

  1. Copy the full SHA
    3a27f49 View commit details
  2. Copy the full SHA
    99d530e View commit details
  3. Copy the full SHA
    cd587e4 View commit details
  4. Copy the full SHA
    57d633f View commit details
Showing with 65 additions and 64 deletions.
  1. +4 −1 artiq/coredevice/dds.py
  2. +4 −18 artiq/coredevice/rtio.py
  3. +0 −1 artiq/coredevice/runtime.py
  4. +1 −5 doc/manual/fpga_board_ports.rst
  5. +1 −1 frontend/runelf.py
  6. +36 −16 soc/artiqlib/rtio/core.py
  7. +18 −19 soc/runtime/rtio.c
  8. +0 −1 soc/runtime/rtio.h
  9. +0 −1 soc/runtime/services.c
  10. +1 −1 soc/targets/artiq.py
5 changes: 4 additions & 1 deletion artiq/coredevice/dds.py
Original file line number Diff line number Diff line change
@@ -26,6 +26,7 @@ class DDS(AutoContext):
parameters = "dds_sysclk reg_channel rtio_switch"

def build(self):
self.previous_on = False
self.previous_frequency = 0*MHz
self.set_phase_mode(PHASE_MODE_CONTINUOUS)
self.sw = rtio.RTIOOut(self, channel=self.rtio_switch)
@@ -95,7 +96,7 @@ def on(self, frequency, phase_mode=PHASE_MODE_DEFAULT, phase_offset=0):
# 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)
rt_fud = merge or self.previous_on
ftw = self.frequency_to_ftw(frequency)
if self.phase_mode != PHASE_MODE_CONTINUOUS:
phase_per_microcycle = ftw*int64(
@@ -108,6 +109,7 @@ def on(self, frequency, phase_mode=PHASE_MODE_DEFAULT, phase_offset=0):
rt_fud, self.phase_mode == PHASE_MODE_TRACKING)
self.previous_frequency = frequency
self.sw.on()
self.previous_on = True

if phase_mode != PHASE_MODE_DEFAULT:
self.set_phase_mode(old_phase_mode)
@@ -118,6 +120,7 @@ def off(self):
"""
self.sw.off()
self.previous_on = False

@kernel
def pulse(self, frequency, duration,
22 changes: 4 additions & 18 deletions artiq/coredevice/rtio.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from artiq.language.core import *
from artiq.coredevice.runtime_exceptions import RTIOSequenceError


class LLRTIOOut(AutoContext):
"""Low-level RTIO output driver.
Allows setting RTIO outputs at arbitrary times, without time unit
conversion and without zero-length transition suppression.
conversion.
This is meant to be used mostly in drivers; consider using
``RTIOOut`` instead.
@@ -15,7 +14,6 @@ class LLRTIOOut(AutoContext):
parameters = "channel"

def build(self):
self.previous_timestamp = int64(0) # in RTIO cycles
self._set_oe()

@kernel
@@ -30,10 +28,7 @@ def set_value(self, t, value):
:param value: value to set at the output.
"""
if t <= self.previous_timestamp:
raise RTIOSequenceError
syscall("rtio_set", t, self.channel, value)
self.previous_timestamp = t

@kernel
def on(self, t):
@@ -53,30 +48,21 @@ def off(self, t):
"""
self.set_value(t, 0)


class _RTIOBase(AutoContext):
parameters = "channel"

def build(self):
self.previous_timestamp = int64(0) # in RTIO cycles
self.previous_value = 0

@kernel
def _set_oe(self, oe):
syscall("rtio_oe", self.channel, oe)

@kernel
def _set_value(self, value):
if time_to_cycles(now()) < self.previous_timestamp:
raise RTIOSequenceError
if self.previous_value != value:
if self.previous_timestamp == time_to_cycles(now()):
syscall("rtio_replace", time_to_cycles(now()),
self.channel, value)
else:
syscall("rtio_set", time_to_cycles(now()),
self.channel, value)
self.previous_timestamp = time_to_cycles(now())
self.previous_value = value
syscall("rtio_set", time_to_cycles(now()), self.channel, value)
self.previous_timestamp = time_to_cycles(now())


class RTIOOut(_RTIOBase):
1 change: 0 additions & 1 deletion artiq/coredevice/runtime.py
Original file line number Diff line number Diff line change
@@ -15,7 +15,6 @@
"gpio_set": "ib:n",
"rtio_oe": "ib:n",
"rtio_set": "Iii:n",
"rtio_replace": "Iii:n",
"rtio_get_counter": "n:I",
"rtio_get": "iI:I",
"rtio_pileup_count": "i:i",
6 changes: 1 addition & 5 deletions doc/manual/fpga_board_ports.rst
Original file line number Diff line number Diff line change
@@ -32,11 +32,7 @@ When plugged to a QC-DAQ LVDS adapter, the AD9858 DDS hardware can be used in ad
+--------------+----------+-----------------+
| 7 | TTL5 | Output only |
+--------------+----------+-----------------+
| 8 | TTL6 | Output only |
+--------------+----------+-----------------+
| 9 | TTL7 | Output only |
+--------------+----------+-----------------+
| 10 | FUD | DDS driver only |
| 8 | FUD | DDS driver only |
+--------------+----------+-----------------+

The input only limitation on channels 0 and 1 comes from the QC-DAQ adapter. When the adapter is not used (and physically unplugged from the Papilio Pro board), the corresponding pins on the Papilio Pro can be used as outputs. Do not configure these channels as outputs when the adapter is plugged, as this would cause electrical contention.
2 changes: 1 addition & 1 deletion frontend/runelf.py
Original file line number Diff line number Diff line change
@@ -16,7 +16,7 @@ def main():

with open(args.file, "rb") as f:
binary = f.read()
with comm_serial.CoreCom() as comm:
with comm_serial.Comm() as comm:
runtime_env = comm.get_runtime_env()
if args.e:
print(runtime_env)
52 changes: 36 additions & 16 deletions soc/artiqlib/rtio/core.py
Original file line number Diff line number Diff line change
@@ -88,17 +88,20 @@ def __init__(self, width, loopback_latency):
class _RTIOBankO(Module):
def __init__(self, rbus, counter, fine_ts_width, fifo_depth, guard_io_cycles):
self.sel = Signal(max=len(rbus))
# timestamp and value must be valid 1 cycle before we
self.timestamp = Signal(counter.width + fine_ts_width)
self.value = Signal(2)
self.writable = Signal()
self.we = Signal() # maximum throughput 1/2
self.replace = Signal()
self.underflow = Signal() # valid 2 cycles after we/replace
self.underflow = Signal() # valid 2 cycles after we
self.underflow_reset = Signal()
self.sequence_error = Signal()
self.sequence_error_reset = Signal()

# # #

signal_underflow = Signal()
signal_sequence_error = Signal()
fifos = []
ev_layout = [("timestamp", counter.width + fine_ts_width),
("value", 2)]
@@ -110,37 +113,50 @@ def __init__(self, rbus, counter, fine_ts_width, fifo_depth, guard_io_cycles):
fifos.append(fifo)

# Buffer
buf_valid = Signal()
buf_pending = Signal()
buf = Record(ev_layout)
buf_just_written = Signal()

# Special cases
replace = Signal()
sequence_error = Signal()
nop = Signal()
self.sync.rsys += [
replace.eq(self.timestamp == buf.timestamp[fine_ts_width:]),
sequence_error.eq(self.timestamp < buf.timestamp[fine_ts_width:]),
nop.eq(self.value == buf.value)
]
self.comb += If(self.we & (self.sel == n) & sequence_error,
signal_sequence_error.eq(1))

# Buffer read and FIFO write
self.comb += fifo.din.eq(buf)
in_guard_time = Signal()
self.comb += in_guard_time.eq(
buf.timestamp[fine_ts_width:] < counter.o_value_sys + guard_io_cycles)
self.sync.rsys += If(in_guard_time, buf_valid.eq(0))
self.sync.rsys += If(in_guard_time, buf_pending.eq(0))
self.comb += \
If(buf_valid,
If(buf_pending,
If(in_guard_time,
If(buf_just_written,
signal_underflow.eq(1)
).Else(
fifo.we.eq(1)
)
),
If(self.we & (self.sel == n), fifo.we.eq(1))
If((self.we & (self.sel == n)
& ~replace & ~nop & ~sequence_error),
fifo.we.eq(1)
)
)

# Buffer write
# Must come after read to handle concurrent read+write properly
self.sync.rsys += [
buf_just_written.eq(0),
If((self.we | self.replace) & (self.sel == n),
# Replace operations on empty buffers may happen
# on underflows, which will be correctly reported.
If(self.we & (self.sel == n) & ~nop & ~sequence_error,
buf_just_written.eq(1),
buf_valid.eq(1),
buf_pending.eq(1),
buf.timestamp.eq(self.timestamp),
buf.value.eq(self.value)
)
@@ -174,7 +190,9 @@ def __init__(self, rbus, counter, fine_ts_width, fifo_depth, guard_io_cycles):
self.writable.eq(Array(fifo.writable for fifo in fifos)[self.sel])
self.sync.rsys += [
If(self.underflow_reset, self.underflow.eq(0)),
If(signal_underflow, self.underflow.eq(1))
If(self.sequence_error_reset, self.sequence_error.eq(0)),
If(signal_underflow, self.underflow.eq(1)),
If(signal_sequence_error, self.sequence_error.eq(1))
]


@@ -298,9 +316,9 @@ def __init__(self, phy, clk_freq, counter_width=32,
self._r_o_timestamp = CSRStorage(counter_width + fine_ts_width)
self._r_o_value = CSRStorage(2)
self._r_o_we = CSR()
self._r_o_replace = CSR()
self._r_o_status = CSRStatus(2)
self._r_o_status = CSRStatus(3)
self._r_o_underflow_reset = CSR()
self._r_o_sequence_error_reset = CSR()

self._r_i_timestamp = CSRStatus(counter_width + fine_ts_width)
self._r_i_value = CSRStatus()
@@ -350,9 +368,11 @@ def __init__(self, phy, clk_freq, counter_width=32,
self.bank_o.timestamp.eq(self._r_o_timestamp.storage),
self.bank_o.value.eq(self._r_o_value.storage),
self.bank_o.we.eq(self._r_o_we.re),
self.bank_o.replace.eq(self._r_o_replace.re),
self._r_o_status.status.eq(Cat(~self.bank_o.writable, self.bank_o.underflow)),
self.bank_o.underflow_reset.eq(self._r_o_underflow_reset.re)
self._r_o_status.status.eq(Cat(~self.bank_o.writable,
self.bank_o.underflow,
self.bank_o.sequence_error)),
self.bank_o.underflow_reset.eq(self._r_o_underflow_reset.re),
self.bank_o.sequence_error_reset.eq(self._r_o_sequence_error_reset.re)
]

# Input
37 changes: 18 additions & 19 deletions soc/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@

#define RTIO_O_STATUS_FULL 1
#define RTIO_O_STATUS_UNDERFLOW 2
#define RTIO_O_STATUS_SEQUENCE_ERROR 4
#define RTIO_I_STATUS_EMPTY 1
#define RTIO_I_STATUS_OVERFLOW 2

@@ -39,18 +40,10 @@ void rtio_set(long long int timestamp, int channel, int value)
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
}
}
}

void rtio_replace(long long int timestamp, int channel, int value)
{
rtio_chan_sel_write(channel);
rtio_o_timestamp_write(timestamp);
rtio_o_value_write(value);
rtio_o_replace_write(1);
if(rtio_o_status_read() & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
if(status & RTIO_O_STATUS_SEQUENCE_ERROR) {
rtio_o_sequence_error_reset_write(1);
exception_raise(EID_RTIO_SEQUENCE_ERROR);
}
}
}

@@ -66,7 +59,7 @@ long long int rtio_get(int channel, long long int time_limit)
int status;

rtio_chan_sel_write(channel);
while(status = rtio_i_status_read()) {
while((status = rtio_i_status_read())) {
if(rtio_i_status_read() & RTIO_I_STATUS_OVERFLOW) {
rtio_i_overflow_reset_write(1);
exception_raise(EID_RTIO_OVERFLOW);
@@ -95,7 +88,7 @@ int rtio_pileup_count(int channel)
return r;
}

#define RTIO_FUD_CHANNEL 10
#define RTIO_FUD_CHANNEL 8

void rtio_fud_sync(void)
{
@@ -105,11 +98,10 @@ void rtio_fud_sync(void)
void rtio_fud(long long int fud_time)
{
long long int fud_end_time;
int status;

rtio_chan_sel_write(RTIO_FUD_CHANNEL);
fud_end_time = fud_time + 3*8;
if(fud_time < previous_fud_end_time)
exception_raise(EID_RTIO_SEQUENCE_ERROR);
previous_fud_end_time = fud_end_time;

rtio_o_timestamp_write(fud_time);
@@ -118,8 +110,15 @@ void rtio_fud(long long int fud_time)
rtio_o_timestamp_write(fud_end_time);
rtio_o_value_write(0);
rtio_o_we_write(1);
if(rtio_o_status_read() & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
status = rtio_o_status_read();
if(status) {
if(status & RTIO_O_STATUS_UNDERFLOW) {
rtio_o_underflow_reset_write(1);
exception_raise(EID_RTIO_UNDERFLOW);
}
if(status & RTIO_O_STATUS_SEQUENCE_ERROR) {
rtio_o_sequence_error_reset_write(1);
exception_raise(EID_RTIO_SEQUENCE_ERROR);
}
}
}
1 change: 0 additions & 1 deletion soc/runtime/rtio.h
Original file line number Diff line number Diff line change
@@ -4,7 +4,6 @@
void rtio_init(void);
void rtio_oe(int channel, int oe);
void rtio_set(long long int timestamp, int channel, int value);
void rtio_replace(long long int timestamp, int channel, int value);
long long int rtio_get_counter(void);
long long int rtio_get(int channel, long long int time_limit);
int rtio_pileup_count(int channel);
1 change: 0 additions & 1 deletion soc/runtime/services.c
Original file line number Diff line number Diff line change
@@ -13,7 +13,6 @@ static const struct symbol syscalls[] = {
{"gpio_set", gpio_set},
{"rtio_oe", rtio_oe},
{"rtio_set", rtio_set},
{"rtio_replace", rtio_replace},
{"rtio_get_counter", rtio_get_counter},
{"rtio_get", rtio_get},
{"rtio_pileup_count", rtio_pileup_count},
2 changes: 1 addition & 1 deletion soc/targets/artiq.py
Original file line number Diff line number Diff line change
@@ -92,7 +92,7 @@ def __init__(self, platform, cpu_type="or1k", ramcon_type="minicon",
platform.request("ttl_h_tx_en").eq(1)
]
rtio_ins = [platform.request("pmt") for i in range(2)]
rtio_outs = [platform.request("ttl", i) for i in range(8)] + [fud]
rtio_outs = [platform.request("ttl", i) for i in range(6)] + [fud]

self.submodules.rtiocrg = _RTIOMiniCRG(platform)
self.submodules.rtiophy = rtio.phy.SimplePHY(