diff --git a/crsn/src/asm/instr/mod.rs b/crsn/src/asm/instr/mod.rs index d936545..1c69c87 100644 --- a/crsn/src/asm/instr/mod.rs +++ b/crsn/src/asm/instr/mod.rs @@ -11,7 +11,7 @@ pub mod cond; mod flatten; /// A higher-level instruction -#[derive(Debug, Clone)] +#[derive(Debug)] pub struct Instr { pub op: OpWrapper, pub branches: Option)>>, diff --git a/crsn/src/asm/instr/op.rs b/crsn/src/asm/instr/op.rs index cd3ffd4..7fc5a1a 100644 --- a/crsn/src/asm/instr/op.rs +++ b/crsn/src/asm/instr/op.rs @@ -1,8 +1,5 @@ use std::fmt::Debug; -use dyn_clonable::*; -use sexp::Sexp; - use crate::asm::data::{ literal::DebugMsg, literal::Label, literal::RoutineName, @@ -11,13 +8,13 @@ use crate::asm::data::{ }; use crate::asm::error::Error; use crate::asm::instr::Cond; +use crate::asm::parse::arg_parser::ArgParser; use crate::runtime::fault::Fault; use crate::runtime::frame::{CallStack, StackFrame}; use crate::runtime::program::Program; -use crate::asm::parse::arg_parser::ArgParser; /// A higher level simple opration -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum OpWrapper { /// Mark a jump target. Label(Label), @@ -30,7 +27,7 @@ pub enum OpWrapper { } /// A low level instruction -#[derive(Clone, Debug)] +#[derive(Debug)] pub enum Op { /// Do nothing Nop, @@ -72,18 +69,16 @@ impl From for OpWrapper { } } -#[clonable] -pub trait OpTrait: Clone + Debug + Send + 'static { +pub trait OpTrait: Debug + Send + Sync + 'static { fn execute(&self, program: &Program, call_stack: &mut CallStack, frame: &mut StackFrame) -> Result<(), Fault>; } pub enum ParseOpResult { - Parsed(Box), + Parsed(Box), Unknown(ArgParser), } -#[clonable] -pub trait AsmModule: Clone + Debug + Send + 'static { +pub trait AsmModule: Debug + Send + 'static { /// Get name of the module fn name(&self) -> &'static str; diff --git a/crsn/src/asm/mod.rs b/crsn/src/asm/mod.rs index 859f0e5..00c9e96 100644 --- a/crsn/src/asm/mod.rs +++ b/crsn/src/asm/mod.rs @@ -12,326 +12,3 @@ pub fn assemble(source: &str, parsers: &[Box]) -> Result, let parsed = parse::parse(source, parsers)?; Ok(lower(parsed)?) } - -#[cfg(test)] -mod tests { - use std::sync::atomic::AtomicU32; - - use crate::asm::data::{DstDisp, Rd, Register, SrcDisp, Wr}; - use crate::asm::data::literal::{Addr, Label}; - use crate::asm::instr::{Flatten, OpWrapper, Instr, lower, Op}; - use crate::asm::instr::Cond; - use crate::asm::parse::{parse, parse_instructions}; - - #[test] - fn test_parse_empty() { - let parsed = parse(" - () - ").unwrap(); - assert_eq!(Vec::::new(), parsed); - } - - #[test] - fn test_parse_empty_routine() { - let parsed = parse(" - ( - (hello) - ) - ").unwrap(); - assert_eq!(vec![ - OpWrapper::Op(Op::Routine("hello".into())), - OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into()))) - ], parsed); - - let parsed = parse(" - ( - (hello) - (world) - ) - ").unwrap(); - assert_eq!(vec![ - OpWrapper::Op(Op::Routine("hello".into())), - OpWrapper::Op(Op::Barrier(Some("Routine \"hello\" overrun".into()))), - OpWrapper::Op(Op::Routine("world".into())), - OpWrapper::Op(Op::Barrier(Some("Routine \"world\" overrun".into()))) - ], parsed); - } - - #[test] - fn test_parse_data_formats() { - let parsed = parse(" - ( - (move - (mov r0 r1) - (mov r15 7) - (mov r15 0xabcd) - (mov r7 0b11110000) - (mov r7 arg1) - (mov r255 arg255) - (mov r7 res0) - (mov r7 res255) - (mov @r0 @r0) ; test in both Rd and Wr positions - (mov @r0 @arg0) - (mov @r0 @res0) - (mov @123456 @0x123456) - (mov @0b010101 @0b010101) - ) - ) - ").unwrap(); - assert_eq!(vec![ - OpWrapper::Op(Op::Routine("move".into())), - // (mov r0 r1) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - // (mov r15 7) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(15))), - Rd::new(SrcDisp::Immediate(7)), - )), - // (mov r15 0xabcd) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(15))), - Rd::new(SrcDisp::Immediate(0xabcd)), - )), - // (mov r7 0b11110000) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(7))), - Rd::new(SrcDisp::Immediate(0b11110000)), - )), - // (mov r7 arg1) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(7))), - Rd::new(SrcDisp::Register(Register::Arg(1))), - )), - // (mov r255 arg255) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(255))), - Rd::new(SrcDisp::Register(Register::Arg(255))), - )), - // (mov r7 res0) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(7))), - Rd::new(SrcDisp::Register(Register::Res(0))), - )), - // (mov r7 res255) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(7))), - Rd::new(SrcDisp::Register(Register::Res(255))), - )), - // (mov @r0 @r0) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), - Rd::new(SrcDisp::RegisterPtr(Register::Gen(0))), - )), - // (mov @r0 @arg0) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), - Rd::new(SrcDisp::RegisterPtr(Register::Arg(0))), - )), - // (mov @r0 @res0) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::RegisterPtr(Register::Gen(0))), - Rd::new(SrcDisp::RegisterPtr(Register::Res(0))), - )), - // (mov @123456 @0x123456) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::ImmediatePtr(Addr(123456))), - Rd::new(SrcDisp::ImmediatePtr(Addr(0x123456))), - )), - // (mov @0b010101 @0b010101) - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::ImmediatePtr(Addr(0b010101))), - Rd::new(SrcDisp::ImmediatePtr(Addr(0b010101))), - )), - OpWrapper::Op(Op::Barrier(Some("Routine \"move\" overrun".into()))), - ], parsed); - } - - fn parse_single_instr(src: &str) -> anyhow::Result { - Ok(parse_instructions(vec![sexp::parse(src)?])?.remove(0)) - } - - fn parse_single_op(src: &str) -> anyhow::Result> { - let num = AtomicU32::new(0); - Ok(parse_single_instr(src)?.flatten(&num)?) - } - - #[test] - fn test_parse_single() { - let parsed = parse_single_op("(mov r0 r1)").unwrap(); - assert_eq!(vec![ - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - ], parsed); - } - - #[test] - fn test_branches_instr() { - let parsed = parse_single_instr(" - (cmp r0 r1 (eq? (mov r0 r0) (mov r1 r2)) (>? (mov r0 r0) (mov r1 r1))) - ").unwrap(); - assert_eq!( - Instr { - op: OpWrapper::Op(Op::Cmp( - Rd::new(SrcDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - branches: Some(vec![ - ( - Cond::Equal, - vec![ - Instr { - op: OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - )), - branches: None, - }, - Instr { - op: OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(1))), - Rd::new(SrcDisp::Register(Register::Gen(2))), - )), - branches: None, - } - ] - ), - ( - Cond::Greater, - vec![ - Instr { - op: OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - )), - branches: None, - }, - Instr { - op: OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(1))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - branches: None, - } - ] - ) - ]), - } - , parsed); - } - - #[test] - fn test_branches_op() { - let parsed = parse_single_op(" - (cmp r0 r1 - (eq? - (mov r0 r0) - (mov r1 r2)) - (>? - (mov r0 r0) - (mov r1 r1))) - ").unwrap(); - assert_eq!( - vec![ - OpWrapper::Op(Op::Cmp( - Rd::new(SrcDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - OpWrapper::JumpIf(Cond::NotEqual, Label::Numbered(1)), - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - )), - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(1))), - Rd::new(SrcDisp::Register(Register::Gen(2))), - )), - OpWrapper::Jump(Label::Numbered(0)), - OpWrapper::Label(Label::Numbered(1)), - OpWrapper::JumpIf(Cond::LowerOrEqual, Label::Numbered(0)), - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - )), - OpWrapper::Op(Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(1))), - Rd::new(SrcDisp::Register(Register::Gen(1))), - )), - OpWrapper::Label(Label::Numbered(0)), - ], parsed); - } - - - #[test] - fn test_jumps_to_skips() { - let parsed = parse("( - (foo - (:foo) - (:unused) - (:whatever) - (mov r0 r0) - (j :foo) - (j :foo) - (mov r0 r0) - (mov r0 r0) - (j :whatever) - (j.if eq :whatever) - ) - )").unwrap(); - - assert_eq!( - vec![ - Op::Routine("foo".into()).into(), - OpWrapper::Label(Label::Named("foo".to_string())), - OpWrapper::Label(Label::Named("unused".to_string())), - OpWrapper::Label(Label::Named("whatever".to_string())), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ).into(), - OpWrapper::Jump(Label::Named("foo".to_string())), - OpWrapper::Jump(Label::Named("foo".to_string())), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ).into(), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ).into(), - OpWrapper::Jump(Label::Named("whatever".to_string())), - OpWrapper::JumpIf(Cond::Equal, Label::Named("whatever".to_string())), - Op::Barrier(Some("Routine \"foo\" overrun".into())).into(), - ], parsed); - - // Labels are removed and jumps become skips - - let cleaned = lower(parsed).unwrap(); - - assert_eq!( - vec![ - Op::Routine("foo".into()), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Skip(Rd::new(SrcDisp::Immediate(-1))), - Op::Skip(Rd::new(SrcDisp::Immediate(-2))), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Mov( - Wr::new(DstDisp::Register(Register::Gen(0))), - Rd::new(SrcDisp::Register(Register::Gen(0))), - ), - Op::Skip(Rd::new(SrcDisp::Immediate(-5))), - Op::SkipIf(Cond::Equal, Rd::new(SrcDisp::Immediate(-6))), - Op::Barrier(Some("Routine \"foo\" overrun".into())), - ], cleaned); - } -} diff --git a/crsn/src/asm/parse/parse_op.rs b/crsn/src/asm/parse/parse_op.rs index e6a4ab4..e13bd63 100644 --- a/crsn/src/asm/parse/parse_op.rs +++ b/crsn/src/asm/parse/parse_op.rs @@ -1,16 +1,13 @@ -use sexp::Sexp; - use crate::asm::data::literal::{Label, RoutineName}; -use crate::asm::error::{AsmError, Error}; -use crate::asm::instr::{OpWrapper, Op}; +use crate::asm::error::Error; +use crate::asm::instr::{Op, OpWrapper}; use crate::asm::instr::cond::parse_cond; use crate::asm::instr::op::{AsmModule, ParseOpResult}; -use crate::asm::parse::parse_data::{parse_label, parse_rd, parse_wr}; -use crate::asm::parse::sexp_expect::expect_string_atom; use crate::asm::parse::arg_parser::ArgParser; +use crate::asm::parse::parse_data::{parse_label, parse_rd}; +use crate::asm::parse::sexp_expect::expect_string_atom; pub fn parse_op(keyword: &str, far: bool, mut arg_tokens: ArgParser, parsers: &[Box]) -> Result { - Ok(match keyword { "j" => { let dest = parse_label(arg_tokens.next())?; diff --git a/crsn/src/runtime/fault.rs b/crsn/src/runtime/fault.rs index 4498342..c76275f 100644 --- a/crsn/src/runtime/fault.rs +++ b/crsn/src/runtime/fault.rs @@ -60,6 +60,9 @@ pub enum Fault { #[error("Call stack underflow")] CallStackUnderflow, + + #[error("Attempt to read undefined extension data store")] + ExtDataNotDefined, } #[derive(Error, Debug)] diff --git a/crsn/src/runtime/program.rs b/crsn/src/runtime/program.rs index e172aa3..1713e12 100644 --- a/crsn/src/runtime/program.rs +++ b/crsn/src/runtime/program.rs @@ -1,10 +1,12 @@ + use std::collections::HashMap; use crate::asm::data::literal::{Addr, Label, RoutineName}; use crate::asm::instr::Op; use crate::runtime::fault::Fault; +use std::sync::Arc; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct Program { ops: Vec, routines: HashMap, @@ -13,7 +15,7 @@ pub struct Program { } impl Program { - pub fn new(ops: Vec) -> Self { + pub fn new(ops: Vec) -> Arc { let mut p = Self { ops, routines: Default::default(), @@ -21,7 +23,7 @@ impl Program { barriers: Default::default(), }; p.scan(); - p + Arc::new(p) } /// Find all the named things diff --git a/crsn/src/runtime/run_thread.rs b/crsn/src/runtime/run_thread.rs index 146b050..4ba46c4 100644 --- a/crsn/src/runtime/run_thread.rs +++ b/crsn/src/runtime/run_thread.rs @@ -1,3 +1,5 @@ +use std::any::{Any, TypeId}; +use std::collections::HashMap; use std::thread::JoinHandle; use std::time::Duration; @@ -5,6 +7,8 @@ use crate::asm::data::literal::Addr; use crate::runtime::exec::EvalRes; use crate::runtime::frame::{CallStack, StackFrame}; use crate::runtime::program::Program; +use std::sync::Arc; + const CYCLE_TIME: Duration = Duration::from_millis(0); //const CYCLE_TIME : Duration = Duration::from_millis(100); @@ -20,11 +24,13 @@ pub struct RunThread { /// Call stack pub call_stack: CallStack, /// Program to run - pub program: Program, + pub program: Arc, + /// Extension data + ext_data: HashMap>, } impl RunThread { - pub fn new(id: ThreadToken, program: Program, pc: Addr, args: &[u64]) -> Self { + pub fn new(id: ThreadToken, program: Arc, pc: Addr, args: &[u64]) -> Self { let sf = StackFrame::new(pc, args); Self { @@ -32,6 +38,7 @@ impl RunThread { frame: sf, call_stack: vec![], program, + ext_data: Default::default(), } } @@ -58,5 +65,13 @@ impl RunThread { } } } -} + pub fn ext_mut(&mut self) -> &mut T { + if !self.ext_data.contains_key(&TypeId::of::()) { + self.ext_data.insert(TypeId::of::(), Box::new(T::default())); + } + + self.ext_data.get_mut(&TypeId::of::()).unwrap() + .downcast_mut().unwrap() + } +} diff --git a/crsn_arith/src/parse.rs b/crsn_arith/src/parse.rs index b981fa1..70d80bd 100644 --- a/crsn_arith/src/parse.rs +++ b/crsn_arith/src/parse.rs @@ -1,8 +1,8 @@ use crsn::asm::data::{Rd, Wr}; -use crsn::asm::error::{AsmError, Error}; -use crsn::asm::instr::op::{AsmModule, OpTrait, ParseOpResult}; -use crsn::asm::parse::parse_data::{parse_rd, parse_wr}; -use crsn::sexp::Sexp; +use crsn::asm::error::{Error}; +use crsn::asm::instr::op::{AsmModule, ParseOpResult}; + + use crate::defs::ArithOp; use crsn::asm::parse::arg_parser::ArgParser;