Repository navigation
Expand file tree
/
Copy pathCPUEmulator.java
More file actions
138 lines (121 loc) · 4.43 KB
/
Copy pathCPUEmulator.java
File metadata and controls
138 lines (121 loc) · 4.43 KB
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
132
133
134
135
136
137
138
import java.util.List;
public class CPUEmulator {
private int PC;
private int AC = 0;
private int FLAG = 0;
private int baseAddress;
private final Memory memory;
private final Cache cache;
public CPUEmulator(int baseAddress, int initialPC, List<String> instructions) {
this.baseAddress = baseAddress;
this.PC = initialPC;
this.memory = new Memory();
this.cache = new Cache();
loadProgram(instructions);
}
private void loadProgram(List<String> instructions) {
for (int i = 0; i < instructions.size(); i++) {
int instruction = Integer.parseInt(instructions.get(i), 2);
memory.writeWord(baseAddress + i * 2, instruction);
}
//System.out.printf("Program loaded from address: 0x%04X to 0x%04X\n",
//baseAddress, baseAddress + instructions.size() * 2 - 1);
}
public void execute() {
int stepCounter = 0;
while (true) {
int instr = readMemWord(PC); // <-- READS FROM CACHE
int opcode = (instr >> 12) & 0xF;
int operand = instr & 0x0FFF;
if (stepCounter < 1000) {
//System.out.printf("PC: %04X | OPCODE: %X | OPERAND: %03X | AC: %d | FLAG: %d\n",
//PC, opcode, operand, AC, FLAG);
}
stepCounter++;
switch (opcode) {
case 0x0: // START
PC += 2;
break;
case 0x1: // LOAD
AC = operand;
PC += 2;
break;
case 0x2: // LOADM
AC = readMemWord(baseAddress + operand);
PC += 2;
break;
case 0x3: // STORE
writeMemWord(baseAddress + operand, AC);
PC += 2;
break;
case 0x4: // CMPM
int val = readMemWord(baseAddress + operand);
//System.out.println("CMPM DEBUG — AC: " + AC + " vs MEM[" + (baseAddress + operand) + "]: " + val);
FLAG = Integer.compare(AC, val);
PC += 2;
break;
case 0x5: // CJMP
if (FLAG > 0) {
PC = baseAddress + operand * 2;
} else {
PC += 2;
}
break;
case 0x6: // JMP
PC = baseAddress + operand * 2;
break;
case 0x7: // ADD
AC += operand;
PC += 2;
break;
case 0x8: // ADDM
AC += readMemWord(baseAddress + operand);
PC += 2;
break;
case 0x9: // SUB
AC -= operand;
PC += 2;
break;
case 0xA: // SUBM
AC -= readMemWord(baseAddress + operand);
PC += 2;
break;
case 0xB: // MUL
AC *= operand;
PC += 2;
break;
case 0xC: // MULM
AC *= readMemWord(baseAddress + operand);
PC += 2;
break;
case 0xD: // DISP
System.out.println("Value in AC: " + AC);
PC += 2;
break;
case 0xE: // HALT
printStats();
return;
default:
System.err.println("Unknown opcode: " + opcode);
return;
}
}
}
private int readMemWord(int address) {
int low = cache.read(address, memory) & 0xFF;
int high = cache.read(address + 1, memory) & 0xFF;
return (high << 8) | low;
}
private void writeMemWord(int address, int value) {
byte low = (byte)(value & 0xFF);
byte high = (byte)((value >> 8) & 0xFF);
cache.write(address, low, memory);
cache.write(address + 1, high, memory);
}
private void printStats() {
int total = cache.getTotalAccesses();
int hits = cache.getHits();
double ratio = total == 0 ? 0.0 : (100.0 * hits / total);
System.out.printf("Cache hit ratio: %.2f%%\n", ratio);
}
}