From a894f9a46f68ffb9e06b0cd3c4560294c6387026 Mon Sep 17 00:00:00 2001 From: Yichao Yu Date: Mon, 17 Mar 2025 14:44:57 -0400 Subject: [PATCH] Support unaligned DMA buffer address Split the base address into an aligned part and an offset. Add one cycle to the start of the DMA playback to skip ahead to the real start of the playback. --- artiq/firmware/ksupport/lib.rs | 2 -- artiq/gateware/rtio/dma.py | 22 +++++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 6766f49982..7dff4417f9 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -396,8 +396,6 @@ extern "C-unwind" fn dma_retrieve(name: &CSlice) -> DmaTrace { #[cfg(kernel_has_rtio_dma)] extern "C-unwind" fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) { - assert!(ptr % 64 == 0); - unsafe { csr::rtio_dma::base_address_write(ptr as u64); csr::rtio_dma::time_offset_write(timestamp as u64); diff --git a/artiq/gateware/rtio/dma.py b/artiq/gateware/rtio/dma.py index 2c98951526..5e0641790e 100644 --- a/artiq/gateware/rtio/dma.py +++ b/artiq/gateware/rtio/dma.py @@ -82,6 +82,7 @@ def __init__(self, membus, enable, cpu_dw): # All numbers in bytes self.base_address = CSRStorage(aw + data_alignment, alignment_bits=data_alignment) + self.base_skip = Signal(data_alignment) # # # @@ -90,7 +91,8 @@ def __init__(self, membus, enable, cpu_dw): self.sync += [ enable_r.eq(enable), If(enable & ~enable_r, - address.address.eq(self.base_address.storage), + address.address.eq(self.base_address.storage[:-data_alignment]), + self.base_skip.eq(self.base_address.storage[-data_alignment:]), address.eop.eq(0), address.stb.eq(1), ), @@ -180,7 +182,7 @@ def __init__(self, in_size, out_size, granularity): class RecordConverter(Module): - def __init__(self, stream_slicer): + def __init__(self, stream_slicer, base_skip): self.source = stream.Endpoint(record_layout) self.end_marker_found = Signal() self.flush = Signal() @@ -197,9 +199,15 @@ def __init__(self, stream_slicer): for i in range(1, 512//8+1)}), ] - fsm = FSM(reset_state="FLOWING") + fsm = FSM(reset_state="START") self.submodules += fsm + fsm.act("START", + If(stream_slicer.source_stb, + stream_slicer.source_consume.eq(base_skip), + NextState("FLOWING") + ) + ) fsm.act("FLOWING", If(stream_slicer.source_stb, If(record_raw.length == 0, @@ -227,15 +235,15 @@ def __init__(self, stream_slicer): fsm.act("SEND_EOP", self.source.eop.eq(1), self.source.stb.eq(1), - If(self.source.ack, NextState("FLOWING")) + If(self.source.ack, NextState("START")) ) class RecordSlicer(Module): - def __init__(self, in_size): + def __init__(self, in_size, base_skip): self.submodules.raw_slicer = ResetInserter()(RawSlicer( in_size//8, layout_len(record_layout)//8, 8)) - self.submodules.record_converter = RecordConverter(self.raw_slicer) + self.submodules.record_converter = RecordConverter(self.raw_slicer, base_skip) self.end_marker_found = self.record_converter.end_marker_found self.flush = self.record_converter.flush @@ -359,7 +367,7 @@ def __init__(self, membus, cpu_dw): self.submodules.dma = DMAReader(membus, flow_enable, cpu_dw) self.submodules.fifo = stream.SyncFIFO( [("data", len(membus.dat_w))], 128, True, lo_wm=64) - self.submodules.slicer = RecordSlicer(len(membus.dat_w)) + self.submodules.slicer = RecordSlicer(len(membus.dat_w), self.dma.base_skip) self.submodules.time_offset = TimeOffset() self.submodules.cri_master = CRIMaster() self.cri = self.cri_master.cri