forked from M-Labs/artiq
gateware,runtime: optimize RTIO kernel interface further
* now pinning (TODO: atomicity) * for inputs, merge request and timeout registers
This commit is contained in:
parent
aadf5112b7
commit
8caea0e6d3
@ -1946,8 +1946,7 @@ class ARTIQIRGenerator(algorithm.Visitor):
|
||||
def printf(format_string, *args):
|
||||
format = ir.Constant(format_string, builtins.TStr())
|
||||
if as_rtio:
|
||||
now_mu = self.append(ir.Builtin("now_mu", [], builtins.TInt64()))
|
||||
self.append(ir.Builtin("rtio_log", [now_mu, format, *args], builtins.TNone()))
|
||||
self.append(ir.Builtin("rtio_log", [format, *args], builtins.TNone()))
|
||||
else:
|
||||
self.append(ir.Builtin("printf", [format, *args], builtins.TNone()))
|
||||
|
||||
|
@ -336,7 +336,7 @@ class LLVMIRGenerator:
|
||||
elif name == self.target.print_function:
|
||||
llty = ll.FunctionType(llvoid, [llptr], var_arg=True)
|
||||
elif name == "rtio_log":
|
||||
llty = ll.FunctionType(llvoid, [lli64, llptr], var_arg=True)
|
||||
llty = ll.FunctionType(llvoid, [llptr], var_arg=True)
|
||||
elif name == "__artiq_personality":
|
||||
llty = ll.FunctionType(lli32, [], var_arg=True)
|
||||
elif name == "__artiq_raise":
|
||||
@ -1137,7 +1137,7 @@ class LLVMIRGenerator:
|
||||
lloperands = []
|
||||
for i, operand in enumerate(insn.operands):
|
||||
lloperand = self.map(operand)
|
||||
if i == 0 and insn.op == "printf" or i == 1 and insn.op == "rtio_log":
|
||||
if i == 0 and (insn.op == "printf" or insn.op == "rtio_log"):
|
||||
lloperands.append(self.llbuilder.extract_value(lloperand, 0))
|
||||
elif builtins.is_str(operand.type) or builtins.is_bytes(operand.type):
|
||||
lloperands.append(self.llbuilder.extract_value(lloperand, 1))
|
||||
|
@ -3,13 +3,12 @@ from artiq.language.types import TInt64, TInt32, TNone, TList
|
||||
|
||||
|
||||
@syscall(flags={"nowrite"})
|
||||
def rtio_output(time_mu: TInt64, target: TInt32, data: TInt32) -> TNone:
|
||||
def rtio_output(target: TInt32, data: TInt32) -> TNone:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
@syscall(flags={"nowrite"})
|
||||
def rtio_output_wide(time_mu: TInt64, target: TInt32,
|
||||
data: TList(TInt32)) -> TNone:
|
||||
def rtio_output_wide(target: TInt32, data: TList(TInt32)) -> TNone:
|
||||
raise NotImplementedError("syscall not simulated")
|
||||
|
||||
|
||||
|
@ -42,7 +42,7 @@ class TTLOut:
|
||||
|
||||
@kernel
|
||||
def set_o(self, o):
|
||||
rtio_output(now_mu(), self.target_o, 1 if o else 0)
|
||||
rtio_output(self.target_o, 1 if o else 0)
|
||||
|
||||
@kernel
|
||||
def on(self):
|
||||
@ -120,7 +120,7 @@ class TTLInOut:
|
||||
|
||||
@kernel
|
||||
def set_oe(self, oe):
|
||||
rtio_output(now_mu(), self.target_oe, 1 if oe else 0)
|
||||
rtio_output(self.target_oe, 1 if oe else 0)
|
||||
|
||||
@kernel
|
||||
def output(self):
|
||||
@ -142,7 +142,7 @@ class TTLInOut:
|
||||
|
||||
@kernel
|
||||
def set_o(self, o):
|
||||
rtio_output(now_mu(), self.target_o, 1 if o else 0)
|
||||
rtio_output(self.target_o, 1 if o else 0)
|
||||
|
||||
@kernel
|
||||
def on(self):
|
||||
@ -187,7 +187,7 @@ class TTLInOut:
|
||||
# Input API: gating
|
||||
@kernel
|
||||
def _set_sensitivity(self, value):
|
||||
rtio_output(now_mu(), self.target_sens, value)
|
||||
rtio_output(self.target_sens, value)
|
||||
|
||||
@kernel
|
||||
def gate_rising_mu(self, duration):
|
||||
@ -361,7 +361,7 @@ class TTLInOut:
|
||||
position of the time cursor.
|
||||
|
||||
The time cursor is not modified by this function."""
|
||||
rtio_output(now_mu(), self.target_sample, 0)
|
||||
rtio_output(self.target_sample, 0)
|
||||
|
||||
@kernel
|
||||
def sample_get(self):
|
||||
@ -398,13 +398,13 @@ class TTLInOut:
|
||||
|
||||
The time cursor is not modified by this function.
|
||||
"""
|
||||
rtio_output(now_mu(), self.target_sample, 2) # gate falling
|
||||
rtio_output(self.target_sample, 2) # gate falling
|
||||
return rtio_input_data(self.channel) == 1
|
||||
|
||||
@kernel
|
||||
def watch_stay_off(self):
|
||||
"""Like :meth:`watch_stay_on`, but for low levels."""
|
||||
rtio_output(now_mu(), self.target_sample, 1) # gate rising
|
||||
rtio_output(self.target_sample, 1) # gate rising
|
||||
return rtio_input_data(self.channel) == 0
|
||||
|
||||
@kernel
|
||||
@ -417,7 +417,7 @@ class TTLInOut:
|
||||
The time cursor is not modified by this function. This function
|
||||
always makes the slack negative.
|
||||
"""
|
||||
rtio_output(now_mu(), self.target_sens, 0)
|
||||
rtio_output(self.target_sens, 0)
|
||||
success = True
|
||||
try:
|
||||
while rtio_input_timestamp(now_mu(), self.channel) != -1:
|
||||
@ -479,7 +479,7 @@ class TTLClockGen:
|
||||
Due to the way the clock generator operates, frequency tuning words
|
||||
that are not powers of two cause jitter of one RTIO clock cycle at the
|
||||
output."""
|
||||
rtio_output(now_mu(), self.target, frequency)
|
||||
rtio_output(self.target, frequency)
|
||||
|
||||
@kernel
|
||||
def set(self, frequency):
|
||||
|
@ -1,3 +1,5 @@
|
||||
use board_misoc::csr;
|
||||
|
||||
macro_rules! api {
|
||||
($i:ident) => ({
|
||||
extern { static $i: u8; }
|
||||
@ -78,7 +80,7 @@ static mut API: &'static [(&'static str, *const ())] = &[
|
||||
/* proxified syscalls */
|
||||
api!(core_log),
|
||||
|
||||
api!(now = &::NOW as *const _),
|
||||
api!(now = csr::rtio::NOW_HI_ADDR as *const _),
|
||||
|
||||
api!(watchdog_set = ::watchdog_set),
|
||||
api!(watchdog_clear = ::watchdog_clear),
|
||||
|
@ -12,7 +12,7 @@ struct slice {
|
||||
};
|
||||
|
||||
void send_to_core_log(struct slice str);
|
||||
void send_to_rtio_log(long long int timestamp, struct slice data);
|
||||
void send_to_rtio_log(struct slice data);
|
||||
|
||||
#define KERNELCPU_EXEC_ADDRESS 0x40800000
|
||||
#define KERNELCPU_PAYLOAD_ADDRESS 0x40840000
|
||||
@ -139,8 +139,8 @@ int core_log(const char *fmt, ...)
|
||||
}
|
||||
|
||||
/* called by kernel */
|
||||
void rtio_log(long long int timestamp, const char *fmt, ...);
|
||||
void rtio_log(long long int timestamp, const char *fmt, ...)
|
||||
void rtio_log(const char *fmt, ...);
|
||||
void rtio_log(const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
@ -154,5 +154,5 @@ void rtio_log(long long int timestamp, const char *fmt, ...)
|
||||
va_end(args);
|
||||
|
||||
struct slice str = { buf, size };
|
||||
send_to_rtio_log(timestamp, str);
|
||||
send_to_rtio_log(str);
|
||||
}
|
||||
|
@ -99,7 +99,6 @@ mod api;
|
||||
mod rtio;
|
||||
mod nrt_bus;
|
||||
|
||||
static mut NOW: u64 = 0;
|
||||
static mut LIBRARY: Option<Library<'static>> = None;
|
||||
|
||||
#[no_mangle]
|
||||
@ -114,8 +113,8 @@ pub extern fn send_to_core_log(text: CSlice<u8>) {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn send_to_rtio_log(timestamp: i64, text: CSlice<u8>) {
|
||||
rtio::log(timestamp, text.as_ref())
|
||||
pub extern fn send_to_rtio_log(text: CSlice<u8>) {
|
||||
rtio::log(text.as_ref())
|
||||
}
|
||||
|
||||
#[unwind(aborts)]
|
||||
@ -184,7 +183,6 @@ fn terminate(exception: &eh_artiq::Exception, backtrace: &mut [usize]) -> ! {
|
||||
}
|
||||
let backtrace = &mut backtrace.as_mut()[0..cursor];
|
||||
|
||||
send(&NowSave(unsafe { NOW }));
|
||||
send(&RunException {
|
||||
exception: kernel_proto::Exception {
|
||||
name: str::from_utf8(exception.name.as_ref()).unwrap(),
|
||||
@ -508,10 +506,7 @@ pub unsafe fn main() {
|
||||
|
||||
ptr::write_bytes(__bss_start as *mut u8, 0, (_end - __bss_start) as usize);
|
||||
|
||||
send(&NowInitRequest);
|
||||
recv!(&NowInitReply(now) => NOW = now);
|
||||
(mem::transmute::<u32, fn()>(__modinit__))();
|
||||
send(&NowSave(NOW));
|
||||
|
||||
if let Some(typeinfo) = typeinfo {
|
||||
attribute_writeback(typeinfo as *const ());
|
||||
|
@ -51,7 +51,8 @@ mod imp {
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
unsafe fn process_exceptional_status(timestamp: i64, channel: i32, status: u8) {
|
||||
unsafe fn process_exceptional_status(channel: i32, status: u8) {
|
||||
let timestamp = *(csr::rtio::NOW_HI_ADDR as *const i64);
|
||||
if status & RTIO_O_STATUS_WAIT != 0 {
|
||||
while csr::rtio::o_status_read() & RTIO_O_STATUS_WAIT != 0 {}
|
||||
}
|
||||
@ -67,30 +68,28 @@ mod imp {
|
||||
}
|
||||
}
|
||||
|
||||
pub extern fn output(timestamp: i64, target: i32, data: i32) {
|
||||
pub extern fn output(target: i32, data: i32) {
|
||||
unsafe {
|
||||
csr::rtio::target_write(target as u32);
|
||||
// writing timestamp clears o_data
|
||||
csr::rtio::timestamp_write(timestamp as u64);
|
||||
// writing target clears o_data
|
||||
rtio_o_data_write(0, data as _);
|
||||
let status = csr::rtio::o_status_read();
|
||||
if status != 0 {
|
||||
process_exceptional_status(timestamp, target >> 8, status);
|
||||
process_exceptional_status(target >> 8, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub extern fn output_wide(timestamp: i64, target: i32, data: CSlice<i32>) {
|
||||
pub extern fn output_wide(target: i32, data: CSlice<i32>) {
|
||||
unsafe {
|
||||
csr::rtio::target_write(target as u32);
|
||||
// writing timestamp clears o_data
|
||||
csr::rtio::timestamp_write(timestamp as u64);
|
||||
// writing target clears o_data
|
||||
for i in 0..data.len() {
|
||||
rtio_o_data_write(i, data[i] as _)
|
||||
}
|
||||
let status = csr::rtio::o_status_read();
|
||||
if status != 0 {
|
||||
process_exceptional_status(timestamp, target >> 8, status);
|
||||
process_exceptional_status(target >> 8, status);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -98,8 +97,7 @@ mod imp {
|
||||
pub extern fn input_timestamp(timeout: i64, channel: i32) -> u64 {
|
||||
unsafe {
|
||||
csr::rtio::target_write((channel as u32) << 8);
|
||||
csr::rtio::timestamp_write(timeout as u64);
|
||||
csr::rtio::i_request_write(1);
|
||||
csr::rtio::i_timeout_write(timeout as u64);
|
||||
|
||||
let mut status = RTIO_I_STATUS_WAIT_STATUS;
|
||||
while status & RTIO_I_STATUS_WAIT_STATUS != 0 {
|
||||
@ -128,8 +126,7 @@ mod imp {
|
||||
pub extern fn input_data(channel: i32) -> i32 {
|
||||
unsafe {
|
||||
csr::rtio::target_write((channel as u32) << 8);
|
||||
csr::rtio::timestamp_write(0xffffffff_ffffffff);
|
||||
csr::rtio::i_request_write(1);
|
||||
csr::rtio::i_timeout_write(0xffffffff_ffffffff);
|
||||
|
||||
let mut status = RTIO_I_STATUS_WAIT_STATUS;
|
||||
while status & RTIO_I_STATUS_WAIT_STATUS != 0 {
|
||||
@ -153,10 +150,9 @@ mod imp {
|
||||
}
|
||||
|
||||
#[cfg(has_rtio_log)]
|
||||
pub fn log(timestamp: i64, data: &[u8]) {
|
||||
pub fn log(data: &[u8]) {
|
||||
unsafe {
|
||||
csr::rtio::target_write(csr::CONFIG_RTIO_LOG_CHANNEL << 8);
|
||||
csr::rtio::timestamp_write(timestamp as u64);
|
||||
|
||||
let mut word: u32 = 0;
|
||||
for i in 0..data.len() {
|
||||
@ -175,7 +171,7 @@ mod imp {
|
||||
}
|
||||
|
||||
#[cfg(not(has_rtio_log))]
|
||||
pub fn log(_timestamp: i64, _data: &[u8]) {
|
||||
pub fn log(_data: &[u8]) {
|
||||
unimplemented!("not(has_rtio_log)")
|
||||
}
|
||||
}
|
||||
|
@ -22,10 +22,6 @@ pub enum Message<'a> {
|
||||
LoadRequest(&'a [u8]),
|
||||
LoadReply(Result<(), dyld::Error<'a>>),
|
||||
|
||||
NowInitRequest,
|
||||
NowInitReply(u64),
|
||||
NowSave(u64),
|
||||
|
||||
RtioInitRequest,
|
||||
|
||||
RtioDestinationStatusRequest { destination: u8 },
|
||||
|
@ -63,7 +63,6 @@ macro_rules! unexpected {
|
||||
// Persistent state
|
||||
#[derive(Debug)]
|
||||
struct Congress {
|
||||
now: u64,
|
||||
cache: Cache,
|
||||
dma_manager: DmaManager,
|
||||
finished_cleanly: Cell<bool>
|
||||
@ -72,7 +71,6 @@ struct Congress {
|
||||
impl Congress {
|
||||
fn new() -> Congress {
|
||||
Congress {
|
||||
now: 0,
|
||||
cache: Cache::new(),
|
||||
dma_manager: DmaManager::new(),
|
||||
finished_cleanly: Cell::new(true)
|
||||
@ -365,14 +363,6 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
|
||||
kern_acknowledge()
|
||||
}
|
||||
|
||||
&kern::NowInitRequest =>
|
||||
kern_send(io, &kern::NowInitReply(session.congress.now)),
|
||||
|
||||
&kern::NowSave(now) => {
|
||||
session.congress.now = now;
|
||||
kern_acknowledge()
|
||||
}
|
||||
|
||||
&kern::DmaRecordStart(name) => {
|
||||
session.congress.dma_manager.record_start(name);
|
||||
kern_acknowledge()
|
||||
|
@ -73,7 +73,11 @@ class RTController(Module):
|
||||
rt_packet.sr_chan_sel.eq(chan_sel),
|
||||
rt_packet.sr_address.eq(self.cri.o_address),
|
||||
rt_packet.sr_data.eq(self.cri.o_data),
|
||||
rt_packet.sr_timestamp.eq(self.cri.timestamp),
|
||||
If(rt_packet_read_request,
|
||||
rt_packet.sr_timestamp.eq(self.cri.i_timeout)
|
||||
).Else(
|
||||
rt_packet.sr_timestamp.eq(self.cri.o_timestamp)
|
||||
),
|
||||
If(rt_packet_buffer_request,
|
||||
rt_packet.sr_notwrite.eq(1),
|
||||
rt_packet.sr_address.eq(0)
|
||||
@ -103,7 +107,7 @@ class RTController(Module):
|
||||
self.submodules += timeout_counter
|
||||
|
||||
cond_underflow = Signal()
|
||||
self.comb += cond_underflow.eq((self.cri.timestamp[tsc.glbl_fine_ts_width:]
|
||||
self.comb += cond_underflow.eq((self.cri.o_timestamp[tsc.glbl_fine_ts_width:]
|
||||
- self.csrs.underflow_margin.storage[tsc.glbl_fine_ts_width:]) < tsc.coarse_ts_sys)
|
||||
|
||||
# buffer space
|
||||
|
@ -61,7 +61,7 @@ class RTErrorsSatellite(Module, AutoCSR):
|
||||
underflow.eq(cri.o_status[1]),
|
||||
overflow.eq(cri.o_status[0]),
|
||||
underflow_error_cri.eq(Cat(cri.chan_sel[:16],
|
||||
cri.timestamp,
|
||||
cri.o_timestamp,
|
||||
tsc.full_ts_cri)),
|
||||
Cat(self.underflow_channel.status,
|
||||
self.underflow_timestamp_event.status,
|
||||
|
@ -68,7 +68,11 @@ class RTPacketRepeater(Module):
|
||||
If(~self.reset & ~cb0_loaded & (self.cri.cmd != cri.commands["nop"]),
|
||||
cb0_loaded.eq(1),
|
||||
cb0_cmd.eq(self.cri.cmd),
|
||||
cb0_timestamp.eq(self.cri.timestamp),
|
||||
If(self.cri.cmd == cri.commands["read"],
|
||||
cb0_timestamp.eq(self.cri.i_timeout)
|
||||
).Else(
|
||||
cb0_timestamp.eq(self.cri.o_timestamp)
|
||||
),
|
||||
cb0_chan_sel.eq(self.cri.chan_sel),
|
||||
cb0_o_address.eq(self.cri.o_address),
|
||||
cb0_o_data.eq(self.cri.o_data)
|
||||
|
@ -94,13 +94,10 @@ class RTPacketSatellite(Module):
|
||||
self.cri.chan_sel.eq(
|
||||
rx_dp.packet_as["write"].chan_sel),
|
||||
),
|
||||
If(cri_read | read_request_pending,
|
||||
self.cri.timestamp.eq(
|
||||
rx_dp.packet_as["read_request"].timeout)
|
||||
).Else(
|
||||
self.cri.timestamp.eq(
|
||||
rx_dp.packet_as["write"].timestamp)
|
||||
),
|
||||
self.cri.i_timeout.eq(
|
||||
rx_dp.packet_as["read_request"].timeout),
|
||||
self.cri.o_timestamp.eq(
|
||||
rx_dp.packet_as["write"].timestamp),
|
||||
self.cri.o_address.eq(
|
||||
rx_dp.packet_as["write"].address),
|
||||
self.cri.o_data.eq(
|
||||
|
@ -70,7 +70,7 @@ class MessageEncoder(Module, AutoCSR):
|
||||
input_output.rtio_counter.eq(tsc.full_ts_cri),
|
||||
If(cri.cmd == cri_commands["write"],
|
||||
input_output.message_type.eq(MessageType.output.value),
|
||||
input_output.timestamp.eq(cri.timestamp),
|
||||
input_output.timestamp.eq(cri.o_timestamp),
|
||||
input_output.data.eq(cri.o_data)
|
||||
).Else(
|
||||
input_output.message_type.eq(MessageType.input.value),
|
||||
|
@ -29,8 +29,8 @@ layout = [
|
||||
# 8 MSBs of chan_sel = routing destination
|
||||
# 16 LSBs of chan_sel = channel within the destination
|
||||
("chan_sel", 24, DIR_M_TO_S),
|
||||
("timestamp", 64, DIR_M_TO_S),
|
||||
|
||||
("o_timestamp", 64, DIR_M_TO_S),
|
||||
("o_data", 512, DIR_M_TO_S),
|
||||
("o_address", 8, DIR_M_TO_S),
|
||||
# o_status bits:
|
||||
@ -43,6 +43,7 @@ layout = [
|
||||
("o_buffer_space_valid", 1, DIR_S_TO_M),
|
||||
("o_buffer_space", 16, DIR_S_TO_M),
|
||||
|
||||
("i_timeout", 64, DIR_M_TO_S),
|
||||
("i_data", 32, DIR_S_TO_M),
|
||||
("i_timestamp", 64, DIR_S_TO_M),
|
||||
# i_status bits:
|
||||
@ -61,17 +62,19 @@ class Interface(Record):
|
||||
class KernelInitiator(Module, AutoCSR):
|
||||
def __init__(self, tsc, cri=None):
|
||||
self.target = CSRStorage(32)
|
||||
self.timestamp = CSRStorage(64)
|
||||
# not using CSRStorage atomic_write feature here to make storage reset_less
|
||||
self.now_hi = CSR(32)
|
||||
self.now_lo = CSR(32)
|
||||
|
||||
# Writing timestamp clears o_data. This implements automatic
|
||||
# Writing target clears o_data. This implements automatic
|
||||
# zero-extension of output event data by the gateware. When staging an
|
||||
# output event, always write timestamp before o_data.
|
||||
# output event, always write target before o_data.
|
||||
self.o_data = CSRStorage(512, write_from_dev=True)
|
||||
self.o_status = CSRStatus(3)
|
||||
|
||||
self.i_timeout = CSRStorage(64)
|
||||
self.i_data = CSRStatus(32)
|
||||
self.i_timestamp = CSRStatus(64)
|
||||
self.i_request = CSR()
|
||||
self.i_status = CSRStatus(4)
|
||||
self.i_overflow_reset = CSR()
|
||||
|
||||
@ -84,24 +87,39 @@ class KernelInitiator(Module, AutoCSR):
|
||||
|
||||
# # #
|
||||
|
||||
now_lo_backing = Signal(32)
|
||||
now = Signal(64, reset_less=True)
|
||||
self.sync += [
|
||||
# TODO: fix compiler and make atomic
|
||||
#If(self.now_lo.re, now_lo_backing.eq(self.now_lo.r)),
|
||||
#If(self.now_hi.re, now.eq(Cat(now_lo_backing, self.now_hi.r)))
|
||||
If(self.now_lo.re, now[:32].eq(self.now_lo.r)),
|
||||
If(self.now_hi.re, now[32:].eq(self.now_hi.r))
|
||||
]
|
||||
self.comb += [
|
||||
self.now_lo.w.eq(now[:32]),
|
||||
self.now_hi.w.eq(now[32:])
|
||||
]
|
||||
|
||||
self.comb += [
|
||||
self.cri.cmd.eq(commands["nop"]),
|
||||
If(self.o_data.re, self.cri.cmd.eq(commands["write"])),
|
||||
If(self.i_request.re, self.cri.cmd.eq(commands["read"])),
|
||||
If(self.i_timeout.re, self.cri.cmd.eq(commands["read"])),
|
||||
|
||||
self.cri.chan_sel.eq(self.target.storage[8:]),
|
||||
self.cri.timestamp.eq(self.timestamp.storage),
|
||||
|
||||
self.cri.o_timestamp.eq(now),
|
||||
self.cri.o_data.eq(self.o_data.storage),
|
||||
self.cri.o_address.eq(self.target.storage[:8]),
|
||||
self.o_status.status.eq(self.cri.o_status),
|
||||
|
||||
self.cri.i_timeout.eq(self.i_timeout.storage),
|
||||
self.i_data.status.eq(self.cri.i_data),
|
||||
self.i_timestamp.status.eq(self.cri.i_timestamp),
|
||||
self.i_status.status.eq(self.cri.i_status),
|
||||
|
||||
self.o_data.dat_w.eq(0),
|
||||
self.o_data.we.eq(self.timestamp.re),
|
||||
self.o_data.we.eq(self.target.re),
|
||||
]
|
||||
self.sync += If(self.counter_update.re, self.counter.status.eq(tsc.full_ts_cri))
|
||||
|
||||
|
@ -274,7 +274,7 @@ class CRIMaster(Module, AutoCSR):
|
||||
|
||||
self.comb += [
|
||||
self.cri.chan_sel.eq(self.sink.channel),
|
||||
self.cri.timestamp.eq(self.sink.timestamp),
|
||||
self.cri.o_timestamp.eq(self.sink.timestamp),
|
||||
self.cri.o_address.eq(self.sink.address),
|
||||
self.cri.o_data.eq(self.sink.data)
|
||||
]
|
||||
|
@ -118,7 +118,7 @@ class InputCollector(Module):
|
||||
|
||||
i_status_raw = Signal(2)
|
||||
self.comb += i_status_raw.eq(Array(i_statuses)[sel])
|
||||
input_timeout = Signal.like(self.cri.timestamp, reset_less=True)
|
||||
input_timeout = Signal.like(self.cri.i_timeout, reset_less=True)
|
||||
input_pending = Signal()
|
||||
self.cri.i_data.reset_less = True
|
||||
self.cri.i_timestamp.reset_less = True
|
||||
@ -134,7 +134,7 @@ class InputCollector(Module):
|
||||
input_pending.eq(0)
|
||||
),
|
||||
If(self.cri.cmd == cri.commands["read"],
|
||||
input_timeout.eq(self.cri.timestamp),
|
||||
input_timeout.eq(self.cri.i_timeout),
|
||||
input_pending.eq(1),
|
||||
self.cri.i_status.eq(0b100)
|
||||
)
|
||||
|
@ -60,7 +60,7 @@ class LaneDistributor(Module):
|
||||
self.comb += [
|
||||
lio.seqn.eq(seqn),
|
||||
lio.payload.channel.eq(self.cri.chan_sel[:16]),
|
||||
lio.payload.timestamp.eq(self.cri.timestamp),
|
||||
lio.payload.timestamp.eq(self.cri.o_timestamp),
|
||||
]
|
||||
if hasattr(lio.payload, "address"):
|
||||
self.comb += lio.payload.address.eq(self.cri.o_address)
|
||||
@ -69,7 +69,7 @@ class LaneDistributor(Module):
|
||||
|
||||
# when timestamp and channel arrive in cycle #1, prepare computations
|
||||
coarse_timestamp = Signal(us_timestamp_width)
|
||||
self.comb += coarse_timestamp.eq(self.cri.timestamp[glbl_fine_ts_width:])
|
||||
self.comb += coarse_timestamp.eq(self.cri.o_timestamp[glbl_fine_ts_width:])
|
||||
min_minus_timestamp = Signal((us_timestamp_width + 1, True),
|
||||
reset_less=True)
|
||||
laneAmin_minus_timestamp = Signal.like(min_minus_timestamp)
|
||||
@ -141,7 +141,7 @@ class LaneDistributor(Module):
|
||||
Array(lio.we for lio in self.output)[use_lanen].eq(do_write)
|
||||
]
|
||||
compensated_timestamp = Signal(64)
|
||||
self.comb += compensated_timestamp.eq(self.cri.timestamp + (compensation << glbl_fine_ts_width))
|
||||
self.comb += compensated_timestamp.eq(self.cri.o_timestamp + (compensation << glbl_fine_ts_width))
|
||||
self.sync += [
|
||||
If(do_write,
|
||||
current_lane.eq(use_lanen),
|
||||
|
@ -112,10 +112,10 @@ class OutputsTestbench:
|
||||
|
||||
def write(self, channel, data):
|
||||
kcsrs = self.dut.master_ki
|
||||
yield from kcsrs.chan_sel.write(channel)
|
||||
yield from kcsrs.timestamp.write(self.now)
|
||||
yield from kcsrs.target.write(channel << 8)
|
||||
yield from kcsrs.now_hi.write(self.now >> 32)
|
||||
yield from kcsrs.now_lo.write(self.now & 0xffffffff)
|
||||
yield from kcsrs.o_data.write(data)
|
||||
yield from kcsrs.o_we.write(1)
|
||||
yield
|
||||
status = 1
|
||||
wlen = 0
|
||||
@ -249,9 +249,8 @@ class TestFullStack(unittest.TestCase):
|
||||
kcsrs = dut.master_ki
|
||||
|
||||
def get_input(timeout):
|
||||
yield from kcsrs.chan_sel.write(2)
|
||||
yield from kcsrs.timestamp.write(10)
|
||||
yield from kcsrs.i_request.write(1)
|
||||
yield from kcsrs.target.write(2 << 8)
|
||||
yield from kcsrs.i_timeout.write(10)
|
||||
yield
|
||||
status = yield from kcsrs.i_status.read()
|
||||
while status & 0x4:
|
||||
|
@ -65,7 +65,7 @@ class TestRepeater(unittest.TestCase):
|
||||
yield
|
||||
for channel, timestamp, address, data in test_writes:
|
||||
yield dut.cri.chan_sel.eq(channel)
|
||||
yield dut.cri.timestamp.eq(timestamp)
|
||||
yield dut.cri.o_timestamp.eq(timestamp)
|
||||
yield dut.cri.o_address.eq(address)
|
||||
yield dut.cri.o_data.eq(data)
|
||||
yield dut.cri.cmd.eq(cri.commands["write"])
|
||||
@ -135,7 +135,7 @@ class TestRepeater(unittest.TestCase):
|
||||
|
||||
def read(chan_sel, timeout):
|
||||
yield dut.cri.chan_sel.eq(chan_sel)
|
||||
yield dut.cri.timestamp.eq(timeout)
|
||||
yield dut.cri.i_timeout.eq(timeout)
|
||||
yield dut.cri.cmd.eq(cri.commands["read"])
|
||||
yield
|
||||
yield dut.cri.cmd.eq(cri.commands["nop"])
|
||||
|
@ -90,7 +90,7 @@ class Testbench:
|
||||
def write(self, channel, data):
|
||||
mcri = self.dut.master.cri
|
||||
yield mcri.chan_sel.eq(channel)
|
||||
yield mcri.timestamp.eq(self.now)
|
||||
yield mcri.o_timestamp.eq(self.now)
|
||||
yield mcri.o_data.eq(data)
|
||||
yield
|
||||
yield mcri.cmd.eq(cri.commands["write"])
|
||||
@ -109,7 +109,7 @@ class Testbench:
|
||||
def read(self, channel, timeout):
|
||||
mcri = self.dut.master.cri
|
||||
yield mcri.chan_sel.eq(channel)
|
||||
yield mcri.timestamp.eq(timeout)
|
||||
yield mcri.i_timeout.eq(timeout)
|
||||
yield
|
||||
yield mcri.cmd.eq(cri.commands["read"])
|
||||
yield
|
||||
|
@ -26,7 +26,7 @@ def encode_record(channel, timestamp, address, data):
|
||||
r = []
|
||||
r += encode_n(channel, 3, 3)
|
||||
r += encode_n(timestamp, 8, 8)
|
||||
r += encode_n(address, 2, 2)
|
||||
r += encode_n(address, 1, 1)
|
||||
r += encode_n(data, 1, 64)
|
||||
return encode_n(len(r)+1, 1, 1) + r
|
||||
|
||||
@ -66,7 +66,7 @@ def do_dma(dut, address):
|
||||
|
||||
test_writes1 = [
|
||||
(0x01, 0x23, 0x12, 0x33),
|
||||
(0x901, 0x902, 0x911, 0xeeeeeeeeeeeeeefffffffffffffffffffffffffffffff28888177772736646717738388488),
|
||||
(0x901, 0x902, 0x11, 0xeeeeeeeeeeeeeefffffffffffffffffffffffffffffff28888177772736646717738388488),
|
||||
(0x81, 0x288, 0x88, 0x8888)
|
||||
]
|
||||
|
||||
@ -150,7 +150,7 @@ class TestDMA(unittest.TestCase):
|
||||
pass
|
||||
elif cmd == cri.commands["write"]:
|
||||
channel = yield dut_cri.chan_sel
|
||||
timestamp = yield dut_cri.timestamp
|
||||
timestamp = yield dut_cri.o_timestamp
|
||||
address = yield dut_cri.o_address
|
||||
data = yield dut_cri.o_data
|
||||
received.append((channel, timestamp, address, data))
|
||||
|
@ -54,7 +54,7 @@ def simulate(wait_cycles, ts_timeouts):
|
||||
yield
|
||||
|
||||
for ts_timeout in ts_timeouts:
|
||||
yield dut.cri.timestamp.eq(ts_timeout)
|
||||
yield dut.cri.i_timeout.eq(ts_timeout)
|
||||
yield dut.cri.cmd.eq(cri.commands["read"])
|
||||
yield
|
||||
yield dut.cri.cmd.eq(cri.commands["nop"])
|
||||
|
@ -21,7 +21,7 @@ def simulate(input_events, compensation=None, wait=True):
|
||||
def gen():
|
||||
for channel, timestamp in input_events:
|
||||
yield dut.cri.chan_sel.eq(channel)
|
||||
yield dut.cri.timestamp.eq(timestamp)
|
||||
yield dut.cri.o_timestamp.eq(timestamp)
|
||||
yield
|
||||
|
||||
yield dut.cri.cmd.eq(cri.commands["write"])
|
||||
|
@ -38,7 +38,7 @@ def simulate(input_events, **kwargs):
|
||||
def gen():
|
||||
yield dut.sed.cri.chan_sel.eq(0)
|
||||
for timestamp, data in input_events:
|
||||
yield dut.sed.cri.timestamp.eq(timestamp)
|
||||
yield dut.sed.cri.o_timestamp.eq(timestamp)
|
||||
yield dut.sed.cri.o_data.eq(data)
|
||||
yield
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user