-
Notifications
You must be signed in to change notification settings - Fork 0
/
mipsim.cc
134 lines (124 loc) · 4.67 KB
/
mipsim.cc
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
#include <stdio.h>
#include <math.h>
#include "mipsim.hpp"
template<>
void Memory<Data8, Data32>::write(const unsigned int addr, const Data32 data) {
// data is in native format
// if little-endian, 3210 (MSB=3)
// memory is in big-endian format (0123, MSB=0)
int i;
unsigned int myAddr = addr - base;
if (size() < myAddr + 4) {
m.resize(myAddr + 4, 0);
}
if (myAddr < lowest) lowest = myAddr;
if (myAddr > highest) highest = myAddr;
if (opts.writes) {
cout << hex << addr << ": " << data << " ( ";
for (i = 0 ; i < 4 ; i++) {
cout << static_cast<unsigned int>(data.data_ubyte4(i)) << ' ';
}
cout << ")" << endl;
}
for (i = 0 ; i < 4 ; i++) {
m[myAddr+i] = Data8(data.data_ubyte4(i));
}
}
template<>
void Memory<Data32, Data32>::write(const unsigned int addr, const Data32 data) {
unsigned int myAddr = addr - base;
// cout << hex << addr << ": " << data << endl;
m[myAddr] = data;
}
template<>
const Data32 Memory<Data8, Data32>::operator[](const unsigned int addr) const {
unsigned int myAddr = addr - base;
return Data32(m[myAddr], m[myAddr+1], m[myAddr+2], m[myAddr+3]);
}
template<>
const Data32 Memory<Data32, Data32>::operator[](const unsigned int addr) const {
unsigned int myAddr = addr - base;
return m[myAddr];
}
template<>
void Memory<Data8, Data32>::dump(DataType dt) const {
Data32 d(0);
unsigned int addr;
for (addr = lowest ; addr <= highest + 3 ; addr++) {
unsigned int byte = addr & 0x3;
d.set_data_ubyte4(byte, m[addr]);
// cout << hex << byte << " " << static_cast<unsigned int>(m[addr]) << endl;
if ((byte == 0x3) && (dt == INSTRUCTIONS)) {
cout << hex << d << endl;
d.printI(d);
} else if ((byte == 0x3) && (dt == DATA) && (d.data_uint() != 0)) {
cout << addr - 3 + getBase() << ": " << d << endl;
}
}
}
template<>
void Memory<Data32, Data32>::dump(DataType dt) const {
if (dt == DATA) {
for_each(m.begin(), m.end(), Data32::printD);
}
}
// This must be updated by the students. It should return true for a
// cache hit and false for a cache miss, and on a cache miss, should
// update the cache tags. The "entries" vector contains the cache
// tags, so if you want to put the tag "t" into cache block "b", then
// evaluate "entries[b] = t;". The locals you have available to help
// you make this decision are "blocksize" (in bytes) and "size" (total
// cache size in blocks). You should also update the "hits" and
// "misses" counters.
bool Cache::access(unsigned int address) {
unsigned int cacheSize = this->size / this->blocksize;
unsigned int mask = (1U << (unsigned int) log2(size)) - 1;
unsigned int tag = address & ~mask;
unsigned int blockAddr = (address / this->blocksize) % cacheSize;
if(this->entries[blockAddr] == tag) {
this->hits++;
return true;
} else {
this->entries[blockAddr] = tag;
this->misses++;
return false;
}
}
void Stats::print() {
cout << dec
<< "Total number of dynamic instructions: " << instrs << endl
<< "Total number of cycles: " << cycles << endl
<< " RType: " << numRType << endl
<< " IType: " << numIType << endl
<< " JType: " << numJType << endl
<< "Number of Memory Reads: " << numMemReads << endl
<< "Number of Memory Writes: " << numMemWrites << endl
<< "Number of Register Reads: " << numRegReads << endl
<< "Number of Register Writes: " << numRegWrites << endl
<< "Number of Forwards:" << endl
<< " From Ex Stage " << exStageForward << endl
<< " From Mem Stage: " << memStageForward << endl
<< "Branches: " << endl
<< " Forward:" << endl
<< " Taken: " << numForwardBranchesTaken << endl
<< " Not taken: " << numForwardBranchesNotTaken << endl
<< " Backward:" << endl
<< " Taken: " << numBackwardBranchesTaken << endl
<< " Not taken: " << numBackwardBranchesNotTaken << endl
<< "Branch delay slot: " << endl
<< " Useful instruction: " << hasUsefulBranchDelaySlot << endl
<< " Not useful instruction: " << hasUselessBranchDelaySlot << endl
<< "Jump delay slot: " << endl
<< " Useful instruction: " << hasUsefulJumpDelaySlot << endl
<< " Not useful instruction: " << hasUselessJumpDelaySlot << endl
<< "Load Use Hazard: " << endl
<< " Has load use stall: " << loadHasLoadUseStall << endl
<< " Has load use hazard: " << loadHasLoadUseHazard << endl
<< " Has no load use hazard: " << loadHasNoLoadUseHazard << endl;
}
unsigned int swizzle(unsigned int d) {
return (((d >> 24) & 0xff) |
((d >> 8) & 0xff00) |
((d << 8) & 0xff0000) |
((d << 24) & 0xff000000));
}