From 03d9827a5a53d04f791b9acf2aeff6e2b71cb623 Mon Sep 17 00:00:00 2001 From: pca006132 Date: Wed, 9 Sep 2020 21:02:39 +0800 Subject: [PATCH] acpki: working --- src/gateware/acpki.py | 26 ++++++++--- src/runtime/src/rtio_acp.rs | 91 ++++++++++++++++++++++++++----------- 2 files changed, 83 insertions(+), 34 deletions(-) diff --git a/src/gateware/acpki.py b/src/gateware/acpki.py index 4f665235..1f226ab8 100644 --- a/src/gateware/acpki.py +++ b/src/gateware/acpki.py @@ -7,8 +7,7 @@ from misoc.interconnect.csr import * from artiq.gateware import rtio - -OUT_BURST_LEN = 4 +OUT_BURST_LEN = 10 IN_BURST_LEN = 4 @@ -98,7 +97,7 @@ class Engine(Module, AutoCSR): ### Write self.comb += [ w.data.eq(self.din), - aw.addr.eq(self.addr_base.storage+32), # Write to next cache line + aw.addr.eq(self.addr_base.storage+96), w.strb.eq(0xff), aw.burst.eq(axi.Burst.incr.value), aw.len.eq(IN_BURST_LEN-1), # Number of transfers in burst minus 1 @@ -191,22 +190,31 @@ class KernelInitiator(Module, AutoCSR): cmd_read.eq(cmd == 1) ] + out_len = Signal(8) dout_cases = {} dout_cases[0] = [ cmd.eq(self.engine.dout[:8]), + out_len.eq(self.engine.dout[8:16]), cri.chan_sel.eq(self.engine.dout[40:]), cri.o_address.eq(self.engine.dout[32:40]) ] + for i in range(8): + target = cri.o_data[i*64:(i+1)*64] + dout_cases[0] += [If(i >= self.engine.dout[8:16], target.eq(0))] + dout_cases[1] = [ - cri.o_timestamp.eq(self.engine.dout) + cri.o_timestamp.eq(self.engine.dout), + cri.i_timeout.eq(self.engine.dout) ] - dout_cases[2] = [cri.o_data.eq(self.engine.dout)] # only lowest 64 bits + for i in range(8): + target = cri.o_data[i*64:(i+1)*64] + dout_cases[i+2] = [target.eq(self.engine.dout)] self.sync += [ cri.cmd.eq(rtio.cri.commands["nop"]), If(self.engine.dout_stb, Case(self.engine.dout_index, dout_cases), - If(self.engine.dout_index == 2, + If(self.engine.dout_index == out_len + 2, If(cmd_write, cri.cmd.eq(rtio.cri.commands["write"])), If(cmd_read, cri.cmd.eq(rtio.cri.commands["read"])) ) @@ -226,7 +234,11 @@ class KernelInitiator(Module, AutoCSR): ) fsm.act("WAIT_OUT_CYCLE", self.engine.din_ready.eq(0), - If(self.engine.dout_stb & (self.engine.dout_index == 3), + If(self.engine.dout_stb & cmd_write & (self.engine.dout_index == out_len + 2), + NextState("WAIT_READY") + ), + # for some reason read requires some delay until the next state + If(self.engine.dout_stb & cmd_read & (self.engine.dout_index == out_len + 3), NextState("WAIT_READY") ) ) diff --git a/src/runtime/src/rtio_acp.rs b/src/runtime/src/rtio_acp.rs index 7cc0b6e4..f7987e1e 100644 --- a/src/runtime/src/rtio_acp.rs +++ b/src/runtime/src/rtio_acp.rs @@ -1,8 +1,8 @@ use cslice::CSlice; use vcell::VolatileCell; use libcortex_a9::asm; - use crate::artiq_raise; +use core::sync::atomic::{fence, Ordering}; use crate::pl::csr; @@ -20,33 +20,33 @@ pub struct TimestampedData { data: i32, } -#[repr(C, align(32))] +#[repr(C, align(64))] struct Transaction { request_cmd: i8, - padding0: i8, - padding1: i8, - padding2: i8, + data_width: i8, + padding0: [i8; 2], request_target: i32, request_timestamp: i64, - request_data: i64, - padding: i64, + request_data: [i32; 16], + padding1: [i64; 2], reply_status: VolatileCell, reply_data: VolatileCell, - reply_timestamp: VolatileCell + reply_timestamp: VolatileCell, + padding2: [i64; 2], } static mut TRANSACTION_BUFFER: Transaction = Transaction { request_cmd: 0, - padding0: 0, - padding1: 0, - padding2: 0, + data_width: 0, request_target: 0, request_timestamp: 0, - request_data: 0, - padding: 0, + request_data: [0; 16], reply_status: VolatileCell::new(0), reply_data: VolatileCell::new(0), - reply_timestamp: VolatileCell::new(0) + reply_timestamp: VolatileCell::new(0), + padding0: [0; 2], + padding1: [0; 2], + padding2: [0; 2] }; pub extern fn init() { @@ -108,13 +108,41 @@ pub extern fn output(target: i32, data: i32) { TRANSACTION_BUFFER.reply_status.set(0); TRANSACTION_BUFFER.request_cmd = 0; + TRANSACTION_BUFFER.data_width = 1; TRANSACTION_BUFFER.request_target = target; TRANSACTION_BUFFER.request_timestamp = NOW; - TRANSACTION_BUFFER.request_data = data as i64; + TRANSACTION_BUFFER.request_data[0] = data; - asm::dmb(); + fence(Ordering::SeqCst); asm::sev(); + let mut status; + loop { + status = TRANSACTION_BUFFER.reply_status.get(); + if status != 0 { + break; + } + } + let status = status & !0x10000; + if status != 0 { + process_exceptional_status(target >> 8, status); + } + } +} + +pub extern fn output_wide(target: i32, data: CSlice) { + unsafe { + // Clear status so we can observe response + TRANSACTION_BUFFER.reply_status.set(0); + + TRANSACTION_BUFFER.request_cmd = 0; + TRANSACTION_BUFFER.data_width = data.len() as i8; + TRANSACTION_BUFFER.request_target = target; + TRANSACTION_BUFFER.request_timestamp = NOW; + TRANSACTION_BUFFER.request_data[..data.len()].copy_from_slice(data.as_ref()); + + fence(Ordering::SeqCst); + asm::sev(); let mut status; loop { status = TRANSACTION_BUFFER.reply_status.get(); @@ -130,21 +158,17 @@ pub extern fn output(target: i32, data: i32) { } } -pub extern fn output_wide(target: i32, data: CSlice) { - // TODO - unimplemented!(); -} - pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { unsafe { // Clear status so we can observe response TRANSACTION_BUFFER.reply_status.set(0); TRANSACTION_BUFFER.request_cmd = 1; - TRANSACTION_BUFFER.request_timestamp = NOW; + TRANSACTION_BUFFER.request_timestamp = timeout; TRANSACTION_BUFFER.request_target = channel << 8; + TRANSACTION_BUFFER.data_width = 0; - asm::dmb(); + fence(Ordering::SeqCst); asm::sev(); let mut status; @@ -180,8 +204,9 @@ pub extern fn input_data(channel: i32) -> i32 { TRANSACTION_BUFFER.request_cmd = 1; TRANSACTION_BUFFER.request_timestamp = -1; TRANSACTION_BUFFER.request_target = channel << 8; + TRANSACTION_BUFFER.data_width = 0; - asm::dmb(); + fence(Ordering::SeqCst); asm::sev(); let mut status; @@ -214,8 +239,9 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD TRANSACTION_BUFFER.request_cmd = 1; TRANSACTION_BUFFER.request_timestamp = timeout; TRANSACTION_BUFFER.request_target = channel << 8; + TRANSACTION_BUFFER.data_width = 0; - asm::dmb(); + fence(Ordering::SeqCst); asm::sev(); let mut status; @@ -245,6 +271,17 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD } pub fn write_log(data: &[i8]) { - // TODO - unimplemented!(); + let mut word: u32 = 0; + for i in 0..data.len() { + word <<= 8; + word |= data[i] as u32; + if i % 4 == 3 { + output((csr::CONFIG_RTIO_LOG_CHANNEL << 8) as i32, word as i32); + word = 0; + } + } + + if word != 0 { + output((csr::CONFIG_RTIO_LOG_CHANNEL << 8) as i32, word as i32); + } }