You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
2.2 KiB
80 lines
2.2 KiB
use std::sync::Arc;
|
|
use std::sync::atomic::AtomicU64;
|
|
use std::thread::JoinHandle;
|
|
use std::time::Duration;
|
|
|
|
pub use info::ThreadInfo;
|
|
pub use state::RunState;
|
|
|
|
use crate::asm::data::literal::Addr;
|
|
use crate::module::EvalRes;
|
|
use crate::runtime::fault::Fault;
|
|
use crate::runtime::frame::StackFrame;
|
|
use crate::runtime::program::Program;
|
|
use std::pin::Pin;
|
|
|
|
#[derive(Clone, Copy, Eq, PartialEq, Debug, Ord, PartialOrd)]
|
|
pub struct ThreadToken(pub u32);
|
|
|
|
pub struct RunThread {
|
|
pub(crate) info: ThreadInfo,
|
|
pub(crate) state: RunState,
|
|
}
|
|
|
|
pub mod info;
|
|
pub mod state;
|
|
|
|
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 fn set_speed(&mut self, cycle_time: Duration) {
|
|
self.info.cycle_time = cycle_time;
|
|
}
|
|
|
|
pub fn start(self) -> JoinHandle<()> {
|
|
std::thread::spawn(move || {
|
|
self.run();
|
|
})
|
|
}
|
|
|
|
fn run(mut self) {
|
|
'run: loop {
|
|
match self.eval_op() {
|
|
Ok(EvalRes { cycles, advance }) => {
|
|
std::thread::sleep(self.info.cycle_time * (cycles as u32));
|
|
trace!("Step {}; Status = {}", advance, self.state.frame.status);
|
|
self.state.frame.pc.advance(advance);
|
|
if self.state.frame.status.invalid {
|
|
warn!("Operation failed with INVALID status!");
|
|
}
|
|
}
|
|
Err(Fault::Halt) => {
|
|
info!("Program ended.");
|
|
break 'run;
|
|
}
|
|
Err(e) => {
|
|
error!("Fault: {:?}", e);
|
|
break 'run;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|