mirror of https://github.com/m-labs/artiq.git
subkernels: send now_mu when starting a subkernel
This commit is contained in:
parent
33b81d0e2e
commit
4178fed3f7
|
@ -37,6 +37,14 @@ fn recv<R, F: FnOnce(&Message) -> R>(f: F) -> R {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_recv<F: FnOnce(&Message)>(f: F) {
|
||||||
|
let msg_ptr = mailbox::receive();
|
||||||
|
if msg_ptr != 0 {
|
||||||
|
f(unsafe { &*(msg_ptr as *const Message) });
|
||||||
|
mailbox::acknowledge();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
macro_rules! recv {
|
macro_rules! recv {
|
||||||
($p:pat => $e:expr) => {
|
($p:pat => $e:expr) => {
|
||||||
recv(move |request| {
|
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) {
|
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 } => {
|
recv!(&SubkernelLoadRunReply { succeeded } => {
|
||||||
if !succeeded {
|
if !succeeded {
|
||||||
raise!("SubkernelError",
|
raise!("SubkernelError",
|
||||||
|
@ -601,6 +617,15 @@ pub unsafe fn main() {
|
||||||
},
|
},
|
||||||
Ok(library) => {
|
Ok(library) => {
|
||||||
send(&LoadReply(Ok(())));
|
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
|
library
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ pub enum Packet {
|
||||||
|
|
||||||
SubkernelAddDataRequest { destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
SubkernelAddDataRequest { destination: u8, id: u32, status: PayloadStatus, length: u16, data: [u8; MASTER_PAYLOAD_MAX_SIZE] },
|
||||||
SubkernelAddDataReply { succeeded: bool },
|
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 },
|
SubkernelLoadRunReply { destination: u8, succeeded: bool },
|
||||||
SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 },
|
SubkernelFinished { destination: u8, id: u32, with_exception: bool, exception_src: u8 },
|
||||||
SubkernelExceptionRequest { source: u8, destination: u8 },
|
SubkernelExceptionRequest { source: u8, destination: u8 },
|
||||||
|
@ -354,7 +354,8 @@ impl Packet {
|
||||||
source: reader.read_u8()?,
|
source: reader.read_u8()?,
|
||||||
destination: reader.read_u8()?,
|
destination: reader.read_u8()?,
|
||||||
id: reader.read_u32()?,
|
id: reader.read_u32()?,
|
||||||
run: reader.read_bool()?
|
run: reader.read_bool()?,
|
||||||
|
timestamp: reader.read_u64()?
|
||||||
},
|
},
|
||||||
0xc5 => Packet::SubkernelLoadRunReply {
|
0xc5 => Packet::SubkernelLoadRunReply {
|
||||||
destination: reader.read_u8()?,
|
destination: reader.read_u8()?,
|
||||||
|
@ -647,12 +648,13 @@ impl Packet {
|
||||||
writer.write_u8(0xc1)?;
|
writer.write_u8(0xc1)?;
|
||||||
writer.write_bool(succeeded)?;
|
writer.write_bool(succeeded)?;
|
||||||
},
|
},
|
||||||
Packet::SubkernelLoadRunRequest { source, destination, id, run } => {
|
Packet::SubkernelLoadRunRequest { source, destination, id, run, timestamp } => {
|
||||||
writer.write_u8(0xc4)?;
|
writer.write_u8(0xc4)?;
|
||||||
writer.write_u8(source)?;
|
writer.write_u8(source)?;
|
||||||
writer.write_u8(destination)?;
|
writer.write_u8(destination)?;
|
||||||
writer.write_u32(id)?;
|
writer.write_u32(id)?;
|
||||||
writer.write_bool(run)?;
|
writer.write_bool(run)?;
|
||||||
|
writer.write_u64(timestamp)?;
|
||||||
},
|
},
|
||||||
Packet::SubkernelLoadRunReply { destination, succeeded } => {
|
Packet::SubkernelLoadRunReply { destination, succeeded } => {
|
||||||
writer.write_u8(0xc5)?;
|
writer.write_u8(0xc5)?;
|
||||||
|
|
|
@ -103,7 +103,7 @@ pub enum Message<'a> {
|
||||||
SpiReadReply { succeeded: bool, data: u32 },
|
SpiReadReply { succeeded: bool, data: u32 },
|
||||||
SpiBasicReply { succeeded: bool },
|
SpiBasicReply { succeeded: bool },
|
||||||
|
|
||||||
SubkernelLoadRunRequest { id: u32, destination: u8, run: bool },
|
SubkernelLoadRunRequest { id: u32, destination: u8, run: bool, timestamp: u64 },
|
||||||
SubkernelLoadRunReply { succeeded: bool },
|
SubkernelLoadRunReply { succeeded: bool },
|
||||||
SubkernelAwaitFinishRequest { id: u32, timeout: i64 },
|
SubkernelAwaitFinishRequest { id: u32, timeout: i64 },
|
||||||
SubkernelAwaitFinishReply,
|
SubkernelAwaitFinishReply,
|
||||||
|
@ -112,6 +112,8 @@ pub enum Message<'a> {
|
||||||
SubkernelMsgRecvReply { count: u8 },
|
SubkernelMsgRecvReply { count: u8 },
|
||||||
SubkernelError(SubkernelStatus<'a>),
|
SubkernelError(SubkernelStatus<'a>),
|
||||||
|
|
||||||
|
UpdateNow(u64),
|
||||||
|
|
||||||
Log(fmt::Arguments<'a>),
|
Log(fmt::Arguments<'a>),
|
||||||
LogSlice(&'a str)
|
LogSlice(&'a str)
|
||||||
}
|
}
|
||||||
|
|
|
@ -194,14 +194,15 @@ pub mod subkernel {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex, routing_table: &RoutingTable,
|
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 _lock = subkernel_mutex.lock(io)?;
|
||||||
let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() };
|
let subkernel = unsafe { SUBKERNELS.get_mut(&id).unwrap() };
|
||||||
if subkernel.state != SubkernelState::Uploaded {
|
if subkernel.state != SubkernelState::Uploaded {
|
||||||
error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state);
|
error!("for id: {} expected Uploaded, got: {:?}", id, subkernel.state);
|
||||||
return Err(Error::IncorrectState);
|
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 {
|
if run {
|
||||||
subkernel.state = SubkernelState::Running;
|
subkernel.state = SubkernelState::Running;
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,11 +594,14 @@ pub mod drtio {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn subkernel_load(io: &Io, aux_mutex: &Mutex, ddma_mutex: &Mutex, subkernel_mutex: &Mutex,
|
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> {
|
) -> Result<(), Error> {
|
||||||
let linkno = routing_table.0[destination as usize][0] - 1;
|
let linkno = routing_table.0[destination as usize][0] - 1;
|
||||||
let reply = aux_transact(io, aux_mutex, ddma_mutex, subkernel_mutex, routing_table, linkno,
|
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 {
|
match reply {
|
||||||
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()),
|
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: true } => Ok(()),
|
||||||
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: false } =>
|
drtioaux::Packet::SubkernelLoadRunReply { destination: 0, succeeded: false } =>
|
||||||
|
|
|
@ -661,9 +661,9 @@ fn process_kern_message(io: &Io, aux_mutex: &Mutex,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(has_drtio)]
|
#[cfg(has_drtio)]
|
||||||
&kern::SubkernelLoadRunRequest { id, destination: _, run } => {
|
&kern::SubkernelLoadRunRequest { id, destination: _, run, timestamp } => {
|
||||||
let succeeded = match subkernel::load(
|
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,
|
Ok(()) => true,
|
||||||
Err(e) => { error!("Error loading subkernel: {}", e); false }
|
Err(e) => { error!("Error loading subkernel: {}", e); false }
|
||||||
};
|
};
|
||||||
|
|
|
@ -363,17 +363,17 @@ impl Manager {
|
||||||
unsafe { self.cache.unborrow() }
|
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);
|
info!("starting subkernel #{}", id);
|
||||||
if self.session.kernel_state != KernelState::Loaded
|
if self.session.kernel_state != KernelState::Loaded
|
||||||
|| self.current_id != id {
|
|| self.current_id != id {
|
||||||
self.load(id)?;
|
self.load(id)?;
|
||||||
}
|
}
|
||||||
self.session.source = source;
|
self.session.source = source;
|
||||||
self.session.kernel_state = KernelState::Running;
|
self.session.kernel_state = KernelState::Running;
|
||||||
cricon_select(RtioMaster::Kernel);
|
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]) {
|
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
|
// ID equal to -1 indicates wildcard for receiving arguments
|
||||||
let id = if id == -1 { self.current_id } else { id as u32 };
|
let id = if id == -1 { self.current_id } else { id as u32 };
|
||||||
self.session.kernel_state = KernelState::MsgAwait {
|
self.session.kernel_state = KernelState::MsgAwait {
|
||||||
id: id, max_time: max_time, tags: tags.to_vec() };
|
id, max_time, tags: tags.to_vec() };
|
||||||
Ok(())
|
Ok(())
|
||||||
},
|
},
|
||||||
|
|
||||||
&kern::SubkernelLoadRunRequest { id, destination: sk_destination, run } => {
|
&kern::SubkernelLoadRunRequest { id, destination: sk_destination, run, timestamp } => {
|
||||||
self.session.kernel_state = KernelState::SubkernelAwaitLoad;
|
self.session.kernel_state = KernelState::SubkernelAwaitLoad;
|
||||||
router.route(drtioaux::Packet::SubkernelLoadRunRequest {
|
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);
|
}, routing_table, rank, destination);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
&kern::SubkernelAwaitFinishRequest{ id, timeout } => {
|
&kern::SubkernelAwaitFinishRequest { id, timeout } => {
|
||||||
let max_time = if timeout > 0 { clock::get_ms() as i64 + timeout } else { 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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -427,7 +427,7 @@ fn process_aux_packet(dmamgr: &mut DmaManager, analyzer: &mut Analyzer, kernelmg
|
||||||
drtioaux::send(0,
|
drtioaux::send(0,
|
||||||
&drtioaux::Packet::SubkernelAddDataReply { succeeded: succeeded })
|
&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);
|
forward!(router, _routing_table, _destination, *rank, *self_destination, _repeaters, &packet);
|
||||||
let mut succeeded = kernelmgr.load(id).is_ok();
|
let mut succeeded = kernelmgr.load(id).is_ok();
|
||||||
// allow preloading a kernel with delayed run
|
// 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
|
// cannot run kernel while DDMA is running
|
||||||
succeeded = false;
|
succeeded = false;
|
||||||
} else {
|
} else {
|
||||||
succeeded |= kernelmgr.run(source, id).is_ok();
|
succeeded |= kernelmgr.run(source, id, timestamp).is_ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
router.send(drtioaux::Packet::SubkernelLoadRunReply {
|
router.send(drtioaux::Packet::SubkernelLoadRunReply {
|
||||||
|
|
Loading…
Reference in New Issue