-
Notifications
You must be signed in to change notification settings - Fork 0
/
thumbsim_driver.cpp
149 lines (135 loc) · 4.59 KB
/
thumbsim_driver.cpp
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
#include "thumbsim.hpp"
#include <cmath>
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<Data16, Data16>::write(const unsigned int addr, const Data16 data) {
// data is in native format
int i;
unsigned short myAddr = addr - base;
if (size() < myAddr + 2) {
m.resize(myAddr + 2, 0);
}
if (myAddr < lowest) lowest = myAddr;
if (myAddr > highest) highest = myAddr;
if (opts.writes) {
cout << hex << addr << ": " << data << " ( ";
for (i = 0 ; i < 2 ; i++) {
cout << static_cast<unsigned int>(data.data_ubyte2(i)) << ' ';
}
cout << ")" << endl;
}
m[myAddr] = data;
}
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 Data16 Memory<Data16, Data16>::operator[](const unsigned int addr) const {
unsigned short myAddr = addr - base;
return m[myAddr];
}
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]);
if ((byte == 0x3) && (dt == INSTRUCTIONS)) {
cout << hex << d << endl;
} else if ((byte == 0x3) && (dt == DATA) && (d.data_uint() != 0)) {
cout << hex << addr - 3 + getBase() << ": " << d << endl;
}
}
}
template<>
void Memory<Data16, Data16>::dump(DataType dt) const {
if (dt == DATA) {
for_each(m.begin(), m.end(), Data16::printD);
}
}
template<>
void Memory<Data32, Data32>::dump(DataType dt) const {
if (dt == DATA) {
for_each(m.begin(), m.end(), Data32::printD);
}
}
// CPE 315: You must implement and call this function for each
// memory address (dmem only) accessed by the program. 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 block_num_bits = log2(blocksize);
unsigned int row_num_bits = log2(size/blocksize);
unsigned int tag_num_bits = 32 - block_num_bits - row_num_bits;
unsigned int tag = address >> (block_num_bits + row_num_bits);
unsigned int row_bits = ((address << tag_num_bits) >> (tag_num_bits + block_num_bits)) % entries.size();
if (entries[row_bits] == tag) {
hits++;
return true;
}
entries[row_bits] = tag;
misses++;
return false;
}
void Stats::print() {
cout << dec
<< "Total number of dynamic instructions: " << instrs << 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
<< "Branches: " << endl
<< " Forward:" << endl
<< " Taken: " << numForwardBranchesTaken << endl
<< " Not taken: " << numForwardBranchesNotTaken << endl
<< " Backward:" << endl
<< " Taken: " << numBackwardBranchesTaken << endl
<< " Not taken: " << numBackwardBranchesNotTaken << endl;
}
unsigned int swizzle(unsigned int d) {
return (((d >> 24) & 0xff) |
((d >> 8) & 0xff00) |
((d << 8) & 0xff0000) |
((d << 24) & 0xff000000));
}