forked from MightyPork/crsn
@reg and @value reading and writing is now possible
This commit is contained in:
+29
-13
@@ -25,10 +25,12 @@ mod wr;
|
||||
pub enum DataDisp {
|
||||
/// Constant value
|
||||
Immediate(Value),
|
||||
/// Object pointer with immediate value
|
||||
ImmObject(Value),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Object pointer
|
||||
ObjectPtr(Register),
|
||||
/// Object pointer in register
|
||||
RegObject(Register),
|
||||
/// Discard the written value
|
||||
Discard,
|
||||
}
|
||||
@@ -42,9 +44,12 @@ impl Display for DataDisp {
|
||||
DataDisp::Register(r) => {
|
||||
write!(f, "{}", r)
|
||||
}
|
||||
DataDisp::ObjectPtr(r) => {
|
||||
DataDisp::RegObject(r) => {
|
||||
write!(f, "@{}", r)
|
||||
}
|
||||
DataDisp::ImmObject(r) => {
|
||||
write!(f, "@{:#x}", r)
|
||||
}
|
||||
DataDisp::Discard => {
|
||||
write!(f, "_")
|
||||
}
|
||||
@@ -57,7 +62,8 @@ impl From<RdData> for DataDisp {
|
||||
match s {
|
||||
RdData::Immediate(x) => DataDisp::Immediate(x),
|
||||
RdData::Register(x) => DataDisp::Register(x),
|
||||
RdData::ObjectPtr(x) => DataDisp::ObjectPtr(x),
|
||||
RdData::RegObject(x) => DataDisp::RegObject(x),
|
||||
RdData::ImmObject(x) => DataDisp::ImmObject(x),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +72,8 @@ impl From<WrData> for DataDisp {
|
||||
fn from(s: WrData) -> Self {
|
||||
match s {
|
||||
WrData::Register(x) => DataDisp::Register(x),
|
||||
WrData::ObjectPtr(x) => DataDisp::ObjectPtr(x),
|
||||
WrData::RegObject(x) => DataDisp::RegObject(x),
|
||||
WrData::ImmObject(x) => DataDisp::ImmObject(x),
|
||||
WrData::Discard => DataDisp::Discard,
|
||||
}
|
||||
}
|
||||
@@ -77,10 +84,12 @@ impl From<WrData> for DataDisp {
|
||||
pub enum RdData {
|
||||
/// Constant value
|
||||
Immediate(Value),
|
||||
/// Pointer into memory, address immediate
|
||||
ImmObject(Value),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
ObjectPtr(Register),
|
||||
RegObject(Register),
|
||||
}
|
||||
|
||||
impl Display for RdData {
|
||||
@@ -94,7 +103,8 @@ impl Display for RdData {
|
||||
}
|
||||
}
|
||||
RdData::Register(r) => write!(f, "{}", r),
|
||||
RdData::ObjectPtr(r) => write!(f, "@{}", r)
|
||||
RdData::RegObject(r) => write!(f, "@{}", r),
|
||||
RdData::ImmObject(v) => write!(f, "@{:#x}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -105,8 +115,9 @@ impl TryFrom<DataDisp> for RdData {
|
||||
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
DataDisp::Immediate(x) => Ok(RdData::Immediate(x)),
|
||||
DataDisp::ImmObject(x) => Ok(RdData::ImmObject(x)),
|
||||
DataDisp::Register(x) => Ok(RdData::Register(x)),
|
||||
DataDisp::ObjectPtr(x) => Ok(RdData::ObjectPtr(x)),
|
||||
DataDisp::RegObject(x) => Ok(RdData::RegObject(x)),
|
||||
DataDisp::Discard => Err(AsmError::DiscardAsValue),
|
||||
}
|
||||
}
|
||||
@@ -115,10 +126,12 @@ impl TryFrom<DataDisp> for RdData {
|
||||
/// Data destination disposition
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
|
||||
pub enum WrData {
|
||||
/// Pointer into memory, address immediate
|
||||
ImmObject(Value),
|
||||
/// Register
|
||||
Register(Register),
|
||||
/// Pointer into memory, stored in a numbered register
|
||||
ObjectPtr(Register),
|
||||
RegObject(Register),
|
||||
/// Discard the written value
|
||||
Discard,
|
||||
}
|
||||
@@ -128,7 +141,8 @@ impl Display for WrData {
|
||||
match self {
|
||||
WrData::Discard => f.write_str("_"),
|
||||
WrData::Register(r) => write!(f, "{}", r),
|
||||
WrData::ObjectPtr(r) => write!(f, "@{}", r)
|
||||
WrData::RegObject(r) => write!(f, "@{}", r),
|
||||
WrData::ImmObject(v) => write!(f, "@{:#x}", v),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -136,9 +150,10 @@ impl Display for WrData {
|
||||
impl From<WrData> for RdData {
|
||||
fn from(s: WrData) -> Self {
|
||||
match s {
|
||||
WrData::ImmObject(x) => RdData::ImmObject(x),
|
||||
WrData::Register(x) => RdData::Register(x),
|
||||
WrData::ObjectPtr(x) => RdData::ObjectPtr(x),
|
||||
WrData::Discard => RdData::Immediate(0),
|
||||
WrData::RegObject(x) => RdData::RegObject(x),
|
||||
WrData::Discard => RdData::Immediate(0), // this should not be allowed by the assembler
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -149,8 +164,9 @@ impl TryFrom<DataDisp> for WrData {
|
||||
fn try_from(value: DataDisp) -> Result<Self, Self::Error> {
|
||||
match value {
|
||||
DataDisp::Immediate(_x) => Err(AsmError::ValueAsOutput),
|
||||
DataDisp::ImmObject(x) => Ok(WrData::ImmObject(x)),
|
||||
DataDisp::Register(x) => Ok(WrData::Register(x)),
|
||||
DataDisp::ObjectPtr(x) => Ok(WrData::ObjectPtr(x)),
|
||||
DataDisp::RegObject(x) => Ok(WrData::RegObject(x)),
|
||||
DataDisp::Discard => Ok(WrData::Discard),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,7 +93,7 @@ impl<'a> TokenParser<'a> {
|
||||
/// Get the next entry as read location
|
||||
pub fn next_rdobj(&mut self) -> Result<RdObj, CrsnError> {
|
||||
match parse_rd(self.next_or_err()?, self.pcx)? {
|
||||
Rd(RdData::ObjectPtr(reg), Mask::FULL) => {
|
||||
Rd(RdData::RegObject(reg), Mask::FULL) => {
|
||||
Ok(RdObj::new(reg))
|
||||
}
|
||||
other => {
|
||||
|
||||
@@ -96,14 +96,14 @@ pub fn parse_data_disp(tok: Sexp, pcx: &ParserContext) -> Result<DataDisp, CrsnE
|
||||
if let Some(reference) = s.strip_prefix('@') {
|
||||
let pstate = pcx.state.borrow();
|
||||
if let Some(reg) = pstate.reg_aliases.get(reference) {
|
||||
Ok(DataDisp::ObjectPtr(*reg))
|
||||
Ok(DataDisp::RegObject(*reg))
|
||||
} else {
|
||||
let reg = reg::parse_reg(reference, &pos)?;
|
||||
|
||||
if pstate.reg_aliases.values().find(|v| **v == reg).is_some() {
|
||||
Err(CrsnError::Parse(format!("Sym exists for register {}, direct access denied. Unsym it if needed.", reg).into(), pos))
|
||||
} else {
|
||||
Ok(DataDisp::ObjectPtr(reg))
|
||||
Ok(DataDisp::RegObject(reg))
|
||||
}
|
||||
}
|
||||
} else if s.starts_with(|c: char| c.is_ascii_digit() || c == '-') {
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::asm::instr::Flatten;
|
||||
use crate::asm::instr::op::OpKind;
|
||||
use crate::asm::parse::arg_parser::TokenParser;
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::run_thread::state::RunState;
|
||||
use crate::runtime::run_thread::state::{RunState};
|
||||
use crate::runtime::run_thread::ThreadInfo;
|
||||
|
||||
mod eval_res;
|
||||
@@ -72,7 +72,7 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
|
||||
}
|
||||
|
||||
/// Run-time method called to read an object (using the object handle syntax)
|
||||
fn read_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, _mask: Mask)
|
||||
fn read_obj(&self, state: &mut RunState, handle: Value, _mask: Mask)
|
||||
-> Result<Option<Value>, Fault>
|
||||
{
|
||||
// Default impl - we do not support reading this object
|
||||
@@ -80,8 +80,7 @@ pub trait CrsnExtension: Debug + Send + Sync + 'static {
|
||||
}
|
||||
|
||||
/// Run-time method called to write an object (using the object handle syntax)
|
||||
fn write_obj(&self, ti: &ThreadInfo, state: &mut RunState, handle: Value, mask: Mask)
|
||||
-> Result<Option<()>, Fault>
|
||||
fn write_obj(&self, state: &mut RunState, handle: Value, _mask: Mask, value: Value) -> Result<Option<()>, Fault>
|
||||
{
|
||||
// Default impl - we do not support writing this object
|
||||
Ok(None)
|
||||
|
||||
@@ -16,7 +16,7 @@ use crate::runtime::program::Program;
|
||||
pub struct ThreadToken(pub u32);
|
||||
|
||||
pub struct RunThread {
|
||||
pub(crate) info: ThreadInfo,
|
||||
pub(crate) info: Arc<ThreadInfo>,
|
||||
pub(crate) state: RunState,
|
||||
}
|
||||
|
||||
@@ -27,25 +27,38 @@ pub fn new_uniq() -> Arc<AtomicU64> {
|
||||
Arc::new(AtomicU64::new(info::UNIQ_BASE))
|
||||
}
|
||||
|
||||
impl RunThread {
|
||||
pub fn new(id: ThreadToken, uniq: Option<Arc<AtomicU64>>, program: Arc<Program>, pc: Addr, args: &[u64]) -> Self {
|
||||
Self {
|
||||
info: ThreadInfo {
|
||||
id,
|
||||
uniq: uniq.unwrap_or_else(new_uniq),
|
||||
program,
|
||||
cycle_time: Duration::default(),
|
||||
},
|
||||
state: RunState {
|
||||
frame: StackFrame::new(pc, args),
|
||||
call_stack: vec![],
|
||||
ext_data: Default::default(),
|
||||
},
|
||||
}
|
||||
}
|
||||
pub struct ThreadParams<'a> {
|
||||
pub id: ThreadToken,
|
||||
pub uniq: Option<Arc<AtomicU64>>,
|
||||
pub program: Arc<Program>,
|
||||
pub pc: Addr,
|
||||
pub cycle_time: Duration,
|
||||
pub args: &'a [u64],
|
||||
}
|
||||
|
||||
pub fn set_speed(&mut self, cycle_time: Duration) {
|
||||
self.info.cycle_time = cycle_time;
|
||||
impl RunThread {
|
||||
pub fn new(params: ThreadParams) -> Self {
|
||||
let extensions = params.program.extensions.clone();
|
||||
|
||||
let ti = Arc::new(ThreadInfo {
|
||||
id: params.id,
|
||||
uniq: params.uniq.unwrap_or_else(new_uniq),
|
||||
program: params.program,
|
||||
cycle_time: params.cycle_time,
|
||||
extensions,
|
||||
});
|
||||
|
||||
let rs = RunState {
|
||||
thread_info: ti.clone(),
|
||||
frame: StackFrame::new(params.pc, params.args),
|
||||
call_stack: vec![],
|
||||
ext_data: Default::default(),
|
||||
};
|
||||
|
||||
Self {
|
||||
info: ti,
|
||||
state: rs,
|
||||
}
|
||||
}
|
||||
|
||||
/// Spawn as a thread
|
||||
|
||||
@@ -5,6 +5,7 @@ use std::time::Duration;
|
||||
use crate::asm::data::literal::Value;
|
||||
use crate::runtime::program::Program;
|
||||
use crate::runtime::run_thread::ThreadToken;
|
||||
use crate::module::CrsnExtension;
|
||||
|
||||
pub struct ThreadInfo {
|
||||
/// Thread ID
|
||||
@@ -15,12 +16,14 @@ pub struct ThreadInfo {
|
||||
pub program: Arc<Program>,
|
||||
/// Program to run
|
||||
pub(crate) cycle_time: Duration,
|
||||
/// Extensions
|
||||
pub extensions: Arc<Vec<Box<dyn CrsnExtension>>>,
|
||||
}
|
||||
|
||||
pub const UNIQ_BASE: u64 = 0x6372_736e_0000_0000;
|
||||
|
||||
impl ThreadInfo {
|
||||
pub fn uniq(&self) -> Value {
|
||||
pub fn unique_value(&self) -> Value {
|
||||
self.uniq.fetch_add(1, Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,31 +1,51 @@
|
||||
use std::any::{Any, TypeId};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use crate::asm::data::{Rd, RdData, RdObj, Register, Wr, WrData};
|
||||
use crate::asm::data::{Rd, RdData, RdObj, Register, Wr, WrData, Mask};
|
||||
use crate::asm::data::literal::{Addr, Value};
|
||||
use crate::asm::instr::Cond;
|
||||
use crate::runtime::fault::Fault;
|
||||
use crate::runtime::frame::{CallStack, REG_COUNT, StackFrame};
|
||||
use std::sync::Arc;
|
||||
use crate::runtime::run_thread::ThreadInfo;
|
||||
|
||||
pub struct RunState {
|
||||
pub thread_info: Arc<ThreadInfo>,
|
||||
/// Active stack frame
|
||||
pub frame: StackFrame,
|
||||
/// Call stack
|
||||
pub call_stack: CallStack,
|
||||
/// Extension data
|
||||
pub ext_data: HashMap<TypeId, Box<dyn Any + Send>>,
|
||||
pub ext_data: ExtensionDataStore,
|
||||
}
|
||||
|
||||
#[derive(Debug,Default)]
|
||||
pub struct ExtensionDataStore {
|
||||
store: HashMap<TypeId, Box<dyn Any + Send>>
|
||||
}
|
||||
|
||||
impl ExtensionDataStore {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
||||
/// Get an extension's persistent data object for mutation.
|
||||
/// It will be created using Default if not present before.
|
||||
pub fn get_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
|
||||
if !self.store.contains_key(&TypeId::of::<T>()) {
|
||||
self.store.insert(TypeId::of::<T>(), Box::new(T::default()));
|
||||
}
|
||||
|
||||
self.store.get_mut(&TypeId::of::<T>()).unwrap()
|
||||
.downcast_mut().unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl RunState {
|
||||
/// Get an extension's persistent data object for mutation.
|
||||
/// It will be created using Default if not present before.
|
||||
pub fn ext_mut<T: Send + Default + 'static>(&mut self) -> &mut T {
|
||||
if !self.ext_data.contains_key(&TypeId::of::<T>()) {
|
||||
self.ext_data.insert(TypeId::of::<T>(), Box::new(T::default()));
|
||||
}
|
||||
|
||||
self.ext_data.get_mut(&TypeId::of::<T>()).unwrap()
|
||||
.downcast_mut().unwrap()
|
||||
self.ext_data.get_mut()
|
||||
}
|
||||
|
||||
/// Set a status flag. Only supports simple, positive conds (i.e. not GreaterOrEqual)
|
||||
@@ -95,12 +115,46 @@ impl RunState {
|
||||
Ok(self.frame.gen[rn as usize])
|
||||
}
|
||||
}
|
||||
RdData::ObjectPtr(_) => {
|
||||
unimplemented!("Read object ptr")
|
||||
RdData::RegObject(register) => {
|
||||
let reference = self.read(Rd::new(RdData::Register(register)))?;
|
||||
self.read_object(reference, rd.mask())
|
||||
}
|
||||
RdData::ImmObject(reference) => {
|
||||
self.read_object(reference, rd.mask())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn read_object(&mut self, reference: Value, mask: Mask) -> Result<Value, Fault> {
|
||||
// This is a shitty dirty hack to allow iterating over the extensions while passing a mutable reference
|
||||
// to self to the reading methods. Since the extensions array is in an Arc, it can't be mutated internally
|
||||
// anyway, and we know it will still live after the method returns - unless someone does something incredibly stupid.
|
||||
let ti: &ThreadInfo = unsafe { &*(self.thread_info.as_ref() as *const _) }; // If this fails, just clone the arc for the loop...
|
||||
|
||||
for ext in ti.extensions.iter() {
|
||||
if let Some(value) = ext.read_obj(self, reference, mask)? {
|
||||
return Ok(value);
|
||||
}
|
||||
}
|
||||
|
||||
Err(Fault::ObjectNotExist(reference))
|
||||
}
|
||||
|
||||
fn write_object(&mut self, reference: Value, mask: Mask, value: Value) -> Result<(), Fault> {
|
||||
// This is a shitty dirty hack to allow iterating over the extensions while passing a mutable reference
|
||||
// to self to the reading methods. Since the extensions array is in an Arc, it can't be mutated internally
|
||||
// anyway, and we know it will still live after the method returns - unless someone does something incredibly stupid.
|
||||
let ti: &ThreadInfo = unsafe { &*(self.thread_info.as_ref() as *const _) }; // If this fails, just clone the arc for the loop...
|
||||
|
||||
for ext in ti.extensions.iter() {
|
||||
if ext.write_obj(self, reference, mask, value)?.is_some() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(Fault::ObjectNotExist(reference))
|
||||
}
|
||||
|
||||
/// Write a value to a `Wr` location
|
||||
pub fn write(&mut self, wr: Wr, val: Value) -> Result<(), Fault> {
|
||||
trace!("WR {:?} := {}", wr, val);
|
||||
@@ -132,8 +186,12 @@ impl RunState {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
WrData::ObjectPtr(_) => {
|
||||
unimplemented!("Write object ptr")
|
||||
WrData::RegObject(register) => {
|
||||
let reference = self.read(Rd::new(RdData::Register(register)))?;
|
||||
self.write_object(reference, wr.mask(), val)
|
||||
}
|
||||
WrData::ImmObject(reference) => {
|
||||
self.write_object(reference, wr.mask(), val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user