From 4178fed3f76144f5501a8f3a1cb62c3b55a9dc53 Mon Sep 17 00:00:00 2001 From: mwojcik Date: Fri, 18 Oct 2024 12:36:09 +0800 Subject: [PATCH] subkernels: send now_mu when starting a subkernel --- artiq/firmware/ksupport/lib.rs | 27 ++++++++++++++++++- .../firmware/libproto_artiq/drtioaux_proto.rs | 8 +++--- artiq/firmware/libproto_artiq/kernel_proto.rs | 4 ++- artiq/firmware/runtime/kernel.rs | 5 ++-- artiq/firmware/runtime/rtio_mgt.rs | 7 +++-- artiq/firmware/runtime/session.rs | 4 +-- artiq/firmware/satman/kernel.rs | 16 +++++------ artiq/firmware/satman/main.rs | 4 +-- 8 files changed, 54 insertions(+), 21 deletions(-) diff --git a/artiq/firmware/ksupport/lib.rs b/artiq/firmware/ksupport/lib.rs index 042f3b429..4f8893a87 100644 --- a/artiq/firmware/ksupport/lib.rs +++ b/artiq/firmware/ksupport/lib.rs @@ -37,6 +37,14 @@ fn recv R>(f: F) -> R { result } +fn try_recv(f: F) { + let msg_ptr = mailbox::receive(); + if msg_ptr != 0 { + f(unsafe { &*(msg_ptr as *const Message) }); + mailbox::acknowledge(); + } +} + macro_rules! recv { ($p:pat => $e:expr) => { recv(move |request| { @@ -473,7 +481,15 @@ extern "C-unwind" fn dma_playback(timestamp: i64, ptr: i32, _uses_ddma: bool) { extern "C-unwind" fn subkernel_load_run(id: u32, destination: u8, run: bool) { - send(&SubkernelLoadRunRequest { id: id, destination: destination, run: run }); + let timestamp = unsafe { + ((csr::rtio::now_hi_read() as u64) << 32) | (csr::rtio::now_lo_read() as u64) + }; + send(&SubkernelLoadRunRequest { + id: id, + destination: destination, + run: run, + timestamp: timestamp, + }); recv!(&SubkernelLoadRunReply { succeeded } => { if !succeeded { raise!("SubkernelError", @@ -601,6 +617,15 @@ pub unsafe fn main() { }, Ok(library) => { send(&LoadReply(Ok(()))); + // Master kernel would just acknowledge kernel load + // Satellites may send UpdateNow + try_recv(move |msg| match msg { + UpdateNow(timestamp) => unsafe { + csr::rtio::now_hi_write((*timestamp >> 32) as u32); + csr::rtio::now_lo_write(*timestamp as u32); + } + _ => unreachable!() + }); library } } diff --git a/artiq/firmware/libproto_artiq/drtioaux_proto.rs b/artiq/firmware/libproto_artiq/drtioaux_proto.rs index ec1c36686..a1b17e888 100644 --- a/artiq/firmware/libproto_artiq/drtioaux_proto.rs +++ b/artiq/firmware/libproto_artiq/drtioaux_proto.rs @@ -120,7 +120,7 @@ pub enum Packet { SubkernelAddDataRequest { destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] }, SubkernelAddDataReply { succeeded: bool }, - SubkernelLoadRunRequest { source: u8, destination: u8, id: u32, run: bool }, + SubkernelLoadRunRequest { source: u8, destination: u8, id: u32, run: bool, timestamp: u64 }, SubkernelLoadRunReply { destination: u8, succeeded: bool }, SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 }, SubkernelExceptionRequest { source: u8, destination: u8 }, @@ -354,7 +354,8 @@ impl Packet { source: reader.read_u8()?, destination: reader.read_u8()?, id: reader.read_u32()?, - run: reader.read_bool()? + run: reader.read_bool()?, + timestamp: reader.read_u64()? }, 0xc5 => Packet::SubkernelLoadRunReply { destination: reader.read_u8()?, @@ -647,12 +648,13 @@ impl Packet { writer.write_u8(0xc1)?; writer.write_bool(succeeded)?; }, - Packet::SubkernelLoadRunRequest { source, destination, id, run } => { + Packet::SubkernelLoadRunRequest { source, destination, id, run, timestamp } => { writer.write_u8(0xc4)?; writer.write_u8(source)?; writer.write_u8(destination)?; writer.write_u32(id)?; writer.write_bool(run)?; + writer.write_u64(timestamp)?; }, Packet::SubkernelLoadRunReply { destination, succeeded } => { writer.write_u8(0xc5)?; diff --git a/artiq/firmware/libproto_artiq/kernel_proto.rs b/artiq/firmware/libproto_artiq/kernel_proto.rs index 31aece5c4..31df20abf 100644 --- a/artiq/firmware/libproto_artiq/kernel_proto.rs +++ b/artiq/firmware/libproto_artiq/kernel_proto.rs @@ -103,7 +103,7 @@ pub enum Message<'a> { SpiReadReply { succeeded: bool, data: u32 }, SpiBasicReply { succeeded: bool }, - SubkernelLoadRunRequest { id: u32, destination: u8, run: bool }, + SubkernelLoadRunRequest { id: u32, destination: u8, run: bool, timestamp: u64 }, SubkernelLoadRunReply { succeeded: bool }, SubkernelAwaitFinishRequest { id: u32, timeout: i64 }, SubkernelAwaitFinishReply, @@ -112,6 +112,8 @@ pub enum Message<'a> { SubkernelMsgRecvReply { count: u8 }, SubkernelError(SubkernelStatus<'a>), + UpdateNow(u64), + Log(fmt::Arguments<'a>), LogSlice(&'a str) } diff --git a/artiq/firmware/runtime/kernel.rs b/artiq/firmware/runtime/kernel.rs index 545f75981..ab0ac31ab 100644 --- a/artiq/firmware/runtime/kernel.rs +++ b/artiq/firmware/runtime/kernel.rs @@ -194,14 +194,15 @@ pub mod subkernel { } pub fn load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, routing_table: &RoutingTable, - id: u32, run: bool) -> Result<(), Error> { + id: u32, run: bool, timestamp: u64) -> Result<(), Error> { let _lock = subkernel_mutex.lock(io)?; let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() }; if subkernel.state != SubkernelState::Uploaded { error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state); return Err(Error::IncorrectState); } - drtio::subkernel_load(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, subkernel.destination, run)?; + drtio::subkernel_load(io, aux_mutex, ddma_mutex, subkernel_mutex, + routing_table, id, subkernel.destination, run, timestamp)?; if run { subkernel.state = SubkernelState::Running; } diff --git a/artiq/firmware/runtime/rtio_mgt.rs b/artiq/firmware/runtime/rtio_mgt.rs index 3ed892d2a..d065214a7 100644 --- a/artiq/firmware/runtime/rtio_mgt.rs +++ b/artiq/firmware/runtime/rtio_mgt.rs @@ -594,11 +594,14 @@ pub mod drtio { } pub fn subkernel_load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, - routing_table: &drtio_routing::RoutingTable, id: u32, destination: u8, run: bool + routing_table: &drtio_routing::RoutingTable, id: u32, destination: u8, run: bool, timestamp: u64 ) -> Result<(), Error> { let linkno = routing_table.0[destination as usize][0] - 1; let reply = aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno, - &drtioaux::Packet::SubkernelLoadRunRequest{ id: id, source: 0, destination: destination, run: run })?; + &drtioaux::Packet::SubkernelLoadRunRequest{ + id: id, source: 0, destination: destination, + run: run, timestamp: timestamp + })?; match reply { drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()), drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: false } => diff --git a/artiq/firmware/runtime/session.rs b/artiq/firmware/runtime/session.rs index 579b2094c..6e849e87a 100644 --- a/artiq/firmware/runtime/session.rs +++ b/artiq/firmware/runtime/session.rs @@ -661,9 +661,9 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex, } } #[cfg(has_drtio)] - &kern::SubkernelLoadRunRequest { id, destination: _, run } => { + &kern::SubkernelLoadRunRequest { id, destination: _, run, timestamp } => { let succeeded = match subkernel::load( - io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, run) { + io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, id, run, timestamp) { Ok(()) => true, Err(e) => { error!("Error loading subkernel: {}", e); false } }; diff --git a/artiq/firmware/satman/kernel.rs b/artiq/firmware/satman/kernel.rs index 6f8f5b7c7..c47f3515e 100644 --- a/artiq/firmware/satman/kernel.rs +++ b/artiq/firmware/satman/kernel.rs @@ -363,17 +363,17 @@ impl Manager { unsafe { self.cache.unborrow() } } - pub fn run(&mut self, source: u8, id: u32) -> Result<(), Error> { + pub fn run(&mut self, source: u8, id: u32, timestamp: u64) -> Result<(), Error> { info!("starting subkernel #{}", id); if self.session.kernel_state != KernelState::Loaded || self.current_id != id { self.load(id)?; - } + } self.session.source = source; self.session.kernel_state = KernelState::Running; cricon_select(RtioMaster::Kernel); - kern_acknowledge() + kern_send(&kern::UpdateNow(timestamp)) } pub fn message_handle_incoming(&mut self, status: PayloadStatus, length: usize, id: u32, slice: &[u8; MASTER_PAYLOAD_MAX_SIZE]) { @@ -825,21 +825,21 @@ impl Manager { // ID equal to -1 indicates wildcard for receiving arguments let id = if id == -1 { self.current_id } else { id as u32 }; self.session.kernel_state = KernelState::MsgAwait { - id: id, max_time: max_time, tags: tags.to_vec() }; + id, max_time, tags: tags.to_vec() }; Ok(()) }, - &kern::SubkernelLoadRunRequest { id, destination: sk_destination, run } => { + &kern::SubkernelLoadRunRequest { id, destination: sk_destination, run, timestamp } => { self.session.kernel_state = KernelState::SubkernelAwaitLoad; router.route(drtioaux::Packet::SubkernelLoadRunRequest { - source: destination, destination: sk_destination, id: id, run: run + source: destination, destination: sk_destination, id, run, timestamp }, routing_table, rank, destination); Ok(()) } - &kern::SubkernelAwaitFinishRequest{ id, timeout } => { + &kern::SubkernelAwaitFinishRequest { id, timeout } => { let max_time = if timeout > 0 { clock::get_ms() as i64 + timeout } else { timeout }; - self.session.kernel_state = KernelState::SubkernelAwaitFinish { max_time: max_time, id: id }; + self.session.kernel_state = KernelState::SubkernelAwaitFinish { max_time, id }; Ok(()) } diff --git a/artiq/firmware/satman/main.rs b/artiq/firmware/satman/main.rs index 8f5470e3e..11da3e1a1 100644 --- a/artiq/firmware/satman/main.rs +++ b/artiq/firmware/satman/main.rs @@ -427,7 +427,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg drtioaux::send(0, &drtioaux::Packet::SubkernelAddDataReply { succeeded: succeeded }) } - drtioaux::Packet::SubkernelLoadRunRequest { source, destination: _destination, id, run } => { + drtioaux::Packet::SubkernelLoadRunRequest { source, destination: _destination, id, run, timestamp } => { forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet); let mut succeeded = kernelmgr.load(id).is_ok(); // allow preloading a kernel with delayed run @@ -436,7 +436,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg // cannot run kernel while DDMA is running succeeded = false; } else { - succeeded |= kernelmgr.run(source, id).is_ok(); + succeeded |= kernelmgr.run(source, id, timestamp).is_ok(); } } router.send(drtioaux::Packet::SubkernelLoadRunReply {