From 7efa04054c9965c0070d2d1e1c47f249a854496e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20Hru=C5=A1ka?= Date: Sun, 11 Oct 2020 22:56:48 +0200 Subject: [PATCH] make it work with musl (the _nox target does not link the screen module that wouldn't build) --- Cargo.lock | 16 ++ Cargo.toml | 1 + crsn_stdio/src/lib.rs | 14 +- launcher_nox/Cargo.toml | 21 +++ launcher_nox/src/main.rs | 172 ++++++++++++++++++++++ launcher_nox/src/read_file.rs | 14 ++ launcher_nox/src/serde_duration_millis.rs | 18 +++ 7 files changed, 255 insertions(+), 1 deletion(-) create mode 100644 launcher_nox/Cargo.toml create mode 100644 launcher_nox/src/main.rs create mode 100644 launcher_nox/src/read_file.rs create mode 100644 launcher_nox/src/serde_duration_millis.rs diff --git a/Cargo.lock b/Cargo.lock index 22f235e..ba8c491 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -365,6 +365,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "launcher_nox" +version = "0.1.0" +dependencies = [ + "anyhow", + "clappconfig", + "crsn", + "crsn_arith", + "crsn_buf", + "crsn_stdio", + "log", + "serde", + "simple_logger", + "thiserror", +] + [[package]] name = "lazy_static" version = "1.4.0" diff --git a/Cargo.toml b/Cargo.toml index 7691d0d..31d54f3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "launcher", + "launcher_nox", "crsn", "crsn_arith", "crsn_screen", diff --git a/crsn_stdio/src/lib.rs b/crsn_stdio/src/lib.rs index a054a92..c570ce6 100644 --- a/crsn_stdio/src/lib.rs +++ b/crsn_stdio/src/lib.rs @@ -9,6 +9,7 @@ use crsn::sexp::SourcePosition; use std::convert::TryFrom; use std::io; use crsn::asm::instr::cond::Flag; +use std::fmt; mod console { use std::{io}; @@ -98,7 +99,7 @@ mod console { } } -#[derive(Debug, Clone)] +#[derive(Clone)] pub struct StdioOps { old_tio: Option, hdl_stdin : Value, @@ -107,6 +108,17 @@ pub struct StdioOps { hdl_stdout_raw : Value, } +impl fmt::Debug for StdioOps { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("StdioOps") + .field("hdl_stdin", &format_args!("0x{:08x}", self.hdl_stdin)) + .field("hdl_stdin_raw", &format_args!("0x{:08x}", self.hdl_stdin_raw)) + .field("hdl_stdout", &format_args!("0x{:08x}", self.hdl_stdout)) + .field("hdl_stdout_raw", &format_args!("0x{:08x}", self.hdl_stdout_raw)) + .finish() + } +} + impl StdioOps { pub fn new() -> Box { Box::new(Self { diff --git a/launcher_nox/Cargo.toml b/launcher_nox/Cargo.toml new file mode 100644 index 0000000..c6d197d --- /dev/null +++ b/launcher_nox/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "launcher_nox" +version = "0.1.0" +authors = ["Ondřej Hruška "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +crsn = { path = "../crsn" } +crsn_arith = { path = "../crsn_arith" } +crsn_buf = { path = "../crsn_buf" } +crsn_stdio = { path = "../crsn_stdio" } + +simple_logger = "1.9.0" +log = "0.4.11" +thiserror = "1.0.20" +anyhow = "1.0.32" +clappconfig = "0.4.0" + +serde = { version = "1.0.116", features = ["derive"] } diff --git a/launcher_nox/src/main.rs b/launcher_nox/src/main.rs new file mode 100644 index 0000000..d4d6a6c --- /dev/null +++ b/launcher_nox/src/main.rs @@ -0,0 +1,172 @@ +#[macro_use] +extern crate log; + +use std::collections::HashMap; + +use std::time::Duration; + +use clappconfig::{AppConfig, clap}; +use clappconfig::clap::ArgMatches; +use serde::{Deserialize, Serialize}; + +use crsn::asm::data::literal::Addr; +use crsn::module::{OpTrait, CrsnUniq}; +use crsn::runtime::run_thread::{RunThread, ThreadToken, ThreadParams}; +use crsn_arith::ArithOps; +use crsn_stdio::StdioOps; +use crsn_buf::BufOps; + +mod read_file; +mod serde_duration_millis; + +#[derive(Debug, Clone, Serialize, Deserialize)] +struct LogConfig { + level: String, + modules: HashMap, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] +struct Config { + log: LogConfig, + #[serde(skip)] + program_file: String, + #[serde(skip)] + assemble_only: bool, + #[serde(with = "serde_duration_millis")] + cycle_time: Duration, +} + +impl Default for Config { + fn default() -> Self { + Self { + log: LogConfig { + level: "warn".to_string(), + modules: Default::default(), + }, + program_file: "".to_string(), + assemble_only: false, + cycle_time: Duration::default(), + } + } +} + +impl AppConfig for Config { + type Init = Self; + + fn logging(&self) -> &str { + &self.log.level + } + + fn logging_mod_levels(&self) -> Option<&HashMap> { + Some(&self.log.modules) + } + + fn pre_log_println(_message: String) { + // shut up + } + + fn print_banner(_name: &str, _version: &str) { + // No banner + } + + /// Add args to later use in the `configure` method. + fn add_args<'a: 'b, 'b>(clap: clap::App<'a, 'b>) -> clap::App<'a, 'b> { + // Default impl + clap + .arg( + clap::Arg::with_name("input") + .value_name("FILE") + .help("Program to run") + .required_unless("default-config") + .takes_value(true), + ) + .arg( + clap::Arg::with_name("asm-only") + .short("P") + .long("asm") + .help("Only assemble, do not run."), + ) + .arg( + clap::Arg::with_name("cycle") + .long("cycle") + .short("C") + .value_name("MICROS") + .help("Cycle time (us, append \"s\" or \"ms\" for coarser time)") + .takes_value(true), + ) + } + + fn configure(mut self, clap: &ArgMatches) -> anyhow::Result { + self.program_file = clap.value_of("input").unwrap().to_string(); + self.assemble_only = clap.is_present("asm-only"); + if let Some(t) = clap.value_of("cycle") { + let (t, mul) = if t.ends_with("us") { + (&t[..(t.len()-2)], 1) + } else if t.ends_with("ms") { + (&t[..(t.len()-2)], 1000) + } else if t.ends_with("m") { + (&t[..(t.len()-1)], 1000) + } else if t.ends_with("u") { + (&t[..(t.len()-1)], 1) + } else if t.ends_with("s") { + (&t[..(t.len()-1)], 1000_000) + } else { + (t, 1) + }; + + self.cycle_time = Duration::from_micros(t.parse::().expect("parse -C value") * mul); + println!("ct = {:?}", self.cycle_time); + } + Ok(self) + } +} + + +fn main() -> anyhow::Result<()> { + let config = Config::init("crsn", "crsn.json5", env!("CARGO_PKG_VERSION"))?; + + debug!("Loading {}", config.program_file); + + let source = read_file::read_file(&config.program_file)?; + + let uniq = CrsnUniq::new(); + + let parsed = crsn::asm::assemble(&source, &uniq, vec![ + ArithOps::new(), + BufOps::new(), + StdioOps::new(), + ])?; + + if config.assemble_only { + for (n, op) in parsed.ops.iter().enumerate() { + println!("{:04} : {}", n, op.to_sexp()); + } + return Ok(()); + } else { + trace!("--- Compiled program ---"); + for (n, op) in parsed.ops.iter().enumerate() { + trace!("{:04} : {}", n, op.to_sexp()); + } + trace!("------------------------"); + } + + debug!("Start runtime"); + + let args = &[]; + let thread = RunThread::new(ThreadParams { + id: ThreadToken(0), + uniq, + program: parsed, + pc: Addr(0), + cycle_time: config.cycle_time, + args + }); + + // run without spawning, so it is on the main thread - required by some extensions + thread.run(); + + debug!("Runtime shut down."); + + Ok(()) +} diff --git a/launcher_nox/src/read_file.rs b/launcher_nox/src/read_file.rs new file mode 100644 index 0000000..5ac24b8 --- /dev/null +++ b/launcher_nox/src/read_file.rs @@ -0,0 +1,14 @@ +use std::fs::File; +use std::io; +use std::io::Read; +use std::path::Path; + +/// Read a file to string +pub fn read_file>(path: P) -> io::Result { + let path = path.as_ref(); + let mut file = File::open(path)?; + + let mut buf = String::new(); + file.read_to_string(&mut buf)?; + Ok(buf) +} diff --git a/launcher_nox/src/serde_duration_millis.rs b/launcher_nox/src/serde_duration_millis.rs new file mode 100644 index 0000000..306ad82 --- /dev/null +++ b/launcher_nox/src/serde_duration_millis.rs @@ -0,0 +1,18 @@ +use std::time::Duration; + +use serde::{self, Deserialize, Deserializer, Serializer}; + +pub fn serialize(value: &Duration, se: S) -> Result + where + S: Serializer, +{ + se.serialize_u64(value.as_secs() * 1000 + value.subsec_millis() as u64) +} + +pub fn deserialize<'de, D>(de: D) -> Result + where + D: Deserializer<'de>, +{ + let s: u64 = u64::deserialize(de)?; + Ok(Duration::from_millis(s)) +}