From 79e70fa465ea7990ab253f4d7cae5ee2e3ec7849 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 23 Nov 2016 16:28:05 +0000 Subject: [PATCH 1/5] runtime: use correct ABI when accepting ARTIQ lists. --- artiq/runtime.rs/libksupport/lib.rs | 23 +++++++++++++++++++---- artiq/runtime.rs/libksupport/rtio.rs | 8 ++++---- artiq/runtime.rs/src/cache.rs | 6 +++--- artiq/runtime.rs/src/kernel_proto.rs | 4 ++-- artiq/runtime.rs/src/session.rs | 4 ++-- 5 files changed, 30 insertions(+), 15 deletions(-) diff --git a/artiq/runtime.rs/libksupport/lib.rs b/artiq/runtime.rs/libksupport/lib.rs index 08673e759..7c0db38c1 100644 --- a/artiq/runtime.rs/libksupport/lib.rs +++ b/artiq/runtime.rs/libksupport/lib.rs @@ -118,6 +118,22 @@ extern fn panic_fmt(args: core::fmt::Arguments, file: &'static str, line: u32) - loop {} } +#[repr(C)] +pub struct ArtiqList { + len: usize, + ptr: *const T +} + +impl ArtiqList { + pub fn from_slice(slice: &'static [T]) -> ArtiqList { + ArtiqList { ptr: slice.as_ptr(), len: slice.len() } + } + + pub unsafe fn as_slice(&self) -> &[T] { + slice::from_raw_parts(self.ptr, self.len) + } +} + static mut NOW: u64 = 0; #[no_mangle] @@ -221,7 +237,7 @@ extern fn watchdog_clear(id: usize) { send(&WatchdogClear { id: id }) } -extern fn cache_get(key: *const u8) -> (usize, *const u32) { +extern fn cache_get(key: *const u8) -> (usize, *const i32) { extern { fn strlen(s: *const c_char) -> size_t; } let key = unsafe { slice::from_raw_parts(key, strlen(key as *const c_char)) }; let key = unsafe { str::from_utf8_unchecked(key) }; @@ -230,13 +246,12 @@ extern fn cache_get(key: *const u8) -> (usize, *const u32) { recv!(&CacheGetReply { value } => (value.len(), value.as_ptr())) } -extern fn cache_put(key: *const u8, &(len, ptr): &(usize, *const u32)) { +extern fn cache_put(key: *const u8, list: ArtiqList) { extern { fn strlen(s: *const c_char) -> size_t; } let key = unsafe { slice::from_raw_parts(key, strlen(key as *const c_char)) }; let key = unsafe { str::from_utf8_unchecked(key) }; - let value = unsafe { slice::from_raw_parts(ptr, len) }; - send(&CachePutRequest { key: key, value: value }); + send(&CachePutRequest { key: key, value: unsafe { list.as_slice() } }); recv!(&CachePutReply { succeeded } => { if !succeeded { artiq_raise!("CacheError", "cannot put into a busy cache row") diff --git a/artiq/runtime.rs/libksupport/rtio.rs b/artiq/runtime.rs/libksupport/rtio.rs index 60dadc815..2825888cc 100644 --- a/artiq/runtime.rs/libksupport/rtio.rs +++ b/artiq/runtime.rs/libksupport/rtio.rs @@ -1,6 +1,7 @@ use board::csr; use core::ptr::{read_volatile, write_volatile}; use core::slice; +use ::ArtiqList; const RTIO_O_STATUS_FULL: u32 = 1; const RTIO_O_STATUS_UNDERFLOW: u32 = 2; @@ -83,17 +84,16 @@ pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { } } -pub extern fn output_list(timestamp: i64, channel: u32, addr: u32, - &(len, ptr): &(usize, *const u32)) { +pub extern fn output_list(timestamp: i64, channel: u32, addr: u32, list: ArtiqList) { unsafe { csr::rtio::chan_sel_write(channel); csr::rtio::o_timestamp_write(timestamp as u64); csr::rtio::o_address_write(addr); - let data = slice::from_raw_parts(ptr, len); + let data = list.as_slice(); for i in 0..data.len() { write_volatile( csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - i) as isize), - data[i]); + data[i] as u32); } csr::rtio::o_we_write(1); let status = csr::rtio::o_status_read(); diff --git a/artiq/runtime.rs/src/cache.rs b/artiq/runtime.rs/src/cache.rs index 4136b96f3..082dda287 100644 --- a/artiq/runtime.rs/src/cache.rs +++ b/artiq/runtime.rs/src/cache.rs @@ -4,7 +4,7 @@ use std::btree_map::BTreeMap; #[derive(Debug)] struct Entry { - data: Vec, + data: Vec, borrowed: bool } @@ -18,7 +18,7 @@ impl Cache { Cache { entries: BTreeMap::new() } } - pub fn get(&mut self, key: &str) -> *const [u32] { + pub fn get(&mut self, key: &str) -> *const [i32] { match self.entries.get_mut(key) { None => &[], Some(ref mut entry) => { @@ -28,7 +28,7 @@ impl Cache { } } - pub fn put(&mut self, key: &str, data: &[u32]) -> Result<(), ()> { + pub fn put(&mut self, key: &str, data: &[i32]) -> Result<(), ()> { match self.entries.get_mut(key) { None => (), Some(ref mut entry) => { diff --git a/artiq/runtime.rs/src/kernel_proto.rs b/artiq/runtime.rs/src/kernel_proto.rs index c015b76d2..89b90657f 100644 --- a/artiq/runtime.rs/src/kernel_proto.rs +++ b/artiq/runtime.rs/src/kernel_proto.rs @@ -51,8 +51,8 @@ pub enum Message<'a> { RpcRecvReply(Result>), CacheGetRequest { key: &'a str }, - CacheGetReply { value: &'static [u32] }, - CachePutRequest { key: &'a str, value: &'static [u32] }, + CacheGetReply { value: &'static [i32] }, + CachePutRequest { key: &'a str, value: &'a [i32] }, CachePutReply { succeeded: bool }, Log(fmt::Arguments<'a>), diff --git a/artiq/runtime.rs/src/session.rs b/artiq/runtime.rs/src/session.rs index 083cfa8a9..b2f58b5d1 100644 --- a/artiq/runtime.rs/src/session.rs +++ b/artiq/runtime.rs/src/session.rs @@ -406,7 +406,7 @@ fn process_kern_message(waiter: Waiter, &kern::CacheGetRequest { key } => { let value = session.congress.cache.get(key); kern_send(waiter, &kern::CacheGetReply { - value: unsafe { mem::transmute::<*const [u32], &'static [u32]>(value) } + value: unsafe { mem::transmute::<*const [i32], &'static [i32]>(value) } }) } @@ -470,7 +470,7 @@ fn process_kern_message(waiter: Waiter, } fn process_kern_queued_rpc(stream: &mut TcpStream, - session: &mut Session) -> io::Result<()> { + _session: &mut Session) -> io::Result<()> { rpc_queue::dequeue(|slice| { trace!("comm<-kern (async RPC)"); let length = NetworkEndian::read_u32(slice) as usize; From cf12a888e7ff325d9dbf6eadc89d659bc91a6b01 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 23 Nov 2016 16:35:02 +0000 Subject: [PATCH 2/5] runtime: refactor rtio_output_list. --- artiq/runtime.rs/libksupport/api.rs | 2 +- artiq/runtime.rs/libksupport/rtio.rs | 25 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/artiq/runtime.rs/libksupport/api.rs b/artiq/runtime.rs/libksupport/api.rs index 57b6302d8..00c6ccec1 100644 --- a/artiq/runtime.rs/libksupport/api.rs +++ b/artiq/runtime.rs/libksupport/api.rs @@ -102,7 +102,7 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(rtio_get_counter = ::rtio::get_counter), api!(rtio_log), api!(rtio_output = ::rtio::output), - api!(rtio_output_list = ::rtio::output_list), + api!(rtio_output_wide = ::rtio::output_wide), api!(rtio_input_timestamp = ::rtio::input_timestamp), api!(rtio_input_data = ::rtio::input_data), diff --git a/artiq/runtime.rs/libksupport/rtio.rs b/artiq/runtime.rs/libksupport/rtio.rs index 2825888cc..01c400427 100644 --- a/artiq/runtime.rs/libksupport/rtio.rs +++ b/artiq/runtime.rs/libksupport/rtio.rs @@ -1,6 +1,5 @@ use board::csr; use core::ptr::{read_volatile, write_volatile}; -use core::slice; use ::ArtiqList; const RTIO_O_STATUS_FULL: u32 = 1; @@ -27,16 +26,16 @@ pub extern fn get_counter() -> i64 { } #[inline(always)] -pub unsafe fn rtio_o_data_write(w: u32) { +pub unsafe fn rtio_o_data_write(offset: usize, data: u32) { write_volatile( - csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1) as isize), - w); + csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - offset) as isize), + data); } #[inline(always)] -pub unsafe fn rtio_i_data_read() -> u32 { +pub unsafe fn rtio_i_data_read(offset: usize) -> u32 { read_volatile( - csr::rtio::I_DATA_ADDR.offset((csr::rtio::I_DATA_SIZE - 1) as isize)) + csr::rtio::I_DATA_ADDR.offset((csr::rtio::I_DATA_SIZE - 1 - offset) as isize)) } #[inline(never)] @@ -75,7 +74,7 @@ pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { csr::rtio::chan_sel_write(channel); csr::rtio::o_timestamp_write(timestamp as u64); csr::rtio::o_address_write(addr); - rtio_o_data_write(data); + rtio_o_data_write(0, data); csr::rtio::o_we_write(1); let status = csr::rtio::o_status_read(); if status != 0 { @@ -84,16 +83,14 @@ pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { } } -pub extern fn output_list(timestamp: i64, channel: u32, addr: u32, list: ArtiqList) { +pub extern fn output_wide(timestamp: i64, channel: u32, addr: u32, list: ArtiqList) { unsafe { csr::rtio::chan_sel_write(channel); csr::rtio::o_timestamp_write(timestamp as u64); csr::rtio::o_address_write(addr); let data = list.as_slice(); for i in 0..data.len() { - write_volatile( - csr::rtio::O_DATA_ADDR.offset((csr::rtio::O_DATA_SIZE - 1 - i) as isize), - data[i] as u32); + rtio_o_data_write(i, data[i] as u32) } csr::rtio::o_we_write(1); let status = csr::rtio::o_status_read(); @@ -154,7 +151,7 @@ pub extern fn input_data(channel: u32) -> u32 { } } - let data = rtio_i_data_read(); + let data = rtio_i_data_read(0); csr::rtio::i_re_write(1); data } @@ -171,14 +168,14 @@ pub fn log(timestamp: i64, data: &[u8]) { word <<= 8; word |= data[i] as u32; if i % 4 == 0 { - rtio_o_data_write(word); + rtio_o_data_write(0, word); csr::rtio::o_we_write(1); word = 0; } } word <<= 8; - rtio_o_data_write(word); + rtio_o_data_write(0, word); csr::rtio::o_we_write(1); } } From ea25856d924c9d0266504ec555b84725e1c00096 Mon Sep 17 00:00:00 2001 From: whitequark Date: Wed, 23 Nov 2016 16:41:43 +0000 Subject: [PATCH 3/5] runtime: match argument signedness between ARTIQ Python and ksupport. This is only required when reading the ABI very strictly, but better be conservative here than spend time debugging silly stuff. --- artiq/runtime.rs/libksupport/i2c.rs | 22 ++++++++++++++++------ artiq/runtime.rs/libksupport/lib.rs | 12 ++++++------ artiq/runtime.rs/libksupport/rtio.rs | 26 +++++++++++++------------- 3 files changed, 35 insertions(+), 25 deletions(-) diff --git a/artiq/runtime.rs/libksupport/i2c.rs b/artiq/runtime.rs/libksupport/i2c.rs index 8a9f6da2d..0f299e6cf 100644 --- a/artiq/runtime.rs/libksupport/i2c.rs +++ b/artiq/runtime.rs/libksupport/i2c.rs @@ -75,7 +75,9 @@ mod imp { use self::imp::*; -pub extern fn init(busno: u32) { +pub extern fn init(busno: i32) { + let busno = busno as u32; + // Set SCL as output, and high level scl_o(busno, true); scl_oe(busno, true); @@ -92,7 +94,9 @@ pub extern fn init(busno: u32) { } } -pub extern fn start(busno: u32) { +pub extern fn start(busno: i32) { + let busno = busno as u32; + // Set SCL high then SDA low scl_o(busno, true); half_period(); @@ -100,7 +104,9 @@ pub extern fn start(busno: u32) { half_period(); } -pub extern fn stop(busno: u32) { +pub extern fn stop(busno: i32) { + let busno = busno as u32; + // First, make sure SCL is low, so that the target releases the SDA line scl_o(busno, false); half_period(); @@ -112,7 +118,9 @@ pub extern fn stop(busno: u32) { half_period(); } -pub extern fn write(busno: u32, data: u8) -> bool { +pub extern fn write(busno: i32, data: i8) -> bool { + let (busno, data) = (busno as u32, data as u8); + // MSB first for bit in (0..8).rev() { // Set SCL low and set our bit on SDA @@ -135,7 +143,9 @@ pub extern fn write(busno: u32, data: u8) -> bool { !sda_i(busno) } -pub extern fn read(busno: u32, ack: bool) -> u8 { +pub extern fn read(busno: i32, ack: bool) -> i8 { + let busno = busno as u32; + // Set SCL low first, otherwise setting SDA as input may cause a transition // on SDA with SCL high which will be interpreted as START/STOP condition. scl_o(busno, false); @@ -162,5 +172,5 @@ pub extern fn read(busno: u32, ack: bool) -> u8 { scl_o(busno, true); half_period(); - data + data as i8 } diff --git a/artiq/runtime.rs/libksupport/lib.rs b/artiq/runtime.rs/libksupport/lib.rs index 7c0db38c1..e8499982a 100644 --- a/artiq/runtime.rs/libksupport/lib.rs +++ b/artiq/runtime.rs/libksupport/lib.rs @@ -224,26 +224,26 @@ pub extern fn __artiq_terminate(exception: *const kernel_proto::Exception, loop {} } -extern fn watchdog_set(ms: i64) -> usize { +extern fn watchdog_set(ms: i64) -> i32 { if ms < 0 { artiq_raise!("ValueError", "cannot set a watchdog with a negative timeout") } send(&WatchdogSetRequest { ms: ms as u64 }); - recv!(&WatchdogSetReply { id } => id) + recv!(&WatchdogSetReply { id } => id) as i32 } -extern fn watchdog_clear(id: usize) { - send(&WatchdogClear { id: id }) +extern fn watchdog_clear(id: i32) { + send(&WatchdogClear { id: id as usize }) } -extern fn cache_get(key: *const u8) -> (usize, *const i32) { +extern fn cache_get(key: *const u8) -> ArtiqList { extern { fn strlen(s: *const c_char) -> size_t; } let key = unsafe { slice::from_raw_parts(key, strlen(key as *const c_char)) }; let key = unsafe { str::from_utf8_unchecked(key) }; send(&CacheGetRequest { key: key }); - recv!(&CacheGetReply { value } => (value.len(), value.as_ptr())) + recv!(&CacheGetReply { value } => ArtiqList::from_slice(value)) } extern fn cache_put(key: *const u8, list: ArtiqList) { diff --git a/artiq/runtime.rs/libksupport/rtio.rs b/artiq/runtime.rs/libksupport/rtio.rs index 01c400427..9bd788962 100644 --- a/artiq/runtime.rs/libksupport/rtio.rs +++ b/artiq/runtime.rs/libksupport/rtio.rs @@ -39,7 +39,7 @@ pub unsafe fn rtio_i_data_read(offset: usize) -> u32 { } #[inline(never)] -unsafe fn process_exceptional_status(timestamp: i64, channel: u32, status: u32) { +unsafe fn process_exceptional_status(timestamp: i64, channel: i32, status: u32) { if status & RTIO_O_STATUS_FULL != 0 { while csr::rtio::o_status_read() & RTIO_O_STATUS_FULL != 0 {} } @@ -69,12 +69,12 @@ unsafe fn process_exceptional_status(timestamp: i64, channel: u32, status: u32) } } -pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { +pub extern fn output(timestamp: i64, channel: i32, addr: i32, data: i32) { unsafe { - csr::rtio::chan_sel_write(channel); + csr::rtio::chan_sel_write(channel as u32); csr::rtio::o_timestamp_write(timestamp as u64); - csr::rtio::o_address_write(addr); - rtio_o_data_write(0, data); + csr::rtio::o_address_write(addr as u32); + rtio_o_data_write(0, data as u32); csr::rtio::o_we_write(1); let status = csr::rtio::o_status_read(); if status != 0 { @@ -83,11 +83,11 @@ pub extern fn output(timestamp: i64, channel: u32, addr: u32, data: u32) { } } -pub extern fn output_wide(timestamp: i64, channel: u32, addr: u32, list: ArtiqList) { +pub extern fn output_wide(timestamp: i64, channel: i32, addr: i32, list: ArtiqList) { unsafe { - csr::rtio::chan_sel_write(channel); + csr::rtio::chan_sel_write(channel as u32); csr::rtio::o_timestamp_write(timestamp as u64); - csr::rtio::o_address_write(addr); + csr::rtio::o_address_write(addr as u32); let data = list.as_slice(); for i in 0..data.len() { rtio_o_data_write(i, data[i] as u32) @@ -100,9 +100,9 @@ pub extern fn output_wide(timestamp: i64, channel: u32, addr: u32, list: ArtiqLi } } -pub extern fn input_timestamp(timeout: i64, channel: u32) -> u64 { +pub extern fn input_timestamp(timeout: i64, channel: i32) -> u64 { unsafe { - csr::rtio::chan_sel_write(channel); + csr::rtio::chan_sel_write(channel as u32); let mut status; loop { status = csr::rtio::i_status_read(); @@ -136,9 +136,9 @@ pub extern fn input_timestamp(timeout: i64, channel: u32) -> u64 { } } -pub extern fn input_data(channel: u32) -> u32 { +pub extern fn input_data(channel: i32) -> i32 { unsafe { - csr::rtio::chan_sel_write(channel); + csr::rtio::chan_sel_write(channel as u32); loop { let status = csr::rtio::i_status_read(); if status == 0 { break } @@ -153,7 +153,7 @@ pub extern fn input_data(channel: u32) -> u32 { let data = rtio_i_data_read(0); csr::rtio::i_re_write(1); - data + data as i32 } } From 2ec6d434419a20356722c2f3c611d22bf1e2033f Mon Sep 17 00:00:00 2001 From: whitequark Date: Sat, 26 Nov 2016 07:26:06 +0000 Subject: [PATCH 4/5] doc: update LLVM configure command (fixes #628). --- doc/manual/installing_from_source.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/manual/installing_from_source.rst b/doc/manual/installing_from_source.rst index b2bbe37a2..0b7eb97ed 100644 --- a/doc/manual/installing_from_source.rst +++ b/doc/manual/installing_from_source.rst @@ -54,7 +54,7 @@ and the ARTIQ kernels. $ mkdir build $ cd build - $ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DLLVM_ENABLE_ASSERTIONS=ON + $ cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr/local/llvm-or1k -DLLVM_TARGETS_TO_BUILD="OR1K;X86" -DLLVM_ENABLE_ASSERTIONS=ON -DLLVM_INSTALL_UTILS=ON $ make -j4 $ sudo make install From c5b55c1dfe5854bf119283e3ce1d5cb771bd5979 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 29 Nov 2016 10:45:07 +0800 Subject: [PATCH 5/5] applets: compatibility with older Qt. Closes #629 --- artiq/gui/applets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/artiq/gui/applets.py b/artiq/gui/applets.py index 91636d601..d440120fa 100644 --- a/artiq/gui/applets.py +++ b/artiq/gui/applets.py @@ -518,7 +518,7 @@ class AppletsDock(QtWidgets.QDockWidget): item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable | QtCore.Qt.ItemIsUserCheckable | - QtCore.Qt.ItemIsAutoTristate | + QtCore.Qt.ItemIsTristate | QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled | QtCore.Qt.ItemIsEnabled)