From 31e58c3337f2e948d7eacffde971ca31e4fddbca Mon Sep 17 00:00:00 2001 From: bunnie Date: Fri, 22 Jan 2021 04:11:02 +0800 Subject: [PATCH] add benchmarks. this commit exhibits a mysterious problem with Lookup API --- Cargo.lock | 26 ++++ Cargo.toml | 6 +- services/benchmark-target/Cargo.toml | 20 +++ services/benchmark-target/src/api.rs | 37 ++++++ services/benchmark-target/src/lib.rs | 23 ++++ services/benchmark-target/src/main.rs | 37 ++++++ services/benchmark/Cargo.toml | 24 ++++ services/benchmark/src/main.rs | 182 ++++++++++++++++++++++++++ xous-rs/src/names.rs | 4 +- xtask/src/main.rs | 4 +- 10 files changed, 360 insertions(+), 3 deletions(-) create mode 100644 services/benchmark-target/Cargo.toml create mode 100644 services/benchmark-target/src/api.rs create mode 100644 services/benchmark-target/src/lib.rs create mode 100644 services/benchmark-target/src/main.rs create mode 100644 services/benchmark/Cargo.toml create mode 100644 services/benchmark/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index 2c15ac31f..84f86a0b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -59,6 +59,32 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +[[package]] +name = "benchmark" +version = "0.1.0" +dependencies = [ + "benchmark-target", + "blitstr-ref", + "graphics-server", + "log", + "log-server", + "ticktimer-server", + "utralib", + "xous", + "xous-names", +] + +[[package]] +name = "benchmark-target" +version = "0.1.0" +dependencies = [ + "log", + "log-server", + "utralib", + "xous", + "xous-names", +] + [[package]] name = "bitflags" version = "1.2.1" diff --git a/Cargo.toml b/Cargo.toml index f271db613..ce5605955 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,6 +14,8 @@ members = [ "services/keyboard", "services/trng", "services/gam", + "services/benchmark", + "services/benchmark-target", "svd2utra", "xtask", "imports/blitstr-ref", @@ -32,7 +34,9 @@ default-members = [ "services/trng", "services/gam", "imports/blitstr-ref", - "imports/com_rs-ref" + "imports/com_rs-ref", + "services/benchmark", + "services/benchmark-target", ] # These packages have custom RUSTFLAGS, so if they diff --git a/services/benchmark-target/Cargo.toml b/services/benchmark-target/Cargo.toml new file mode 100644 index 000000000..e1ce4e125 --- /dev/null +++ b/services/benchmark-target/Cargo.toml @@ -0,0 +1,20 @@ +[package] +name = "benchmark-target" +version = "0.1.0" +authors = ["bunnie "] +edition = "2018" +description = "Benchmark target for Xous" + +[dependencies] +xous = { path = "../../xous-rs" } +xous-names = { path = "../xous-names" } +log-server = { path = "../log-server" } +log = "0.4" + +[target.'cfg(not(any(windows,unix)))'.dependencies] +utralib = { path = "../../utralib"} + +[features] +debugprint = [] +# default = ["debugprint"] # "debugprint" +default = [] diff --git a/services/benchmark-target/src/api.rs b/services/benchmark-target/src/api.rs new file mode 100644 index 000000000..4d55ed36f --- /dev/null +++ b/services/benchmark-target/src/api.rs @@ -0,0 +1,37 @@ +use xous::{Message, ScalarMessage}; +use xous_names::api::Lookup; + +#[allow(dead_code)] +#[derive(Debug)] +pub enum Opcode { + TestScalar(u32), + TestMemory(Lookup), +} + +impl core::convert::TryFrom<& Message> for Opcode { + type Error = &'static str; + fn try_from(message: & Message) -> Result { + match message { + Message::BlockingScalar(m) => match m.id { + 0 => Ok(Opcode::TestScalar(m.arg1 as u32)), + _ => Err("BENCHMARK-TARGET api: unknown BlockingScalar ID"), + }, + _ => Err("BENCHMARK-TARGET api: unhandled message type"), + } + } +} + +impl Into for Opcode { + fn into(self) -> Message { + match self { + Opcode::TestScalar(count) => Message::BlockingScalar(ScalarMessage { + id: 0, + arg1: count as usize, + arg2: 0, + arg3: 0, + arg4: 0, + }), + _ => panic!("GFX api: Opcode type not handled by Into(), maybe you meant to use a helper method?"), + } + } +} diff --git a/services/benchmark-target/src/lib.rs b/services/benchmark-target/src/lib.rs new file mode 100644 index 000000000..b7c5ed7b8 --- /dev/null +++ b/services/benchmark-target/src/lib.rs @@ -0,0 +1,23 @@ +#![cfg_attr(target_os = "none", no_std)] + +pub mod api; +use xous::{CID, send_message}; +use xous_names::api::Lookup; +use xous::ipc::Sendable; + +pub fn test_scalar(cid: CID, testvar: u32) -> Result { + let response = send_message(cid, api::Opcode::TestScalar(testvar).into())?; + if let xous::Result::Scalar1(r) = response { + Ok(r as u32) + } else { + panic!("unexpected return value: {:#?}", response); + } +} + +pub fn test_memory(cid: CID, testvar: u32) -> Result { + let reg = Lookup::new(); + let mut sendable_reg = Sendable::new(reg).expect("can't create test structure"); + sendable_reg.challenge[0] = testvar; + sendable_reg.lend_mut(cid, 0).expect("test failure"); + Ok(sendable_reg.challenge[0]) +} \ No newline at end of file diff --git a/services/benchmark-target/src/main.rs b/services/benchmark-target/src/main.rs new file mode 100644 index 000000000..3d3dd29fa --- /dev/null +++ b/services/benchmark-target/src/main.rs @@ -0,0 +1,37 @@ +#![cfg_attr(target_os = "none", no_std)] +#![cfg_attr(target_os = "none", no_main)] + +mod api; +use api::*; + +use xous_names::api::Lookup; + +use core::convert::TryFrom; + +use log::{error, info}; + +#[xous::xous_main] +fn xmain() -> ! { + log_server::init_wait().unwrap(); + + let bench_sid = xous_names::register_name(xous::names::SERVER_NAME_BENCHMARK).expect("BENCHTARGET: can't register server"); + info!("BENCHTARGET: registered with NS -- {:?}", bench_sid); + + loop { + let envelope = xous::receive_message(bench_sid).unwrap(); + if let Ok(opcode) = Opcode::try_from(&envelope.body) { + match opcode { + Opcode::TestScalar(val) => { + xous::return_scalar(envelope.sender, (val + 1) as usize) + .expect("BENCHTARGET: couldn't return TestScalar request"); + }, + _ => error!("BENCHTARGET: opcode not yet implemented"), + } + } else if let xous::Message::MutableBorrow(m) = &envelope.body { + let lookup: &mut Lookup = unsafe { &mut *(m.buf.as_mut_ptr() as *mut Lookup) }; + lookup.challenge[0] = lookup.challenge[0] + 1; + } else { + error!("BENCHTARGET: couldn't convert opcode"); + } + } +} diff --git a/services/benchmark/Cargo.toml b/services/benchmark/Cargo.toml new file mode 100644 index 000000000..1af6f5a9a --- /dev/null +++ b/services/benchmark/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "benchmark" +version = "0.1.0" +authors = ["bunnie "] +edition = "2018" +description = "Benchmarks for Xous" + +[dependencies] +xous = { path = "../../xous-rs" } +graphics-server = { path = "../graphics-server" } +ticktimer-server = { path = "../ticktimer-server" } +xous-names = { path = "../xous-names" } +log-server = { path = "../log-server" } +log = "0.4" +blitstr-ref = { path = "../../imports/blitstr-ref" } +benchmark-target = { path = "../benchmark-target" } + +[target.'cfg(not(any(windows,unix)))'.dependencies] +utralib = { path = "../../utralib"} + +[features] +debugprint = [] +# default = ["debugprint"] # "debugprint" +default = [] diff --git a/services/benchmark/src/main.rs b/services/benchmark/src/main.rs new file mode 100644 index 000000000..3cdfabc2d --- /dev/null +++ b/services/benchmark/src/main.rs @@ -0,0 +1,182 @@ +#![cfg_attr(target_os = "none", no_std)] +#![cfg_attr(target_os = "none", no_main)] + +use blitstr_ref as blitstr; +use blitstr::{Cursor, GlyphStyle}; +use core::fmt::Write; +use graphics_server::{DrawStyle, PixelColor, Point, Rectangle}; + +use log::{error, info}; +use xous::{String, Message, ScalarMessage}; + +use core::convert::TryFrom; + +pub enum Opcode { + Start, + Stop, +} + +impl core::convert::TryFrom<& Message> for Opcode { + type Error = &'static str; + fn try_from(message: & Message) -> Result { + match message { + Message::Scalar(m) => match m.id { + 0 => Ok(Opcode::Start), + 1 => Ok(Opcode::Stop), + _ => Err("BENCHMARK api: unknown Scalar ID"), + }, + _ => Err("BENCHMARK api: unhandled message type"), + } + } +} + +impl Into for Opcode { + fn into(self) -> Message { + match self { + Opcode::Start => Message::Scalar(ScalarMessage { + id: 0, + arg1: 0, + arg2: 0, + arg3: 0, + arg4: 0, + }), + Opcode::Stop => Message::Scalar(ScalarMessage { + id: 1, + arg1: 0, + arg2: 0, + arg3: 0, + arg4: 0, + }), + } + } +} + +fn stopwatch_thread(_arg: xous::SID) { + info!("BENCHMARK|stopwatch: starting"); + + let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap(); + let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap(); + + let shell_conn = xous_names::request_connection_blocking(xous::names::SERVER_NAME_SHELL).expect("BENCHMARK|stopwatch: can't connect to main program"); + let mut last_time: u64 = ticktimer_server::elapsed_ms(ticktimer_conn).unwrap(); + let mut start_sent = false; + loop { + if let Ok(elapsed_time) = ticktimer_server::elapsed_ms(ticktimer_conn) { + if elapsed_time - last_time > 500 && !start_sent { + last_time = elapsed_time; + xous::send_message(shell_conn, Opcode::Start.into()).expect("BENCHMARK|stopwatch: couldn't send Start message"); + start_sent = true; + } else if elapsed_time - last_time > 10_000 && start_sent { + last_time = elapsed_time; + start_sent = false; + xous::send_message(shell_conn, Opcode::Stop.into()).expect("BENCHMARK|stopwatch: couldn't send Stop message"); + } + } else { + error!("error requesting ticktimer!") + } + if false { + // send a start loop message + xous::send_message(shell_conn, Opcode::Start.into()).expect("BENCHMARK|stopwatch: couldn't send Start message"); + ticktimer_server::sleep_ms(ticktimer_conn, 10_000).expect("couldn't sleep"); + // send a stop loop message + xous::send_message(shell_conn, Opcode::Stop.into()).expect("BENCHMARK|stopwatch: couldn't send Stop message"); + // give a moment for the result to update + ticktimer_server::sleep_ms(ticktimer_conn, 500).expect("couldn't sleep"); + } + xous::yield_slice(); + } +} + +#[xous::xous_main] +fn shell_main() -> ! { + log_server::init_wait().unwrap(); + + info!("BENCHMARK: ticktimer"); + let ticktimer_server_id = xous::SID::from_bytes(b"ticktimer-server").unwrap(); + let ticktimer_conn = xous::connect(ticktimer_server_id).unwrap(); + + let shell_server = xous_names::register_name(xous::names::SERVER_NAME_SHELL).expect("BENCHMARK: can't register server"); + + let graphics_conn = xous_names::request_connection_blocking(xous::names::SERVER_NAME_GFX).expect("BENCHMARK: can't connect to COM"); + let target_conn = xous_names::request_connection_blocking(xous::names::SERVER_NAME_BENCHMARK).expect("BENCHMARK: can't connect to COM"); + + xous::create_thread_simple(stopwatch_thread, shell_server).unwrap(); + info!("BENCHMARK: stopwatch thread started"); + + let screensize = graphics_server::screen_size(graphics_conn).expect("Couldn't get screen size"); + + let mut string_buffer = String::new(4096); + + graphics_server::set_glyph_style(graphics_conn, GlyphStyle::Small) + .expect("unable to set glyph"); + let (_, font_h) = graphics_server::query_glyph(graphics_conn).expect("unable to query glyph"); + let status_clipregion = + Rectangle::new_coords_with_style(4, 0, screensize.x, font_h as i16 * 4, DrawStyle::new(PixelColor::Light, PixelColor::Light, 1)); + + graphics_server::draw_rectangle(graphics_conn, status_clipregion) + .expect("unable to clear region"); + + string_buffer.clear(); + write!(&mut string_buffer, "First pass, please wait..."); + let status_cursor = Cursor::from_top_left_of(status_clipregion.into()); + graphics_server::set_cursor(graphics_conn, status_cursor).expect("can't set cursor"); + graphics_server::draw_string(graphics_conn, &string_buffer).expect("unable to draw string"); + graphics_server::flush(graphics_conn).expect("unable to draw to screen"); + + let mut start_time: u64 = 0; + let mut stop_time: u64 = 0; + let mut update_result: bool = false; + let mut count: u32 = 0; + let mut check_count: u32 = 0; + loop { + let maybe_env = xous::try_receive_message(shell_server).unwrap(); + match maybe_env { + Some(envelope) => { + info!("BENCHMARK: Message: {:?}", envelope); + if let Ok(opcode) = Opcode::try_from(&envelope.body) { + match opcode { + Opcode::Start => { + start_time = ticktimer_server::elapsed_ms(ticktimer_conn).unwrap(); + }, + Opcode::Stop => { + stop_time = ticktimer_server::elapsed_ms(ticktimer_conn).unwrap(); + update_result = true; + }, + } + } else { + error!("BENCHMARK: couldn't convert opcode"); + } + } + None => (), // don't yield, we are trying to run the loop as fast as we can... + } + + // actual benchmark + // get a scalar message + if false { + // measured at 1349 iterations per second in this loop + count = benchmark_target::test_scalar(target_conn, count).expect("BENCHMARK: couldn't send test message"); + check_count = check_count + 1; + } else { + count = benchmark_target::test_memory(target_conn, count).expect("BENCHMARK: couldn't send test message"); + check_count = check_count + 1; + } + + if update_result { + update_result = false; + + graphics_server::draw_rectangle(graphics_conn, status_clipregion) + .expect("unable to clear region"); + + string_buffer.clear(); + write!(&mut string_buffer, "Elapsed: {}, count: {}, check: {}", + stop_time - start_time, count, check_count).unwrap(); + let status_cursor = Cursor::from_top_left_of(status_clipregion.into()); + graphics_server::set_cursor(graphics_conn, status_cursor).expect("can't set cursor"); + graphics_server::draw_string(graphics_conn, &string_buffer).expect("unable to draw string"); + graphics_server::flush(graphics_conn).expect("unable to draw to screen"); + + count = 0; + check_count = 0; + } + } +} diff --git a/xous-rs/src/names.rs b/xous-rs/src/names.rs index bc5e4715b..e61024198 100644 --- a/xous-rs/src/names.rs +++ b/xous-rs/src/names.rs @@ -8,12 +8,14 @@ for the core set of kernel services. pub const SERVER_NAME_COM: &str = "_COM manager_"; pub const SERVER_NAME_SHELL: &str = "_Shell_"; pub const SERVER_NAME_GFX: &str = "_Graphics_"; -pub const SERVER_NAME_FCCAGENT: &str = "_Agent for EMC Testing_"; pub const SERVER_NAME_KBD: &str = "_Matrix keyboard driver_"; pub const SERVER_NAME_TRNG: &str = "_TRNG manager_"; pub const SERVER_NAME_GAM: &str = "_Graphical Abstraction Manager_"; pub const SERVER_NAME_STATUS: &str = "_Status bar manager_"; +pub const SERVER_NAME_FCCAGENT: &str = "_Agent for EMC Testing_"; +pub const SERVER_NAME_BENCHMARK: &str= "_Benchmark target_"; + /* Global message IDs diff --git a/xtask/src/main.rs b/xtask/src/main.rs index a10d33635..a09f2a2bc 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -79,8 +79,10 @@ fn build_hw_image(debug: bool, svd: Option) -> Result<(), DynError> { let kernel = build_kernel(debug)?; let mut init = vec![]; for pkg in &[ - "shell", + //"shell", //"gam", + "benchmark", + "benchmark-target", "graphics-server", "ticktimer-server", "log-server",