-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathProcessorNoCache.java
More file actions
422 lines (419 loc) · 16.6 KB
/
ProcessorNoCache.java
File metadata and controls
422 lines (419 loc) · 16.6 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
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
public class ProcessorNoCache {
// UNCHANGED VALS
private static final Bit T = new Bit(true);
private static final Bit F = new Bit(false);
private static final Word32 BLANK = new Word32();
private static final Word32 ONE = new Word32(new Bit[]{F, F, F, F, F, F, F, F, F, F,F, F, F, F, F, F, F, F, F, F,F, F, F, F, F, F, F, F, F, F,F,T});
private static final Word16 RETURN = new Word16(new Bit[]{F,T,F,T,F});
private static final Word16 LOAD = new Word16(new Bit[]{T,F,F,T,F});
private static final Word16 SYSCALL = new Word16(new Bit[]{F,T,F,F,F});
private static final Word16 MULTIPLY = new Word16(new Bit[]{F,F,F,T,T});
private static final Word16 BNE = new Word16(new Bit[]{T,F,F,F,T});
private static final Word16 CALL = new Word16(new Bit[]{F,T,F,F,T});
private static final Word16 COPY = new Word16(new Bit[]{T,F,T,F,F});
private static final Word16 STORE = new Word16(new Bit[]{T,F,F,T,T});
private static final LinkedList<String>OpCodesFormat = new LinkedList<>(Arrays.asList(
"f,f,f,f,t", // add
"f,f,f,t,f", // and
"f,f,f,t,t", // multiply
"f,f,t,f,f", // leftshift
"f,f,t,f,t", // subtract
"f,f,t,t,f", // or
"f,f,t,t,t", // rightshift
"f,t,f,t,t" // compare
));
private static final LinkedList<String>NONALUOpCodesFormat = new LinkedList<>(Arrays.asList(
"t,f,f,t,f", // load
"t,f,f,t,t", // store
"t,f,t,f,f" // copy
));
// Memory class
private Memory mem;
// ALU class
private ALU alu = new ALU();
// Storage for registers
private LinkedList<Word32> Registers = new LinkedList<>();
// Storage for instructions
private LinkedList<Word16> Instructions = new LinkedList<Word16>();
private LinkedList<Word32> Saved_Addr = new LinkedList<Word32>();
// Storage for output
public List<String> output = new LinkedList<>();
// PC keeps track of instructions present
private Word32 PC = new Word32();
// Instruction keeps track of current instruction
private Word16 Instruction = new Word16();
// OP1 & OP2 used for various op formatted instructs.
private Word32 OP1 = new Word32();
private Word32 OP2 = new Word32();
// CURR_ADDR used to store the current address in memory
private Word32 CURR_ADDR = new Word32();
// CallReturnVal used for various CallReturn formatted instructs
private Word32 CallReturnVal = new Word32();
// isHalt used to pause program
private boolean isHalt = false;
// is2R checks to see the format of the instruction
private boolean is2R = false;
// skipIteration skips the current iteration if need be
private boolean skipIteration = false;
// isReturn checks if return is called.
private boolean isReturn = false;
// Cycle counter for amount of clock cycles per program.
private int CURRENT_CLOCK_CYCLE = 0;
// Constructor for Processor
public ProcessorNoCache(Memory m) {
// Set up memory
mem = m;
// Set up Registers
for(int i = 0; i < 32; i++)
Registers.add(new Word32());
}
public void run() {
// Clear mem.address in case it still has stuff in it
BLANK.copy(mem.address);
while(!isHalt){
// If PC is even, then call fetch
fetch();
// While instructions, and no other booleans are true, iterate thru loop,
// go thru decode execute & store as normally.
while(!Instructions.isEmpty() && !skipIteration && !isReturn) {
// Pop instruction from instructions stack.
Instruction = Instructions.pop();
decode();
// if halt, then break
if (isHalt)
break;
// if isReturn, then clear instructions and break
else if(isReturn){
Instructions.clear();
break;
}
execute();
// Breaks if skipIteration is true
if(skipIteration){
Instructions.clear();
break;
}
store();
}
// if not skipping, att one to PC
if(!skipIteration && !isReturn){
Word32 PCCopy = new Word32();
PC.copy(PCCopy);
Adder.add(PCCopy, ONE, PC);
}
if(isReturn){
Saved_Addr.remove(0).copy(PC);
PC.copy(mem.address);
}
skipIteration = false;
isReturn = false;
}
}
private void fetch() {
// Read memory to read instructions coming from it
mem.read();
// Input instructions from memory value.
Word32 instructs = new Word32();
mem.value.copy(instructs);
// Get both instructions from word
Word16 getInstruct1 = new Word16();
Word16 getInstruct2 = new Word16();
instructs.getTopHalf(getInstruct1);
instructs.getBottomHalf(getInstruct2);
// Add both instructions to linkedList
Instructions.add(getInstruct1);
Instructions.add(getInstruct2);
// Add 1 to memory address to read from next address
Word32 memCpy = new Word32();
mem.address.copy(memCpy);
Adder.add(memCpy, ONE, mem.address);
// Read in case needed for next usage.
CURRENT_CLOCK_CYCLE += 300;
}
private void decode() {
// fullInstruct & instruct to keep track of instructions.
String fullInstruct = Instruction.toString();
String instruct = fullInstruct.substring(0,9);
BLANK.copy(OP1);
BLANK.copy(OP2);
// Checks if halt
if(Instruction.equals(new Word16(), 5))
isHalt = true;
// Checks for return, if true then address to saved address
else if(Instruction.equals(RETURN, 5)){
Word32 newAddr = new Word32();
PC.copy(newAddr);
Saved_Addr.add(newAddr);
isReturn = true;
}
else{
// Checks if format 2R/Immediate or Call/Return
if(OpCodesFormat.contains(instruct) || NONALUOpCodesFormat.contains(fullInstruct.substring(0,9))){
is2R = true;
Bit b = new Bit(false);
Instruction.getBitN(5, b);
// Checks if format is immediate
if(b.getValue() == Bit.boolValues.TRUE){
GenerateImmediateVal(Instruction).copy(OP1);
RetrieveValFromRegister(Instruction, 1).copy(OP2);
}
// Else check if immediate.
else{
RetrieveValFromRegister(Instruction, 0).copy(OP1);
RetrieveValFromRegister(Instruction, 1).copy(OP2);
}
}
// If call/return format
else{
is2R = false;
GenerateCallReturnValue(Instruction).copy(CallReturnVal);
}
}
}
private void execute() {
String fullInstruct = Instruction.toString();
String instruct = fullInstruct.substring(0,9);
// If format is 2R
if(is2R){
// If instruction is in ALU
if(OpCodesFormat.contains(instruct)){
Instruction.copy(alu.instruction);
OP2.copy(alu.op1);
OP1.copy(alu.op2);
if(Instruction.equals(MULTIPLY, 5))
CURRENT_CLOCK_CYCLE += 10;
else
CURRENT_CLOCK_CYCLE += 2;
alu.doInstruction();
}
// if load
else if(Instruction.equals(LOAD, 5))
RetrieveValFromMem(OP1, OP2);
}
else{
// If equals syscall
if(Instruction.equals(SYSCALL, 5)){
Bit b = new Bit(false);
CallReturnVal.getBitN(31, b);
// Print mem if val is 1, else 0
if(b.getValue() == Bit.boolValues.TRUE)
printMem();
else
printReg();
}
// If equals bne
else if(Instruction.equals(BNE, 5)){
// If immediate, then check msb, make necessary changes to address (by adding or subtracting),
// then modify and adjust PC while updating the new memory value.
if(alu.equal.getValue() == Bit.boolValues.FALSE){
Word32 res = new Word32();
Bit msb = new Bit(false);
CallReturnVal.getBitN(0,msb);
if(msb.getValue() == Bit.boolValues.TRUE){
Word32 Positive = new Word32();
CallReturnVal.not(Positive);
Word32 AddOne = new Word32();
Adder.add(Positive, ONE, AddOne);
Adder.subtract(PC, AddOne, res);
}
else
Adder.add(PC, CallReturnVal, res);
// Ensure that skipIteration is set to true for the inner main loop to stop repeating and automatically
// switch to the proceeding processes.
res.copy(PC);
PC.copy(mem.address);
skipIteration = true;
}
}
// call pushes the address onto the future addresses.
else if(Instruction.equals(CALL ,5)){
pushAddr(CallReturnVal);
}
}
}
private void printReg() {
for (int i = 0; i < 32; i++) {
var line = "r"+ i + ":" + Registers.get(i);
output.add(line);
System.out.println(line);
}
System.out.println("Total clock cycles: " + CURRENT_CLOCK_CYCLE);
}
private void printMem() {
for (int i = 0; i < 350; i++) {
Word32 addr = new Word32();
Word32 value = new Word32();
int n = i;
int k = 31;
while(n > 0){
if(n % 2 != 0)
addr.setBitN(k, new Bit(true));
else
addr.setBitN(k, new Bit(false));
n /= 2;
k--;
}
addr.copy(mem.address);
mem.read();
mem.value.copy(value);
var line = i + ":" + value;
output.add(line);
System.out.println(line);
}
System.out.println("Total clock cycles: " + CURRENT_CLOCK_CYCLE);
}
private void store() {
String fullInstruct = Instruction.toString();
if(is2R){
// If calculation is complete, send to register with ALU result.
if(OpCodesFormat.contains(fullInstruct.substring(0,9)) && !Instruction.equals(ALU.COMPARE, 5))
SendValToRegister(Instruction, alu.result);
// If copy, then send value in 2r or immediate formatting.
else if(Instruction.equals(COPY, 5)){
Bit b = new Bit(false);
Instruction.getBitN(5, b);
if(b.getValue() == Bit.boolValues.TRUE)
SendValToRegister(Instruction, OP1);
else
SendAlternateValToRegister(OP1);
}
// Send val to memory if store.
else if(Instruction.equals(STORE, 5)){
SendValToMem(Instruction);
}
}
}
// Helper methods:
// Generate an immediate value as a word32 for input.
private Word32 GenerateImmediateVal(Word16 inp){
Word32 FIN_VAL = new Word32();
Bit signBit = new Bit(false);
inp.getBitN(6, signBit);
for(int i = 0; i < 5; i++){
Bit B = new Bit(false);
inp.getBitN(10 - i, B);
FIN_VAL.setBitN(31 - i, B);
}
if(signBit.getValue() == Bit.boolValues.TRUE){
for(int i = 0; i < 27; i++)
FIN_VAL.setBitN(i, new Bit(true));
}
return FIN_VAL;
}
// Retrieve value from register, depending on the choice it can depend
// on the index in which the user wants (first or second).
private Word32 RetrieveValFromRegister(Word16 inp, int choice){
int start = 10;
if(choice == 1 || choice == 2)
start = 15;
int end = start - 5;
return Registers.get(generateIndex(inp, start, end));
}
// Creates an index based on the instructions inputted.
private int generateIndex(Word16 inp, int start, int end){
Word32 num = new Word32();
Bit b = new Bit(false);
int i = 0;
while(end < start){
inp.getBitN(start, b);
num.setBitN(31-i, b);
i++;
start--;
}
Word32 iterator = new Word32();
int fin = 0;
while(!iterator.equals(num)) {
Word32 temp = new Word32();
iterator.copy(temp);
fin++;
Adder.add(temp, ONE, iterator);
}
return fin;
}
// sendVal to register takes the value of a word and sends it to a register address.
private void SendValToRegister(Word16 addr, Word32 val){
int start = 15;
val.copy(Registers.get(generateIndex(addr, start, start-5)));
}
// In cases where an address val is being sent to another address val, this
// is done instead. It simply takes the instruction address and uses it inplace
// to then send it to the value.
private void SendAlternateValToRegister(Word32 op1){
int start = 15;
Word16 Bot = new Word16();
Instruction.copy(Bot);
op1.copy(Registers.get(generateIndex(Bot, start, start-5)));
}
// sendValToMem simply gets the OP1 address and then sends its input into
// an address in memory.
private void SendValToMem(Word16 inp){
mem.address.copy(CURR_ADDR);
Registers.get(generateIndex(inp,15,10)).copy(mem.address);
OP1.copy(mem.value);
mem.write();
CURR_ADDR.copy(mem.address);
CURRENT_CLOCK_CYCLE += 300;
}
// RetrievalFromMem takes an address from OP 1 and then
// calculates the proximity the from the value of register
// OP 2 to then derive a value.
public void RetrieveValFromMem(Word32 OP1, Word32 OP2){
Word32 addr = new Word32();
Word32 o1C = new Word32();
Word32 o2C = new Word32();
OP1.copy(o1C);
OP2.copy(o2C);
Bit MSB = new Bit(false);
OP1.getBitN(0, MSB);
if(MSB.getValue() == Bit.boolValues.FALSE)
Adder.add(o1C, o2C, addr);
else {
Word32 subtract = new Word32();
OP1.not(subtract);
Word32 positive = new Word32();
Adder.add(subtract, ONE, positive);
Adder.subtract(o2C,positive ,addr);
}
mem.address.copy(CURR_ADDR);
addr.copy(mem.address);
mem.read();
mem.value.copy(Registers.get(generateIndex(Instruction, 15,10)));
CURR_ADDR.copy(mem.address);
CURRENT_CLOCK_CYCLE += 300;
}
// GenerateCallReturnValue simply generates a call return value depending on input.
private Word32 GenerateCallReturnValue(Word16 inp){
Word32 FIN_VAL = new Word32();
Bit signBit = new Bit(false);
inp.getBitN(6, signBit);
Bit C = new Bit(false);
int n = 0;
for(int i = 15; i > 5; i--){
inp.getBitN(i,C);
FIN_VAL.setBitN(31-n,C);
n++;
}
if(signBit.getValue() == Bit.boolValues.TRUE){
for(int i = 0; i < 22; i++)
FIN_VAL.setBitN(i, new Bit(true));
}
return FIN_VAL;
}
// pushAddr takes the address and pushes the next address into saved addresses.
// it then reacts from memory the current address.
private void pushAddr(Word32 dest){
Word32 cp = new Word32();
PC.copy(cp);
Word32 S_ADD = new Word32();
Adder.add(cp, ONE, S_ADD);
Saved_Addr.add(S_ADD);
Word32 res = new Word32();
Adder.add(PC, dest, res);
res.copy(PC);
PC.copy(mem.address);
skipIteration = true;
}
}