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. Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    2f838e3 View commit details
  3. sawg: unittest data format

    jordens committed Nov 21, 2016

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    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)), []))