runtime/rtio_acp: working

This commit is contained in:
pca006132 2020-08-11 12:49:30 +08:00
parent 7342736124
commit d12bf11de1
3 changed files with 82 additions and 33 deletions

View File

@ -7,8 +7,7 @@ from misoc.interconnect.csr import *
from artiq.gateware import rtio from artiq.gateware import rtio
OUT_BURST_LEN = 10
OUT_BURST_LEN = 4
IN_BURST_LEN = 4 IN_BURST_LEN = 4
@ -98,7 +97,7 @@ class Engine(Module, AutoCSR):
### Write ### Write
self.comb += [ self.comb += [
w.data.eq(self.din), 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), w.strb.eq(0xff),
aw.burst.eq(axi.Burst.incr.value), aw.burst.eq(axi.Burst.incr.value),
aw.len.eq(IN_BURST_LEN-1), # Number of transfers in burst minus 1 aw.len.eq(IN_BURST_LEN-1), # Number of transfers in burst minus 1
@ -178,7 +177,7 @@ class KernelInitiator(Module, AutoCSR):
evento_latched = Signal() evento_latched = Signal()
evento_latched_d = Signal() evento_latched_d = Signal()
self.specials += MultiReg(evento, evento_latched) self.specials += MultiReg(evento, evento_latched)
self.sync += evento_latched_d.eq(evento_latched) self.sync += [evento_latched_d.eq(evento_latched)]
self.comb += self.engine.trigger_stb.eq(self.enable.storage & (evento_latched != evento_latched_d)) self.comb += self.engine.trigger_stb.eq(self.enable.storage & (evento_latched != evento_latched_d))
cri = self.cri cri = self.cri
@ -191,16 +190,24 @@ class KernelInitiator(Module, AutoCSR):
cmd_read.eq(cmd == 1) cmd_read.eq(cmd == 1)
] ]
out_len = Signal(8)
dout_cases = {} dout_cases = {}
dout_cases[0] = [ dout_cases[0] = [
cmd.eq(self.engine.dout[:8]), cmd.eq(self.engine.dout[:8]),
out_len.eq(self.engine.dout[8:16]),
cri.chan_sel.eq(self.engine.dout[40:]), cri.chan_sel.eq(self.engine.dout[40:]),
cri.o_address.eq(self.engine.dout[32: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] = [ dout_cases[1] = [
cri.o_timestamp.eq(self.engine.dout) cri.o_timestamp.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 += [ self.sync += [
cri.cmd.eq(rtio.cri.commands["nop"]), cri.cmd.eq(rtio.cri.commands["nop"]),
@ -226,7 +233,7 @@ class KernelInitiator(Module, AutoCSR):
) )
fsm.act("WAIT_OUT_CYCLE", fsm.act("WAIT_OUT_CYCLE",
self.engine.din_ready.eq(0), self.engine.din_ready.eq(0),
If(self.engine.dout_stb & (self.engine.dout_index == 3), If(self.engine.dout_stb & (self.engine.dout_index == out_len + 2),
NextState("WAIT_READY") NextState("WAIT_READY")
) )
) )

View File

@ -14,7 +14,7 @@ use libcortex_a9::{
use libboard_zynq::{mpcore, gic}; use libboard_zynq::{mpcore, gic};
use libsupport_zynq::ram; use libsupport_zynq::ram;
use dyld::{self, Library}; use dyld::{self, Library};
use crate::eh_artiq; use crate::{eh_artiq, rtio};
use super::{ use super::{
api::resolve, api::resolve,
rpc::rpc_send_async, rpc::rpc_send_async,
@ -151,6 +151,12 @@ pub fn main_core1() {
INIT_LOCK.lock(); INIT_LOCK.lock();
core0_tx.reset(); core0_tx.reset();
core1_tx.reset(); core1_tx.reset();
if !KERNEL_IMAGE.is_null() {
// indicates forceful termination of previous kernel
KERNEL_IMAGE = core::ptr::null();
debug!("rtio init");
rtio::init();
}
dma::init_dma_recorder(); dma::init_dma_recorder();
} }
*CHANNEL_0TO1.lock() = Some(core0_tx); *CHANNEL_0TO1.lock() = Some(core0_tx);

View File

@ -1,8 +1,9 @@
use cslice::CSlice; use cslice::{CSlice, AsCSlice};
use vcell::VolatileCell; use vcell::VolatileCell;
use libcortex_a9::asm; use libcortex_a9::{asm, cache::dcci};
use log::debug;
use crate::artiq_raise; use crate::artiq_raise;
use core::sync::atomic::{fence, Ordering};
use crate::pl::csr; use crate::pl::csr;
@ -20,33 +21,33 @@ pub struct TimestampedData {
data: i32, data: i32,
} }
#[repr(C, align(32))] #[repr(C, align(64))]
struct Transaction { struct Transaction {
request_cmd: i8, request_cmd: i8,
padding0: i8, data_width: i8,
padding1: i8, padding0: [i8; 2],
padding2: i8,
request_target: i32, request_target: i32,
request_timestamp: i64, request_timestamp: i64,
request_data: i64, request_data: [i32; 16],
padding: i64, padding1: [i64; 2],
reply_status: VolatileCell<i32>, reply_status: VolatileCell<i32>,
reply_data: VolatileCell<i32>, reply_data: VolatileCell<i32>,
reply_timestamp: VolatileCell<i64> reply_timestamp: VolatileCell<i64>,
padding2: [i64; 2],
} }
static mut TRANSACTION_BUFFER: Transaction = Transaction { static mut TRANSACTION_BUFFER: Transaction = Transaction {
request_cmd: 0, request_cmd: 0,
padding0: 0, data_width: 0,
padding1: 0,
padding2: 0,
request_target: 0, request_target: 0,
request_timestamp: 0, request_timestamp: 0,
request_data: 0, request_data: [0; 16],
padding: 0,
reply_status: VolatileCell::new(0), reply_status: VolatileCell::new(0),
reply_data: 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() { pub extern fn init() {
@ -54,6 +55,8 @@ pub extern fn init() {
csr::rtio_core::reset_write(1); csr::rtio_core::reset_write(1);
csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32); csr::rtio::engine_addr_base_write(&TRANSACTION_BUFFER as *const Transaction as u32);
csr::rtio::enable_write(1); csr::rtio::enable_write(1);
debug!("Set reply status");
TRANSACTION_BUFFER.reply_status.set(0x1000);
} }
} }
@ -104,17 +107,40 @@ unsafe fn process_exceptional_status(channel: i32, status: i32) {
pub extern fn output(target: i32, data: i32) { pub extern fn output(target: i32, data: i32) {
unsafe { unsafe {
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);
}
// Clear status so we can observe response // Clear status so we can observe response
TRANSACTION_BUFFER.reply_status.set(0); TRANSACTION_BUFFER.reply_status.set(0);
// volatile are not used temporarily to allow the compiler to optimize better...
// probably would use it back later.
TRANSACTION_BUFFER.request_cmd = 0; TRANSACTION_BUFFER.request_cmd = 0;
TRANSACTION_BUFFER.data_width = 1;
TRANSACTION_BUFFER.request_target = target; TRANSACTION_BUFFER.request_target = target;
TRANSACTION_BUFFER.request_timestamp = NOW; 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(); asm::sev();
dcci(&TRANSACTION_BUFFER.reply_status);
// asm::wfe();
// optimize cache...
// asm::wfe();
}
}
pub extern fn output_wide(target: i32, data: CSlice<i32>) {
unsafe {
let mut status; let mut status;
loop { loop {
status = TRANSACTION_BUFFER.reply_status.get(); status = TRANSACTION_BUFFER.reply_status.get();
@ -127,12 +153,19 @@ pub extern fn output(target: i32, data: i32) {
if status != 0 { if status != 0 {
process_exceptional_status(target >> 8, status); process_exceptional_status(target >> 8, status);
} }
} // Clear status so we can observe response
} TRANSACTION_BUFFER.reply_status.set(0);
pub extern fn output_wide(target: i32, data: CSlice<i32>) { TRANSACTION_BUFFER.request_cmd = 0;
// TODO TRANSACTION_BUFFER.data_width = data.len() as i8;
unimplemented!(); 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();
dcci(&TRANSACTION_BUFFER.reply_status);
}
} }
pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 { pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 {
@ -144,8 +177,9 @@ pub extern fn input_timestamp(timeout: i64, channel: i32) -> i64 {
TRANSACTION_BUFFER.request_timestamp = NOW; TRANSACTION_BUFFER.request_timestamp = NOW;
TRANSACTION_BUFFER.request_target = channel << 8; TRANSACTION_BUFFER.request_target = channel << 8;
asm::dmb(); fence(Ordering::SeqCst);
asm::sev(); asm::sev();
dcci(&TRANSACTION_BUFFER.reply_status);
let mut status; let mut status;
loop { loop {
@ -181,8 +215,9 @@ pub extern fn input_data(channel: i32) -> i32 {
TRANSACTION_BUFFER.request_timestamp = -1; TRANSACTION_BUFFER.request_timestamp = -1;
TRANSACTION_BUFFER.request_target = channel << 8; TRANSACTION_BUFFER.request_target = channel << 8;
asm::dmb(); fence(Ordering::SeqCst);
asm::sev(); asm::sev();
dcci(&TRANSACTION_BUFFER.reply_status);
let mut status; let mut status;
loop { loop {
@ -215,8 +250,9 @@ pub extern fn input_timestamped_data(timeout: i64, channel: i32) -> TimestampedD
TRANSACTION_BUFFER.request_timestamp = timeout; TRANSACTION_BUFFER.request_timestamp = timeout;
TRANSACTION_BUFFER.request_target = channel << 8; TRANSACTION_BUFFER.request_target = channel << 8;
asm::dmb(); fence(Ordering::SeqCst);
asm::sev(); asm::sev();
dcci(&TRANSACTION_BUFFER.reply_status);
let mut status; let mut status;
loop { loop {