From b2af0f6cc352faa3509793dc644ccf6751f28f40 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 9 Jun 2015 19:51:02 +0800 Subject: [PATCH] soc,runtime: support TTL override --- artiq/gateware/rtio/__init__.py | 2 +- artiq/gateware/rtio/core.py | 10 +++- artiq/gateware/rtio/moninj.py | 43 +++++++++++++++-- artiq/gateware/rtio/phy/ttl_simple.py | 36 ++++++++++++-- soc/runtime/moninj.c | 67 ++++++++++++++++++++++----- soc/targets/artiq_kc705.py | 13 +++--- soc/targets/artiq_pipistrello.py | 15 +++--- 7 files changed, 150 insertions(+), 36 deletions(-) diff --git a/artiq/gateware/rtio/__init__.py b/artiq/gateware/rtio/__init__.py index 2ca9db8aa..b02ac0d3a 100644 --- a/artiq/gateware/rtio/__init__.py +++ b/artiq/gateware/rtio/__init__.py @@ -1,2 +1,2 @@ from artiq.gateware.rtio.core import Channel, RTIO -from artiq.gateware.rtio.moninj import Monitor +from artiq.gateware.rtio.moninj import MonInj diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index b9d02246a..9aad47127 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -247,12 +247,20 @@ class _InputManager(Module): class Channel: - def __init__(self, interface, probes=[], ofifo_depth=64, ififo_depth=64): + def __init__(self, interface, probes=[], overrides=[], + ofifo_depth=64, ififo_depth=64): self.interface = interface self.probes = probes + self.overrides = overrides self.ofifo_depth = ofifo_depth self.ififo_depth = ififo_depth + @classmethod + def from_phy(cls, phy, **kwargs): + probes = getattr(phy, "probes", []) + overrides = getattr(phy, "overrides", []) + return cls(phy.rtlink, probes, overrides, **kwargs) + class _KernelCSRs(AutoCSR): def __init__(self, chan_sel_width, diff --git a/artiq/gateware/rtio/moninj.py b/artiq/gateware/rtio/moninj.py index 03494c2a1..a09422945 100644 --- a/artiq/gateware/rtio/moninj.py +++ b/artiq/gateware/rtio/moninj.py @@ -1,6 +1,6 @@ from migen.fhdl.std import * from migen.bank.description import * -from migen.genlib.cdc import BusSynchronizer +from migen.genlib.cdc import BusSynchronizer, MultiReg class Monitor(Module, AutoCSR): @@ -11,7 +11,7 @@ class Monitor(Module, AutoCSR): max_probe_len = max(flen(p) for cp in chan_probes for p in cp) self.chan_sel = CSRStorage(bits_for(len(chan_probes)-1)) self.probe_sel = CSRStorage(bits_for(max_chan_probes-1)) - self.probe_value = CSRStatus(max_probe_len) + self.value = CSRStatus(max_probe_len) # # # @@ -25,5 +25,42 @@ class Monitor(Module, AutoCSR): cp_sys.append(vs.o) cp_sys += [0]*(max_chan_probes-len(cp)) chan_probes_sys.append(Array(cp_sys)[self.probe_sel.storage]) - self.comb += self.probe_value.status.eq( + self.comb += self.value.status.eq( Array(chan_probes_sys)[self.chan_sel.storage]) + + +class Injector(Module, AutoCSR): + def __init__(self, channels): + chan_overrides = [c.overrides for c in channels] + + max_chan_overrides = max(len(co) for co in chan_overrides) + max_override_len = max(flen(o) for co in chan_overrides for o in co) + self.chan_sel = CSRStorage(bits_for(len(chan_overrides)-1)) + self.override_sel = CSRStorage(bits_for(max_chan_overrides-1)) + self.value = CSR(max_override_len) + + # # # + + chan_overrides_sys = [] + for n_channel, co in enumerate(chan_overrides): + co_sys = [] + for n_override, o in enumerate(co): + # We do the clock domain transfer with a simple double-latch. + # Software has to ensure proper timing of any strobe signal etc. + # to avoid problematic glitches. + o_sys = Signal.like(o) + self.specials += MultiReg(o_sys, o, "rio") + self.sync += If(self.value.re & (self.chan_sel.storage == n_channel) + & (self.override_sel.storage == n_override), + o_sys.eq(self.value.r)) + co_sys.append(o_sys) + co_sys += [0]*(max_chan_overrides-len(co)) + chan_overrides_sys.append(Array(co_sys)[self.override_sel.storage]) + self.comb += self.value.w.eq( + Array(chan_overrides_sys)[self.chan_sel.storage]) + + +class MonInj(Module, AutoCSR): + def __init__(self, channels): + self.submodules.mon = Monitor(channels) + self.submodules.inj = Injector(channels) diff --git a/artiq/gateware/rtio/phy/ttl_simple.py b/artiq/gateware/rtio/phy/ttl_simple.py index 747f7ca9e..3250a2659 100644 --- a/artiq/gateware/rtio/phy/ttl_simple.py +++ b/artiq/gateware/rtio/phy/ttl_simple.py @@ -8,10 +8,23 @@ class Output(Module): def __init__(self, pad): self.rtlink = rtlink.Interface(rtlink.OInterface(1)) self.probes = [pad] + override_en = Signal() + override_o = Signal() + self.overrides = [override_en, override_o] # # # - self.sync.rio_phy += If(self.rtlink.o.stb, pad.eq(self.rtlink.o.data)) + pad_k = Signal() + self.sync.rio_phy += [ + If(self.rtlink.o.stb, + pad_k.eq(self.rtlink.o.data) + ), + If(override_en, + pad.eq(override_o) + ).Else( + pad.eq(pad_k) + ) + ] class Inout(Module): @@ -19,6 +32,10 @@ class Inout(Module): self.rtlink = rtlink.Interface( rtlink.OInterface(2, 2), rtlink.IInterface(1)) + override_en = Signal() + override_o = Signal() + override_oe = Signal() + self.overrides = [override_en, override_o, override_oe] self.probes = [] # # # @@ -27,10 +44,21 @@ class Inout(Module): self.specials += ts.get_tristate(pad) sensitivity = Signal(2) - self.sync.rio_phy += If(self.rtlink.o.stb, - If(self.rtlink.o.address == 0, ts.o.eq(self.rtlink.o.data[0])), - If(self.rtlink.o.address == 1, ts.oe.eq(self.rtlink.o.data[0])), + o_k = Signal() + oe_k = Signal() + self.sync.rio_phy += [ + If(self.rtlink.o.stb, + If(self.rtlink.o.address == 0, o_k.eq(self.rtlink.o.data[0])), + If(self.rtlink.o.address == 1, oe_k.eq(self.rtlink.o.data[0])), + ), + If(override_en, + ts.o.eq(override_o), + ts.oe.eq(override_oe) + ).Else( + ts.o.eq(o_k), + ts.oe.eq(oe_k) ) + ] self.sync.rio += If(self.rtlink.o.stb & (self.rtlink.o.address == 2), sensitivity.eq(self.rtlink.o.data)) diff --git a/soc/runtime/moninj.c b/soc/runtime/moninj.c index 9dc0811aa..336c88ce1 100644 --- a/soc/runtime/moninj.c +++ b/soc/runtime/moninj.c @@ -20,6 +20,19 @@ enum { MONINJ_REQ_TTLSET = 2 }; +enum { + MONINJ_TTL_MODE_EXP = 0, + MONINJ_TTL_MODE_1 = 1, + MONINJ_TTL_MODE_0 = 2, + MONINJ_TTL_MODE_IN = 3 +}; + +enum { + MONINJ_TTL_OVERRIDE_ENABLE = 0, + MONINJ_TTL_OVERRIDE_O = 1, + MONINJ_TTL_OVERRIDE_OE = 2 +}; + static struct udp_pcb *listen_pcb; struct monitor_reply { @@ -28,8 +41,6 @@ struct monitor_reply { long long int ttl_overrides; }; -static long long int ttl_overrides; - static void moninj_monitor(const ip_addr_t *addr, u16_t port) { struct monitor_reply reply; @@ -38,16 +49,20 @@ static void moninj_monitor(const ip_addr_t *addr, u16_t port) reply.ttl_levels = 0; reply.ttl_oes = 0; + reply.ttl_overrides = 0; for(i=0;i