diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 2d0cbad55..de16b47cb 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -710,11 +710,30 @@ fn read_device_map() -> DeviceMap { device_map } +fn toggle_sed_spread(val: u8) { + unsafe { csr::rtio_core::sed_spread_enable_write(val); } +} + +fn setup_sed_spread() { + config::read_str("sed_spread_enable", |r| { + match r { + Ok("1") => { info!("SED spreading enabled"); toggle_sed_spread(1); }, + Ok("0") => { info!("SED spreading disabled"); toggle_sed_spread(0); }, + Ok(_) => { + warn!("sed_spread_enable value not supported (only 1, 0 allowed), disabling by default"); + toggle_sed_spread(0); + }, + Err(_) => { info!("SED spreading disabled by default"); toggle_sed_spread(0) }, + } + }); +} + pub fn startup(io: &Io, aux_mutex: &Mutex, routing_table: &Urc>, up_destinations: &Urc>, ddma_mutex: &Mutex, subkernel_mutex: &Mutex) { set_device_map(read_device_map()); + setup_sed_spread(); drtio::startup(io, aux_mutex, routing_table, up_destinations, ddma_mutex, subkernel_mutex); unsafe { csr::rtio_core::reset_phy_write(1); diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 335c353df..c77d93a21 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -14,7 +14,7 @@ extern crate io; extern crate eh; use core::convert::TryFrom; -use board_misoc::{csr, ident, clock, uart_logger, i2c, pmp}; +use board_misoc::{csr, ident, clock, config, uart_logger, i2c, pmp}; #[cfg(has_si5324)] use board_artiq::si5324; #[cfg(has_si549)] @@ -70,6 +70,10 @@ fn drtiosat_tsc_loaded() -> bool { } } +fn toggle_sed_spread(val: u8) { + unsafe { csr::drtiosat::sed_spread_enable_write(val); } +} + #[derive(Clone, Copy)] pub enum RtioMaster { Drtio, @@ -754,6 +758,18 @@ pub extern fn main() -> i32 { init_rtio_crg(); + config::read_str("sed_spread_enable", |r| { + match r { + Ok("1") => { info!("SED spreading enabled"); toggle_sed_spread(1); }, + Ok("0") => { info!("SED spreading disabled"); toggle_sed_spread(0); }, + Ok(_) => { + warn!("sed_spread_enable value not supported (only 1, 0 allowed), disabling by default"); + toggle_sed_spread(0); + }, + Err(_) => { info!("SED spreading disabled by default"); toggle_sed_spread(0) }, + } + }); + #[cfg(has_drtio_eem)] drtio_eem::init(); diff --git a/artiq/gateware/drtio/core.py b/artiq/gateware/drtio/core.py index 8928f833e..9397ba313 100644 --- a/artiq/gateware/drtio/core.py +++ b/artiq/gateware/drtio/core.py @@ -1,6 +1,7 @@ from types import SimpleNamespace from migen import * +from migen.genlib.cdc import MultiReg from migen.genlib.resetsync import AsyncResetSynchronizer from misoc.interconnect.csr import * @@ -51,6 +52,7 @@ class SyncRTIO(Module): def __init__(self, tsc, channels, lane_count=8, fifo_depth=128): self.cri = cri.Interface() self.async_errors = Record(async_errors_layout) + self.sed_spread_enable = Signal() chan_fine_ts_width = max(max(rtlink.get_fine_ts_width(channel.interface.o) for channel in channels), @@ -61,10 +63,11 @@ class SyncRTIO(Module): self.submodules.outputs = ClockDomainsRenamer("rio")( SED(channels, tsc.glbl_fine_ts_width, lane_count=lane_count, fifo_depth=fifo_depth, - enable_spread=True, fifo_high_watermark=0.75, - report_buffer_space=True, interface=self.cri)) + fifo_high_watermark=0.75, report_buffer_space=True, + interface=self.cri)) self.comb += self.outputs.coarse_timestamp.eq(tsc.coarse_ts) self.sync += self.outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 16) + self.specials += MultiReg(self.sed_spread_enable, self.outputs.enable_spread, "rio") self.submodules.inputs = ClockDomainsRenamer("rio")( InputCollector(tsc, channels, interface=self.cri)) @@ -78,6 +81,7 @@ class DRTIOSatellite(Module): self.reset = CSRStorage(reset=1) self.reset_phy = CSRStorage(reset=1) self.tsc_loaded = CSR() + self.sed_spread_enable = CSRStorage() # master interface in the sys domain self.cri = cri.Interface() self.async_errors = Record(async_errors_layout) @@ -143,7 +147,7 @@ class DRTIOSatellite(Module): self.rt_packet, tsc, self.async_errors) def get_csrs(self): - return ([self.reset, self.reset_phy, self.tsc_loaded] + + return ([self.reset, self.sed_spread_enable, self.reset_phy, self.tsc_loaded] + self.link_layer.get_csrs() + self.link_stats.get_csrs() + self.rt_errors.get_csrs()) diff --git a/artiq/gateware/rtio/core.py b/artiq/gateware/rtio/core.py index 52012379d..fad45a85f 100644 --- a/artiq/gateware/rtio/core.py +++ b/artiq/gateware/rtio/core.py @@ -3,7 +3,7 @@ from operator import and_ from migen import * from migen.genlib.resetsync import AsyncResetSynchronizer -from migen.genlib.cdc import BlindTransfer +from migen.genlib.cdc import MultiReg, BlindTransfer from misoc.interconnect.csr import * from artiq.gateware.rtio import cri @@ -18,6 +18,7 @@ class Core(Module, AutoCSR): self.cri = cri.Interface() self.reset = CSR() self.reset_phy = CSR() + self.sed_spread_enable = CSRStorage() self.async_error = CSR(3) self.collision_channel = CSRStatus(16) self.busy_channel = CSRStatus(16) @@ -67,6 +68,7 @@ class Core(Module, AutoCSR): self.submodules += outputs self.comb += outputs.coarse_timestamp.eq(tsc.coarse_ts) self.sync += outputs.minimum_coarse_timestamp.eq(tsc.coarse_ts + 12) + self.specials += MultiReg(self.sed_spread_enable.storage, outputs.enable_spread, "rio") inputs = ClockDomainsRenamer("rio")(InputCollector(tsc, channels, quash_channels=quash_channels, diff --git a/artiq/gateware/rtio/sed/core.py b/artiq/gateware/rtio/sed/core.py index 32ed90996..b9703aef5 100644 --- a/artiq/gateware/rtio/sed/core.py +++ b/artiq/gateware/rtio/sed/core.py @@ -12,7 +12,7 @@ __all__ = ["SED"] class SED(Module): def __init__(self, channels, glbl_fine_ts_width, - lane_count=8, fifo_depth=128, fifo_high_watermark=1.0, enable_spread=True, + lane_count=8, fifo_depth=128, fifo_high_watermark=1.0, quash_channels=[], report_buffer_space=False, interface=None): seqn_width = layouts.seqn_width(lane_count, fifo_depth) @@ -23,7 +23,6 @@ class SED(Module): layouts.fifo_payload(channels), [channel.interface.o.delay for channel in channels], glbl_fine_ts_width, - enable_spread=enable_spread, quash_channels=quash_channels, interface=interface) self.submodules.fifos = FIFOs(lane_count, fifo_depth, fifo_high_watermark, @@ -47,6 +46,10 @@ class SED(Module): self.cri.o_buffer_space.eq(self.fifos.buffer_space) ] + @property + def enable_spread(self): + return self.lane_dist.enable_spread + @property def cri(self): return self.lane_dist.cri diff --git a/artiq/gateware/rtio/sed/lane_distributor.py b/artiq/gateware/rtio/sed/lane_distributor.py index f14010362..17073e641 100644 --- a/artiq/gateware/rtio/sed/lane_distributor.py +++ b/artiq/gateware/rtio/sed/lane_distributor.py @@ -10,7 +10,7 @@ __all__ = ["LaneDistributor"] class LaneDistributor(Module): def __init__(self, lane_count, seqn_width, layout_payload, compensation, glbl_fine_ts_width, - enable_spread=True, quash_channels=[], interface=None): + quash_channels=[], interface=None): if lane_count & (lane_count - 1): raise NotImplementedError("lane count must be a power of 2") @@ -28,6 +28,8 @@ class LaneDistributor(Module): self.output = [Record(layouts.fifo_ingress(seqn_width, layout_payload)) for _ in range(lane_count)] + self.enable_spread = Signal() + # # # o_status_wait = Signal() @@ -173,12 +175,11 @@ class LaneDistributor(Module): ] # current lane has reached high watermark, spread events by switching to the next. - if enable_spread: - self.sync += [ - If(current_lane_high_watermark | ~current_lane_writable, - force_laneB.eq(1) - ), - If(do_write, - force_laneB.eq(0) - ) - ] + self.sync += [ + If(self.enable_spread & (current_lane_high_watermark | ~current_lane_writable), + force_laneB.eq(1) + ), + If(do_write, + force_laneB.eq(0) + ) + ] diff --git a/artiq/gateware/targets/efc.py b/artiq/gateware/targets/efc.py index 5410eafa3..385e05479 100644 --- a/artiq/gateware/targets/efc.py +++ b/artiq/gateware/targets/efc.py @@ -217,7 +217,10 @@ class Satellite(BaseSoC, AMPSoC): # satellite (master-controlled) RTIO self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) + self.comb += [ + self.drtiosat.async_errors.eq(self.local_io.async_errors), + self.local_io.sed_spread_enable.eq(self.drtiosat.sed_spread_enable.storage) + ] # subkernel RTIO self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) diff --git a/artiq/gateware/targets/kasli.py b/artiq/gateware/targets/kasli.py index 0bdc50f28..af3db6a68 100755 --- a/artiq/gateware/targets/kasli.py +++ b/artiq/gateware/targets/kasli.py @@ -597,7 +597,10 @@ class SatelliteBase(BaseSoC, AMPSoC): # satellite (master-controlled) RTIO self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels, lane_count=sed_lanes) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) + self.comb += [ + self.drtiosat.async_errors.eq(self.local_io.async_errors), + self.local_io.sed_spread_enable.eq(self.drtiosat.sed_spread_enable.storage) + ] # subkernel RTIO self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 4200919ae..f7b951872 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -468,7 +468,10 @@ class _SatelliteBase(BaseSoC, AMPSoC): # DRTIO self.submodules.local_io = SyncRTIO(self.rtio_tsc, rtio_channels) - self.comb += self.drtiosat.async_errors.eq(self.local_io.async_errors) + self.comb += [ + self.drtiosat.async_errors.eq(self.local_io.async_errors), + self.local_io.sed_spread_enable.eq(self.drtiosat.sed_spread_enable.storage) + ] # subkernel RTIO self.submodules.rtio = rtio.KernelInitiator(self.rtio_tsc) diff --git a/artiq/gateware/test/rtio/test_sed_top.py b/artiq/gateware/test/rtio/test_sed_top.py index 5c5002fd3..20bf1f8ec 100644 --- a/artiq/gateware/test/rtio/test_sed_top.py +++ b/artiq/gateware/test/rtio/test_sed_top.py @@ -27,6 +27,7 @@ class DUT(Module): self.sed.coarse_timestamp.eq(self.sed.coarse_timestamp + 1), self.sed.minimum_coarse_timestamp.eq(self.sed.coarse_timestamp + 16) ] + self.comb += self.sed.enable_spread.eq(0) def simulate(input_events, **kwargs): @@ -110,6 +111,6 @@ class TestSED(unittest.TestCase): input_events += [(now, 1), (now, 0)] ttl_changes, access_results = simulate(input_events, - lane_count=2, fifo_depth=2, enable_spread=False) + lane_count=2, fifo_depth=2) self.assertEqual([r[0] for r in access_results], ["ok"]*len(input_events)) self.assertEqual(ttl_changes, list(range(40, 40+40*20, 10)))