fixed a deadlock
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
use std::{
|
use std::{
|
||||||
sync::{
|
sync::{
|
||||||
Arc, Mutex,
|
Arc, Mutex, MutexGuard,
|
||||||
mpsc::{self, Receiver, Sender},
|
mpsc::{self, Receiver, Sender},
|
||||||
},
|
},
|
||||||
thread,
|
thread,
|
||||||
@@ -15,27 +15,39 @@ use crate::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn run_emulator(
|
pub fn run_emulator(cmd_rx: &Receiver<Command>, state_tx: &Sender<State>, cpu: Processor) {
|
||||||
cmd_rx: &Receiver<Command>,
|
println!("starting");
|
||||||
state_tx: &Sender<State>,
|
|
||||||
cpu: &Arc<Mutex<Processor>>,
|
|
||||||
) {
|
|
||||||
let mut running = Running::Paused;
|
let mut running = Running::Paused;
|
||||||
let mut addr = 0u32;
|
let mut addr = 0u32;
|
||||||
let size = 256;
|
let size = 256;
|
||||||
|
|
||||||
// Send initial state.
|
// Send initial state.
|
||||||
let Ok(mut cpu_lock) = cpu.lock() else {
|
// let Ok(mut cpu_lock) = cpu.lock() else {
|
||||||
panic!("Failed to lock CPU.")
|
// panic!("Failed to lock CPU.")
|
||||||
};
|
// };
|
||||||
|
|
||||||
|
let mut cpu_lock = cpu;
|
||||||
|
|
||||||
|
cpu_lock.get_stack(32);
|
||||||
|
println!("got stack");
|
||||||
|
|
||||||
|
cpu_lock.display();
|
||||||
|
println!("got display");
|
||||||
|
|
||||||
let memory_view = cpu_lock.memory.read_range(addr, size);
|
let memory_view = cpu_lock.memory.read_range(addr, size);
|
||||||
let initial_state = state(cpu, running, 0, memory_view);
|
println!("got view");
|
||||||
|
let initial_state = state(&mut cpu_lock, running, 0, memory_view);
|
||||||
|
println!("got state");
|
||||||
|
|
||||||
let _ = state_tx.send(initial_state);
|
let _ = state_tx.send(initial_state);
|
||||||
|
println!("sent state");
|
||||||
|
|
||||||
let mut instruction_count = 0;
|
let mut instruction_count = 0;
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
|
println!("looping");
|
||||||
|
|
||||||
let cmd = if running == Running::Running {
|
let cmd = if running == Running::Running {
|
||||||
match cmd_rx.try_recv() {
|
match cmd_rx.try_recv() {
|
||||||
Ok(cmd) => Some(cmd),
|
Ok(cmd) => Some(cmd),
|
||||||
@@ -50,6 +62,8 @@ pub fn run_emulator(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if let Some(cmd) = cmd {
|
if let Some(cmd) = cmd {
|
||||||
|
println!("Received command: {:?}", cmd);
|
||||||
|
|
||||||
match cmd {
|
match cmd {
|
||||||
Command::Start => {
|
Command::Start => {
|
||||||
running = Running::Running;
|
running = Running::Running;
|
||||||
@@ -95,7 +109,7 @@ pub fn run_emulator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
let memory_view = cpu_lock.memory.read_range(addr, size);
|
let memory_view = cpu_lock.memory.read_range(addr, size);
|
||||||
let state = state(cpu, running, instruction_count, memory_view);
|
let state = state(&mut cpu_lock, running, instruction_count, memory_view);
|
||||||
|
|
||||||
let _ = state_tx.send(state);
|
let _ = state_tx.send(state);
|
||||||
}
|
}
|
||||||
@@ -129,7 +143,7 @@ pub fn run_emulator(
|
|||||||
|
|
||||||
if update {
|
if update {
|
||||||
let memory_view = cpu_lock.memory.read_range(addr, size);
|
let memory_view = cpu_lock.memory.read_range(addr, size);
|
||||||
let state = state(cpu, running, instruction_count, memory_view);
|
let state = state(&mut cpu_lock, running, instruction_count, memory_view);
|
||||||
let _ = state_tx.send(state);
|
let _ = state_tx.send(state);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -139,15 +153,11 @@ pub fn run_emulator(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn state(
|
fn state(
|
||||||
cpu: &Arc<Mutex<Processor>>,
|
cpu_lock: &mut Processor,
|
||||||
running: Running,
|
running: Running,
|
||||||
instruction_count: usize,
|
instruction_count: usize,
|
||||||
memory_view: Vec<u8>,
|
memory_view: Vec<u8>,
|
||||||
) -> State {
|
) -> State {
|
||||||
let Ok(mut cpu_lock) = cpu.lock() else {
|
|
||||||
panic!("Could not lock CPU.")
|
|
||||||
};
|
|
||||||
|
|
||||||
State {
|
State {
|
||||||
// TODO: Replace with actual register access from your CPU.
|
// TODO: Replace with actual register access from your CPU.
|
||||||
reg_file: cpu_lock.registers,
|
reg_file: cpu_lock.registers,
|
||||||
|
|||||||
@@ -7,6 +7,14 @@ pub enum Running {
|
|||||||
Halted,
|
Halted,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IODevice: Send + Sync {
|
||||||
|
fn read_byte(&mut self, addr: u32) -> u8;
|
||||||
|
fn write_byte(&mut self, addr: u32, value: u8);
|
||||||
|
fn read_range(&mut self, addr: u32, size: u32) -> Vec<u8>;
|
||||||
|
fn write_range(&mut self, addr: u32, value: Vec<u8>);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Eq, Debug, Clone)]
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
Start,
|
Start,
|
||||||
Stop,
|
Stop,
|
||||||
|
|||||||
@@ -1,27 +1,33 @@
|
|||||||
use std::cmp::{max, min};
|
use std::{
|
||||||
|
cmp::{max, min},
|
||||||
|
sync::Arc,
|
||||||
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::instructions::{Instruction, Interrupt, Register, errors::InstructionDecodeError},
|
common::instructions::{Instruction, Interrupt, Register, errors::InstructionDecodeError},
|
||||||
emulator::system::{memory::MemoryUnit, model::RegFile},
|
emulator::system::{
|
||||||
|
memory::MemoryUnit,
|
||||||
|
model::{IODevice, RegFile},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Processor {
|
pub struct Processor {
|
||||||
pub memory: Box<dyn MemoryUnit>,
|
pub memory: Box<dyn MemoryUnit>,
|
||||||
pub registers: RegFile,
|
pub registers: RegFile,
|
||||||
pub halted: bool,
|
pub halted: bool,
|
||||||
// pub io_devices: Vec<Arc<dyn IODevice>>,
|
pub io_devices: Vec<Arc<dyn IODevice>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::needless_pass_by_ref_mut)]
|
#[allow(clippy::needless_pass_by_ref_mut)]
|
||||||
impl Processor {
|
impl Processor {
|
||||||
// io_devices: Vec<Arc<dyn IODevice>>
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn new(memory: Box<dyn MemoryUnit>) -> Self {
|
pub fn new(memory: Box<dyn MemoryUnit>, io_devices: Vec<Arc<dyn IODevice>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
// io_devices,
|
// io_devices,
|
||||||
memory,
|
memory,
|
||||||
registers: RegFile::default(),
|
registers: RegFile::default(),
|
||||||
halted: false,
|
halted: false,
|
||||||
|
io_devices,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ use crate::{
|
|||||||
|
|
||||||
fn create_test_processor() -> Processor {
|
fn create_test_processor() -> Processor {
|
||||||
let memory = Box::new(MainStore::new());
|
let memory = Box::new(MainStore::new());
|
||||||
Processor::new(memory)
|
Processor::new(memory, Vec::new())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
+2
-6
@@ -17,14 +17,10 @@ fn main() -> Result<(), eframe::Error> {
|
|||||||
let (state_sender, state_receiver) = std::sync::mpsc::channel();
|
let (state_sender, state_receiver) = std::sync::mpsc::channel();
|
||||||
|
|
||||||
let mainstore = MainStore::new();
|
let mainstore = MainStore::new();
|
||||||
let processor = Processor::new(Box::new(mainstore));
|
let processor = Processor::new(Box::new(mainstore), vec![]);
|
||||||
|
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
run_emulator(
|
run_emulator(&cmd_receiver, &state_sender, processor);
|
||||||
&cmd_receiver,
|
|
||||||
&state_sender,
|
|
||||||
&Arc::new(Mutex::new(processor)),
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Create UI
|
// Create UI
|
||||||
|
|||||||
Reference in New Issue
Block a user