pc/cpu/
beispiele.rs

1//! Beispiel-CPUs zur Veranschaulichung der Funktionsweisen.
2//!
3//! Hier befinden sich Beispiel-Implementation einer CPU zur näheren
4//! Veranschaulichung der Funktionsweise.
5
6use crate::cpu;
7use crate::cpu::{Architektur, Features};
8
9/// Beispiel für Instructions, welche von unserer Beispiel-CPU angenommen wird.
10#[non_exhaustive]
11#[derive(Debug, Copy, Clone)]
12pub enum Instructions {
13    Addieren,
14    Subtrahieren,
15}
16
17/// Eine fiktive Beispiel-CPU.
18#[derive(Debug)]
19pub struct BeispielCPU {
20    /// Alle Instructions, die diese CPU ausführen soll.
21    instructions: Vec<Instructions>,
22    /// Die aktuelle Instruction.
23    instruction_pointer: usize,
24
25    return_register: u64,
26    rax: u64,
27    rbx: u64,
28}
29
30impl BeispielCPU {
31    fn new() -> BeispielCPU {
32        Self {
33            instruction_pointer: 0,
34            instructions: Vec::new(),
35            return_register: 0,
36            rbx: 0,
37            rax: 0,
38        }
39    }
40
41    fn add_instruction(&mut self, instruction: Instructions) {
42        self.instructions.push(instruction);
43    }
44
45    fn set_rax(&mut self, value: u64) {
46        self.rax = value;
47    }
48
49    fn set_rbx(&mut self, value: u64) {
50        self.rbx = value;
51    }
52
53    fn get_result(&self) -> u64 {
54        self.return_register
55    }
56}
57
58impl cpu::CPU for BeispielCPU {
59    fn architektur(&self) -> Architektur {
60        Architektur::x86_64
61    }
62
63    fn kerne(&self) -> u8 {
64        12
65    }
66
67    fn basis_takt(&self) -> u64 {
68        5_200_000_000
69    }
70
71    fn turbo_takt(&self) -> Option<u64> {
72        Some(5_800_000_000)
73    }
74
75    fn features(&self) -> Vec<Features> {
76        vec![Features::Paging, Features::MemoryManagementUnit]
77    }
78
79    /// Sehen wir uns einmal genauer an, wie unsere fiktive CPU eine
80    /// Rechenoperation vornimmt.
81    ///
82    /// Keine Sorge, wenn du den exakten Programmablauf nicht verstehst: Es geht
83    /// hier vielmehr um das Konzept als die tatsächliche Anwendung. Solltest du
84    /// trotzdem Verständnisfragen haben, konsultiere gerne
85    /// <https://doc.rust-lang.org/std/index.html> sowie
86    /// <https://doc.rust-lang.org/book/title-page.html> oder Bjarne.
87    ///
88    /// # Fetch
89    /// ```Rust
90    /// let instruction = self.instructions[self.instruction_pointer];
91    /// ```
92    /// Hier deklarieren wir die Variable `instruction` und laden sofort die
93    /// aktuelle instruction (vorgegeben durch instruction_pointer) aus dem
94    /// [Vektor](Vec) instructions.
95    /// # Decode und Execute
96    /// ```Rust
97    /// self.return_register = match instruction {
98    ///     Instructions::Addieren => self.rax + self.rbx,
99    ///     Instructions::Subtrahieren => self.rax - self.rbx,
100    /// };
101    /// ```
102    /// Hier wird sowohl dekodiert als auch ausgeführt:
103    ///
104    /// - Mit `match` machen wir effektiv ein if {} else if {} zu einer
105    /// übersichtlichen Operation und bieten Ausgänge für alle möglichen
106    /// Operationen
107    /// - Wenn die Operation [Addieren](Instructions::Addieren) ist (dekodieren):
108    ///     - Addiere rax und rbx (ausführen)
109    /// - Wenn die Operation [Subtrahieren](Instructions::Subtrahieren) ist
110    /// (dekodieren):
111    ///     - Subtrahiere rbx von rax (ausführen)
112    ///
113    /// # Save
114    /// ```Rust
115    /// Ok(self.return_register)
116    /// ```
117    /// Das berechnete Ergebnis wird wieder zurück gegeben und die Funktion endet.
118    fn eins_ausführen(&mut self) -> Result<u64, ()> {
119        // Bounds check
120        if self.instruction_pointer >= self.instructions.len() {
121            return Err(());
122        }
123
124        // Fetch
125        let instruction = self.instructions[self.instruction_pointer];
126
127        // Decode + Execute
128        self.return_register = match instruction {
129            Instructions::Addieren => self.rax + self.rbx,
130            Instructions::Subtrahieren => self.rax - self.rbx,
131        };
132        self.instruction_pointer += 1;
133
134        // Save
135        Ok(self.return_register)
136    }
137}
138
139#[cfg(test)]
140mod test {
141    use crate::cpu::CPU;
142    use crate::cpu::beispiele::{BeispielCPU, Instructions};
143
144    #[test]
145    fn test_add() {
146        let mut cpu = BeispielCPU::new();
147        cpu.add_instruction(Instructions::Addieren);
148        cpu.set_rax(1);
149        cpu.set_rbx(2);
150        assert_eq!(cpu.eins_ausführen(), Ok(3))
151    }
152
153    #[test]
154    fn test_sub() {
155        let mut cpu = BeispielCPU::new();
156        cpu.add_instruction(Instructions::Subtrahieren);
157        cpu.set_rax(4);
158        cpu.set_rbx(2);
159        assert_eq!(cpu.eins_ausführen(), Ok(2))
160    }
161}