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}