-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemory.C
More file actions
156 lines (145 loc) · 4.79 KB
/
Memory.C
File metadata and controls
156 lines (145 loc) · 4.79 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
#include <iostream>
#include <iomanip>
#include "Memory.h"
#include "Tools.h"
//memInstance will be initialized to the single instance
//of the Memory class
Memory * Memory::memInstance = NULL;
/**
* Memory constructor
* initializes the mem array to 0
*/
Memory::Memory() {
for (int i = 0; i < MEMSIZE; i++) { mem[i] = 0; }
}
/**
* getInstance
* if memInstance is NULL then creates a Memory object
* and sets memInstance to point to it; returns memInstance
*
* @return memInstance
*/
Memory * Memory::getInstance() {
if (memInstance == NULL) memInstance = new Memory();
return memInstance;
}
/**
* getLong
* returns the 64-bit word at the indicated address; sets imem_error
* to false if the access is aligned and the address is within range;
* otherwise sets imem_error to true
*
* @param address of 64-bit word; access must be aligned (address % 8 == 0)
* @return imem_error is set to true or false
* @return returns 64-bit word at the specified address or 0 if the
* access is not aligned or out of range
*/
uint64_t Memory::getLong(int32_t address, bool & imem_error) {
uint8_t BYTE_SIZE = 8;
if (address % BYTE_SIZE == 0 && (address >= 0 && address < MEMSIZE)) {
imem_error = false;
uint64_t output = 0;
for (int i = 0; i < BYTE_SIZE; i++) {
output = Tools::copyBits(mem[address + i],
output, 0, i * BYTE_SIZE, BYTE_SIZE);
}
return output;
}
imem_error = true;
return 0;
}
/**
* getByte
* returns the byte (8-bits) at the indicated address if address
* is within range and sets imem_error; otherwise sets imem_error to
* true and returns 0
*
* @param address of byte
* @return imem_error is set to true or false
* @return byte at specified address or 0 if the address is out of range
*/
uint8_t Memory::getByte(int32_t address, bool & imem_error) {
if (address >= 0 && address < MEMSIZE) {
imem_error = false;
return mem[address];
}
imem_error = true;
return 0;
}
/**
* putLong
* sets the 64-bit word in memory at the indicated address to the
* value that is provided if the address is aligned and within range
* and sets imem_error to false; otherwise sets
* imem_error to true
*
* @param 64-bit value to be stored in memory (mem array)
* @param address of 64-bit word; access must be aligned (address % 8 == 0)
* @return imem_error is set to true or false
*/
void Memory::putLong(uint64_t value, int32_t address, bool & imem_error) {
uint8_t BYTE_SIZE = 8;
if (address % BYTE_SIZE == 0 && (address >= 0 && address < MEMSIZE)) {
imem_error = false;
for (int i = 0; i < BYTE_SIZE; i++) {
mem[address + i] = Tools::getByte(value, i);
}
}
else imem_error = true;
}
/**
* putByte
* sets the byte (8-bits) in memory at the indicated address to the value
* provided if the address is within range and sets imem_error to false;
* otherwise sets imem_error to true
*
* @param 8-bit value to be stored in memory (mem array)
* @param address of byte
* @return imem_error is set to true or false
*/
void Memory::putByte(uint8_t value, int32_t address, bool & imem_error) {
if (address >= 0 && address < MEMSIZE) {
imem_error = false;
mem[address] = value;
} else imem_error = true;
}
/**
* dump
* Output the contents of memory (mem array), four 64-bit words per line.
* Rather than output memory that contains a lot of 0s, it outputs
* a * after a line to indicate that the values in memory up to the next
* line displayed are identical.
*/
void Memory::dump() {
uint64_t prevLine[4] = {0, 0, 0, 0};
uint64_t currLine[4] = {0, 0, 0, 0};
int32_t i;
bool star = false;
bool mem_error;
//32 bytes per line (four 8-byte words)
for (i = 0; i < MEMSIZE; i+=32)
{
//get the values for the current line
for (int32_t j = 0; j < 4; j++) currLine[j] = getLong(i+j*8, mem_error);
//if they are the same as the values in the previous line then
//don't display them, but always display the first line
if (i == 0 || currLine[0] != prevLine[0] || currLine[1] != prevLine[1]
|| currLine[2] != prevLine[2] || currLine[3] != prevLine[3])
{
std::cout << std::endl << std::setw(3) << std::setfill('0')
<< std::hex << i << ": ";
for (int32_t j = 0; j < 4; j++)
std::cout << std::setw(16) << std::setfill('0')
<< std::hex << currLine[j] << " ";
star = false;
} else
{
//if this line is exactly like the previous line then
//just print a * if one hasn't been printed already
if (star == false) std::cout << "*";
star = true;
}
for (int32_t j = 0; j < 4; j++) prevLine[j] = currLine[j];
}
std::cout << std::endl;
}