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: 9221a275cb82
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: b226dbd2573b
Choose a head ref
  • 3 commits
  • 4 files changed
  • 1 contributor

Commits on Nov 21, 2016

  1. Copy the full SHA
    174c4be View commit details
  2. Copy the full SHA
    2f838e3 View commit details
  3. sawg: unittest data format

    jordens committed Nov 21, 2016
    Copy the full SHA
    b226dbd View commit details
Showing with 158 additions and 13 deletions.
  1. +1 −2 artiq/coredevice/sawg.py
  2. +9 −5 artiq/gateware/targets/kc705.py
  3. +7 −6 artiq/runtime/rtio.c
  4. +141 −0 artiq/test/gateware/test_sawg_fe.py
3 changes: 1 addition & 2 deletions artiq/coredevice/sawg.py
Original file line number Diff line number Diff line change
@@ -26,7 +26,7 @@ def from_mu(self, value: TInt32) -> TFloat:
@portable(flags=["fast-math"])
def to_mu64(self, value: TFloat) -> TList(TInt32):
v = int(round(value*self.scale), width=64)
return [int(v >> 32, width=32), int(v, width=32)]
return [int(v, width=32), int(v >> 32, width=32)]

@kernel
def set_mu(self, value: TInt32):
@@ -73,7 +73,6 @@ def coeff_to_mu(self, value: TList(TFloat)) -> TList(TInt32):
wi = (vi >> k) & 0xffff
v[j//2] += wi << (16 * ((j + 1)//2 - j//2))
j += 1
v.append(vi)
return v

@kernel
14 changes: 9 additions & 5 deletions artiq/gateware/targets/kc705.py
Original file line number Diff line number Diff line change
@@ -451,17 +451,17 @@ def __init__(self, platform):

qpll = GTXQuadPLL(refclk, refclk_freq, linerate)
self.submodules += qpll
phys = []
self.phys = []
for i in range(4):
phy = JESD204BPhyTX(
qpll, platform.request("ad9154_jesd", i), fabric_freq)
phy.gtx.cd_tx.clk.attr.add("keep")
platform.add_period_constraint(phy.gtx.cd_tx.clk, 40*1e9/linerate)
platform.add_false_path_constraints(self.cd_jesd.clk,
phy.gtx.cd_tx.clk)
phys.append(phy)
self.phys.append(phy)
to_jesd = ClockDomainsRenamer("jesd")
self.submodules.core = to_jesd(JESD204BCoreTX(phys, settings,
self.submodules.core = to_jesd(JESD204BCoreTX(self.phys, settings,
converter_data_width=32))
self.submodules.control = to_jesd(JESD204BCoreTXControl(self.core))

@@ -595,8 +595,12 @@ def __init__(self, cpu_type="or1k", **kwargs):

self.config["RTIO_FINE_TS_WIDTH"] = self.rtio.fine_ts_width
platform.add_false_path_constraints(
self.crg.cd_sys.clk,
self.rtio_crg.cd_rtio.clk)
self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk)
platform.add_false_path_constraints(
self.crg.cd_sys.clk, self.ad9154.jesd.cd_jesd.clk)
for phy in self.ad9154.jesd.phys:
platform.add_false_path_constraints(
self.crg.cd_sys.clk, phy.gtx.cd_tx.clk)


def main():
13 changes: 7 additions & 6 deletions artiq/runtime/rtio.c
Original file line number Diff line number Diff line change
@@ -58,7 +58,7 @@ void rtio_output(long long int timestamp, int channel, unsigned int addr,
#ifdef CSR_RTIO_O_ADDRESS_ADDR
rtio_o_address_write(addr);
#endif
MMPTR(CSR_RTIO_O_DATA_ADDR) = data;
MMPTR(CSR_RTIO_O_DATA_ADDR + CSR_RTIO_O_DATA_SIZE - 1) = data;
rtio_o_we_write(1);
status = rtio_o_status_read();
if(status)
@@ -70,15 +70,16 @@ void rtio_output_list(long long int timestamp, int channel,
unsigned int addr, struct artiq_list data)
{
int status, i;
volatile unsigned int *p = &MMPTR(CSR_RTIO_O_DATA_ADDR);
volatile unsigned int *p = &MMPTR(
CSR_RTIO_O_DATA_ADDR + CSR_RTIO_O_DATA_SIZE - 1);

rtio_chan_sel_write(channel);
rtio_o_timestamp_write(timestamp);
#ifdef CSR_RTIO_O_ADDRESS_ADDR
rtio_o_address_write(addr);
#endif
for(i=0;i<data.length;i++)
*p++ = *data.elements++;
*p-- = *data.elements++;
rtio_o_we_write(1);
status = rtio_o_status_read();
if(status)
@@ -136,7 +137,7 @@ unsigned int rtio_input_data(int channel)
}
}

data = MMPTR(CSR_RTIO_I_DATA_ADDR);
data = MMPTR(CSR_RTIO_I_DATA_ADDR + CSR_RTIO_I_DATA_SIZE - 1);
rtio_i_re_write(1);
return data;
}
@@ -160,14 +161,14 @@ void rtio_log_va(long long int timestamp, const char *fmt, va_list args)
word <<= 8;
word |= *buf & 0xff;
if(*buf == 0) {
MMPTR(CSR_RTIO_O_DATA_ADDR) = word;
MMPTR(CSR_RTIO_O_DATA_ADDR + CSR_RTIO_O_DATA_SIZE - 1) = word;
rtio_o_we_write(1);
break;
}
buf++;
i++;
if(i == 4) {
MMPTR(CSR_RTIO_O_DATA_ADDR) = word;
MMPTR(CSR_RTIO_O_DATA_ADDR + CSR_RTIO_O_DATA_SIZE - 1) = word;
rtio_o_we_write(1);
word = 0;
i = 0;
141 changes: 141 additions & 0 deletions artiq/test/gateware/test_sawg_fe.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import unittest
import numpy as np

import migen as mg

from artiq.coredevice import sawg
from artiq.language import delay_mu, core as core_language
from artiq.gateware.rtio.phy.sawg import Channel
from artiq.sim import devices as sim_devices, time as sim_time


class RTIOManager:
def __init__(self):
self.outputs = []

def rtio_output(self, now, channel, addr, data):
self.outputs.append((now, channel, addr, data))

def rtio_output_list(self, *args, **kwargs):
self.rtio_output(*args, **kwargs)

def int(self, value, width=32):
if width == 32:
return np.int32(value)
elif width == 64:
return np.int64(value)
else:
raise ValueError(width)

def patch(self, mod):
assert not getattr(mod, "_saved", None)
mod._saved = {}
for name in "rtio_output rtio_output_list int".split():
mod._saved[name] = getattr(mod, name, None)
setattr(mod, name, getattr(self, name))

def unpatch(self, mod):
mod.__dict__.update(mod._saved)
del mod._saved


class SAWGTest(unittest.TestCase):
def setUp(self):
core_language.set_time_manager(sim_time.Manager())
self.rtio_manager = RTIOManager()
self.rtio_manager.patch(sawg)
self.core = sim_devices.Core({})
self.core.coarse_ref_period = 8
self.channel = mg.ClockDomainsRenamer({"rio_phy": "sys"})(
Channel(width=16, parallelism=4))
self.driver = sawg.SAWG({"core": self.core}, channel_base=0,
parallelism=self.channel.parallelism)

def tearDown(self):
self.rtio_manager.unpatch(sawg)

def test_instantiate(self):
pass

def test_make_events(self):
d = self.driver
d.offset.set(.9)
delay_mu(2*8)
d.frequency0.set64(.1)
delay_mu(2*8)
d.offset.set(0)
self.assertEqual(
self.rtio_manager.outputs, [
(0, 1, 0, int(round(
(1 << self.driver.offset.width - 1)*.9))),
(2*8, 8, 0, [0, int(round(
(1 << self.driver.frequency0.width - 1) *
self.channel.parallelism*.1))]),
(4*8, 1, 0, 0),
])

def run_channel(self, events):
def gen(dut, events):
c = 0
for time, channel, address, data in events:
assert c <= time
while c < time:
yield
c += 1
for phy in dut.phys:
yield phy.rtlink.o.stb.eq(0)
rt = dut.phys[channel].rtlink.o
if isinstance(data, list):
data = sum(d << i*32 for i, d in enumerate(data))
yield rt.data.eq(int(data))
yield rt.stb.eq(1)
assert not (yield rt.busy)

def log(dut, data, n):
for i in range(dut.latency):
yield
for i in range(n):
yield
data.append((yield from [(yield _) for _ in dut.o]))

data = []
mg.run_simulation(self.channel, [
gen(self.channel, events),
log(self.channel, data, int(events[-1][0]//8) + 1)],
vcd_name="dds.vcd")
return sum(data, [])

def test_channel(self):
self.test_make_events()
out = self.run_channel(self.rtio_manager.outputs)
print(out)

def test_coeff(self):
import struct
for v in [-.1], [.1, -.01], [.1, .01, -.00001], \
[.1, .01, .00001, -.000000001]:
ch = self.driver.offset
p = ch.coeff_to_mu(v)
t = ch.time_width
w = ch.width
p0 = [struct.pack("<" + "_hiqq"[(w + i*t)//16],
int(round(vi*ch.scale*ch.time_scale**i))
)[:(w + i*t)//8]
for i, vi in enumerate(v)]
p0 = b"".join(p0)
if len(p0) % 4:
p0 += b"\x00"*(4 - len(p0) % 4)
p0 = list(struct.unpack("<" + "I"*((len(p0) + 3)//4), p0))
with self.subTest(v):
self.assertEqual(p, p0)

def test_linear(self):
d = self.driver
d.offset.set_list_mu([100, 10])
delay_mu(10*8)
d.offset.set_list([0])
delay_mu(1*8)
out = self.run_channel(self.rtio_manager.outputs)
self.assertEqual(
out, sum(([100 + i*10]*self.channel.parallelism
for i in range(11)), []))