osiris_process/
processor.rs

1use std::cell::{Ref, RefCell, RefMut};
2use std::ops::Add;
3use std::rc::Rc;
4use std::time::{Duration, Instant};
5
6use osiris_data::data::atomic::Word;
7use osiris_data::data::composite::ProduceConsume;
8use osiris_data::data::identification::{Address, Identifier};
9use osiris_data::memory::{Memory, MemoryError, MemoryResult};
10use crate::communication::MessageQueue;
11
12use crate::operation;
13use crate::operation::{Instruction, Operation, OperationSet};
14use crate::operation::error::{OperationError, OperationResult};
15use crate::register::{RegisterBank, RegisterId, RegisterRange};
16use crate::register::floating_point::{Number, VectorApplication};
17use crate::register::integral::BankApplication;
18use crate::register::state::{CpuState, TickState};
19
20#[derive(Copy, Clone, Debug)]
21pub struct CpuConfiguration {
22    pub frequency: usize,
23}
24
25impl CpuConfiguration {
26    pub const DEFAULT_FREQUENCY: usize = 64;
27}
28
29impl Default for CpuConfiguration {
30    /// See : [CpuConfiguration::DEFAULT_FREQUENCY]
31    fn default() -> Self {
32        CpuConfiguration {
33            frequency: Self::DEFAULT_FREQUENCY,
34        }
35    }
36}
37
38/// Cpu is a facade to a virtual processor : register control and instructions_sets, and memory.
39#[derive(Clone, Debug, Default)]
40pub struct Cpu {
41    pub parent: Option<Rc<Cpu>>,
42    pub config: CpuConfiguration,
43    pub state: CpuState,
44    pub output: MessageQueue,
45    operations: Rc<OperationSet>,
46    ram: RefCell<Memory>,
47}
48
49impl Cpu {
50    pub fn new(memory: RefCell<Memory>, operation_set: Rc<OperationSet>) -> Self {
51        Self {
52            parent: None,
53            config: CpuConfiguration::default(),
54            state: CpuState::new(),
55            output: MessageQueue::default(),
56            operations: operation_set,
57            ram: memory,
58        }
59    }
60
61    pub fn fork(self, fork_target: Address) -> (Self, Rc<Self>) {
62        let config = self.config;
63        let mut state = self.state.clone();
64        state.current = fork_target;
65        let operations = self.operations.clone();
66        let ram = self.memory();
67        let rc = Rc::from(self);
68
69        (Self {
70            parent: Some(rc.clone()),
71            config,
72            state,
73            output: MessageQueue::default(),
74            operations,
75            ram,
76        }, rc)
77    }
78
79    pub fn debug(&self, label: &str, value: String, symbol: String) {
80        if self.state.flag_debug {
81            println!("\u{2ba1} {:15} {:} \x1b[1;38m{}\x1b[0m", label, symbol, value);
82        }
83    }
84
85    // ///////////////////////////////////////////////////////////////////////////////////////////// Memory references
86
87    pub fn memory(&self) -> RefCell<Memory> { self.ram.clone() }
88    pub fn ram(&self) -> Ref<Memory> { self.ram.borrow() }
89    pub fn ram_mut(&self) -> RefMut<Memory> { self.ram.borrow_mut() }
90
91    // ///////////////////////////////////////////////////////////////////////////////////////////// Operations
92
93    pub fn stack_push(&mut self, word: Word) {
94        self.debug("push", format!("{:016x}", word.to_u64()), "🔽".to_string());
95        self.state.stack.produce(word);
96    }
97    pub fn stack_pop(&mut self) -> Option<Word> {
98        let pop = self.state.stack.consume();
99        self.debug("pop", match &pop {
100            None => "".to_string(),
101            Some(w) => format!("{:016x}", w.to_u64()),
102        }, "🔼".to_string());
103        pop
104    }
105    pub fn bank_get(&self, register_id: RegisterId) -> Word {
106        let v = self.state.bank.get(register_id);
107        self.debug(format!("get r{:04x}", register_id.to_u16()).as_str(), format!("{:016x}", v.to_u64()), "▶️".to_string());
108        v
109    }
110    pub fn bank_set(&mut self, register_id: RegisterId, word: Word) {
111        self.state.bank.set(register_id, word);
112        self.debug(format!("set r{:04x}", register_id.to_u16()).as_str(), format!("{:016x}", self.state.bank.get(register_id).to_u64()), "◀️".to_string());
113    }
114
115    pub fn bank_store(&mut self, register_id: RegisterId, address: Address) -> MemoryResult<()> {
116        let word = self.state.bank.get(register_id);
117        self.ram_mut().store(address, word)?;
118        self.debug("store", format!("{:016x} {:016x}", address.to_u64(), word.to_u64()), "⏬".to_string());
119        Ok(())
120    }
121
122    pub fn bank_load(&mut self, register_id: RegisterId, address: Address) -> MemoryResult<()> {
123        let word = self.ram().load(address)?;
124        self.state.bank.set(register_id, word);
125        self.debug("load", format!("{:016x} {:016x}", address.to_u64(), word.to_u64()), "⏫".to_string());
126        Ok(())
127    }
128
129    pub fn bank_apply(&mut self, target: RegisterId, range: RegisterRange, application: BankApplication) {
130        self.debug("apply unsigned", format!("{:04x}:{:04x}", range.start.to_u16(), range.end.to_u16()), "⚙️".to_string());
131        self.state.operation.result = self.state.bank.apply(range, application);
132        self.bank_set(target, self.state.operation.result);
133    }
134
135    pub fn bank_push(&mut self, register_id: RegisterId) {
136        self.stack_push(self.bank_get(register_id));
137    }
138
139    pub fn bank_pop(&mut self, register_id: RegisterId) {
140        if self.state.stack.is_empty() { return; }
141        let popped = self.stack_pop().unwrap_or(self.state.bank.get(register_id));
142        self.bank_set(register_id, popped);
143    }
144
145    pub fn vector_get(&self, register_id: RegisterId) -> Number {
146        let v = self.state.vector.get(register_id);
147        self.debug(format!("get f{:04x}", register_id.to_u16()).as_str(), format!("{}", v.to_f64()), "▶️".to_string());
148        v
149    }
150    pub fn vector_set(&mut self, register_id: RegisterId, number: Number) {
151        self.state.vector.set(register_id, number);
152        self.debug(format!("set f{:04x}", register_id.to_u16()).as_str(), format!("{}", self.state.vector.get(register_id).to_f64()), "◀️".to_string());
153    }
154
155    pub fn vector_store(&mut self, register_id: RegisterId, address: Address) -> MemoryResult<()> {
156        let number = self.state.vector.get(register_id);
157        self.ram_mut().store(address, Word::new(number.to_u64()))?;
158        self.debug("store", format!("{:016x} {}", address.to_u64(), number.to_f64()), "⏬".to_string());
159        Ok(())
160    }
161
162    pub fn vector_load(&mut self, register_id: RegisterId, address: Address) -> MemoryResult<()> {
163        let number = self.ram().load(address)?;
164        let number = Number::from_u64(number.to_u64());
165        self.state.vector.set(register_id, number);
166        self.debug("load", format!("{:016x} {}", address.to_u64(), number.to_f64()), "⏬".to_string());
167        Ok(())
168    }
169
170    pub fn vector_apply(&mut self, target: RegisterId, range: RegisterRange, application: VectorApplication) {
171        self.debug("apply float", format!("{:04x}:{:04x}", range.start.to_u16(), range.end.to_u16()), "⚙️".to_string());
172        self.state.vector.set(target, self.state.vector.apply(range, application));
173    }
174
175    pub fn vector_push(&mut self, register_id: RegisterId) { self.stack_push(Word::new(self.vector_get(register_id).to_u64())); }
176
177    pub fn vector_pop(&mut self, register_id: RegisterId) {
178        if self.state.stack.is_empty() { return; }
179        let value = self.stack_pop()
180            .unwrap_or(Word::new(self.vector_get(register_id).to_u64())).to_u64();
181        self.vector_set(register_id, Number::from_u64(value))
182    }
183
184    pub fn next_instruction(&mut self) {
185        self.state.current.increment();
186    }
187
188    pub fn stack_size(&self) -> usize { self.state.stack.len() }
189    pub fn memory_size(&self) -> usize { self.ram().len() }
190
191    pub fn current_instruction(&self) -> Instruction { Instruction::new(self.ram().load(self.state.current).unwrap_or_default().to_u64()) }
192
193    pub fn point_instruction(&mut self, new_address: Address) -> MemoryResult<()> {
194        if new_address.to_usize() > self.memory_size() {
195            return Err(MemoryError::OutOfBounds { requested: new_address.to_usize(), memory_len: self.memory_size() });
196        }
197        self.state.current = new_address;
198        self.debug("point", format!("{:016x}", self.state.current.to_u64()), "📌".to_string());
199        Ok(())
200    }
201
202    pub fn decrease_loop_counter(&mut self) {
203        let counter = self.state.operation.counter.to_u64();
204        if counter > 0 {
205            self.state.operation.counter = Word::new(counter - 1);
206            self.debug("loop--", format!("{}", counter), "♾️".to_string());
207        } else {
208            self.debug("no loop", format!("{}", counter), "♾️".to_string());
209        }
210    }
211
212    pub fn halt(&mut self) {
213        self.debug("halt cpu", "".to_string(), "🛑".to_string());
214        self.state.flag_halt = true;
215    }
216
217    // ///////////////////////////////////////////////////////////////////////////////////////////// Operation execution utilities
218
219    pub fn tick(&mut self) -> OperationResult<TickState> {
220        let instruction = self.current_instruction();
221        match operation::match_operation(&self.operations, instruction) {
222            None => Err(OperationError::MismatchedInstruction(instruction)),
223            Some(operation) => self.execute_or_skip(instruction, operation)
224        }
225    }
226
227    fn execute_or_skip(&mut self, instruction: Instruction, operation: Operation<()>) -> OperationResult<TickState> {
228        let scheme = instruction.operation_to_instruction(&operation);
229        if self.state.flag_skip {
230            self.state.flag_skip = false;
231            Ok(TickState::Skipped)
232        } else {
233            let old_current = self.state.current;
234            if self.state.flag_debug {
235                let [addr_top, addr_bottom] = Word::new(self.state.current.to_u64()).split();
236                print!("\x1b[37m{:08x}\x1b[0m{:08x}: ", addr_top.to_u32(), addr_bottom.to_u32());
237                operation.call_debug(self, scheme)?;
238            } else {
239                operation.call(self, scheme)?;
240            }
241            if self.state.current != old_current {
242                Ok(TickState::Jumped)
243            } else {
244                Ok(TickState::Executed)
245            }
246        }
247    }
248
249    pub fn next_instant(&self) -> Instant {
250        // `::from_nanos` is used for precision. Maximum frequency of the Cpu should be far inferior.
251        Instant::now().add(Duration::from_nanos(((1024 * 1024 * 1024) as f64 / self.config.frequency as f64) as u64))
252    }
253
254    pub fn advance(&mut self) {
255        let state = match self.tick() {
256            Ok(s) => s,
257            Err(err) => panic!("⚠️ \x1b[31mOperation error\x1b[0m : {:#?}", err)
258        };
259        if state != TickState::Jumped {
260            self.next_instruction();
261        }
262    }
263
264    pub fn until_halt(&mut self) {
265        loop {
266            self.advance();
267            if self.state.flag_halt {
268                break;
269            }
270        }
271    }
272
273}