-
Notifications
You must be signed in to change notification settings - Fork 7
/
cpu.hpp
131 lines (120 loc) · 4.81 KB
/
cpu.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/**
* @file cpu.hpp
* @author paul
* @date 25.05.20
* Definition of the structs used for the main emulation loop.
*/
#ifndef TEMPLATE_CPU_CPU_HPP
#define TEMPLATE_CPU_CPU_HPP
#include "instructions.hpp"
/**
* Concept for a program as an alias for a type list
* @tparam T the type to check
*/
template<typename T>
concept Program = IsTypeList<T>::val;
/**
* Alias for declaring a program using a variadic template.
* @tparam instructions the instructions
*/
template<Instruction ... instructions>
using DeclareProgram = typename FromVariadicType<instructions...>::type;
/**
* Struct containing the results of the execution of a program
* @tparam registers the registers after execution
* @tparam memory the memory after execution
* @tparam PC_ the program counter after execution
* @tparam instr_count_ the number of instructions executed
* @tparam breakpoint true if the program was stopped due to a breakpoint
*/
template<Registers registers, Memory memory, std::size_t PC_, std::size_t instr_count_, bool breakpoint>
struct Result {
using reg = registers;
using mem = memory;
static constexpr auto pc = PC_;
static constexpr auto instr_count = instr_count_;
static constexpr auto is_breakpoint = breakpoint;
};
/**
* Struct used for fetching the Instruction and running the Instruction on the current state.
* @tparam program the program
* @tparam old_pc the old/current program counter
* @tparam registers the registers
* @tparam memory the memory
*/
template<Program program, std::size_t old_pc, Registers registers, Memory memory>
struct ExecuteInstr {
static constexpr auto pc = InstrImpl<typename GetType<program, old_pc>::type, registers, memory, old_pc>::pc;
using reg = typename InstrImpl<typename GetType<program, old_pc>::type, registers, memory, old_pc>::reg;
using mem = typename InstrImpl<typename GetType<program, old_pc>::type, registers, memory, old_pc>::mem;
};
/**
* The main struct for running the CPU emulation code.
* @tparam program the program
* @tparam size the size of the program (number of instructions)
* @tparam PC the current program counter
* @tparam registers the registers
* @tparam memory the memory
* @tparam instr_count the number of instructions which have been executed since start
* @tparam max_instructions the maximum numbers of instructions to run
*/
template<Program program, std::size_t size, std::size_t PC, Registers registers, Memory memory, std::size_t instr_count, std::size_t max_instructions>
struct CpuState {
using val = typename CpuState<
program,
size,
ExecuteInstr<program, PC, registers, memory>::pc,
typename ExecuteInstr<program, PC, registers, memory>::reg,
typename ExecuteInstr<program, PC, registers, memory>::mem,
instr_count + 1,
max_instructions
>::val;
};
/**
* Specialization if the program terminates normally
*/
template<Program program, std::size_t size, Registers registers, Memory memory, std::size_t instr_count, std::size_t max_instructions>
struct CpuState<program, size, size, registers, memory, instr_count, max_instructions> {
using val = Result<registers, memory, size, instr_count, false>;
};
/**
* Specialization for breakpoints
*/
template<Program program, std::size_t size, std::size_t PC, Registers registers, Memory memory, std::size_t max_instructions>
struct CpuState<program, size, PC, registers, memory, max_instructions, max_instructions> {
using val = Result<registers, memory, PC, max_instructions, true>;
};
/**
* Main struct for emulating a program.
* @tparam program the program
*/
template<Program program>
struct Cpu {
using run = typename CpuState<
program,
Size<program>::val,
0,
typename FillVal<static_cast<std::size_t>(Register::LENGTH), base_type, 0>::type,
typename FillVal<MEM_SIZE, base_type, 0>::type,
0,
static_cast<std::size_t>(-1)
>::val;
};
/**
* Main struct for running a program until a certain number of instructions is executed.
* @tparam program the program
* @tparam instructions the number of instructions to run
*/
template<Program program, std::size_t instructions>
struct CpuDebug {
using run = typename CpuState<
program,
Size<program>::val,
0,
typename FillVal<static_cast<std::size_t>(Register::LENGTH), base_type, 0>::type,
typename FillVal<MEM_SIZE, base_type, 0>::type,
0,
instructions
>::val;
};
#endif //TEMPLATE_CPU_CPU_HPP