forked from moizumi99/m99_riscv_emulator
-
Notifications
You must be signed in to change notification settings - Fork 0
/
memory_wrapper.cpp
110 lines (97 loc) · 3.27 KB
/
memory_wrapper.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
//
// Created by moiz on 1/19/20.
//
#include <stdexcept>
#include <cassert>
#include "memory_wrapper.h"
namespace RISCV_EMULATOR {
MemoryWrapper::MemoryWrapper() {
assigned_ = {}; // Default value
for (auto &a: assigned_) {
a = false;
}
}
const uint8_t MemoryWrapper::ReadByte(size_t i) const {
uint64_t dram_address = (i >> kWordBits) << kWordBits;
uint64_t read_data = Read32(dram_address);
int byte_offset = i & 0b11;
read_data = read_data >> byte_offset * 8;
return static_cast<uint8_t>(read_data & 0xFF);
}
void MemoryWrapper::WriteByte(size_t i, uint8_t data) {
constexpr std::array<uint64_t, 4> mask = {
0xFFFFFF00,
0xFFFF00FF,
0xFF00FFFF,
0x00FFFFFF,
};
uint64_t dram_address = (i >> kWordBits) << kWordBits;
uint64_t original_data = Read32(dram_address);
uint64_t write_data = data;
int byte_offset = i & 0b11;
write_data = (original_data & mask[byte_offset]) | (write_data << byte_offset * 8);
Write32(dram_address, (uint32_t)write_data);
}
const uint16_t MemoryWrapper::Read16(size_t i) const {
assert((i & 1) == 0);
uint64_t dram_address = (i >> kWordBits) << kWordBits;
uint64_t read_data = Read32(dram_address);
int short_word_offset = i & 0b11;
read_data = read_data >> short_word_offset * 8;
return static_cast<uint16_t>(read_data & 0xFFFF);
}
void MemoryWrapper::Write16(size_t i, uint16_t data) {
assert((i & 1) == 0);
constexpr std::array<uint64_t, 2> mask = {
0xFFFF0000,
0x0000FFFF,
};
uint64_t dram_address = (i >> kWordBits) << kWordBits;
uint32_t original_data = Read32(dram_address);
int short_word_offset = (i >> 1) & 1;
uint32_t write_data = (original_data & (uint32_t)mask[short_word_offset]) | (data << short_word_offset * 16);
Write32(dram_address, write_data);
}
const uint32_t MemoryWrapper::Read32(size_t i) const {
assert((i & 0b11) == 0);
int entry = (i >> kOffsetBits) & kEntryMask;
uint32_t read_data = 0;
if (CheckRange(entry)) {
int offset = i & kOffsetMask;
int word_offset = offset >> kWordBits;
read_data = mapping_[entry][word_offset];
}
return read_data;
}
void MemoryWrapper::Write32(size_t i, uint32_t value) {
assert((i & 0b11) == 0);
int entry = (i >> kOffsetBits) & kEntryMask;
if (!CheckRange(entry)) {
assigned_[entry] = true;
mapping_[entry].resize(1 << (kOffsetBits - kWordBits));
}
int offset = i & kOffsetMask;
int word_offset = offset >> kWordBits;
mapping_[entry][word_offset] = value;
}
const uint64_t MemoryWrapper::Read64(size_t i) const {
assert((i & 0b111) == 0);
uint64_t dram_address = (i >> kWordBits) << kWordBits;
uint64_t read_data_lower = Read32(dram_address);
uint64_t read_data_upper = Read32(dram_address + 4);
uint64_t read_data = read_data_lower | (read_data_upper << 32);
return read_data;
}
void MemoryWrapper::Write64(size_t i, uint64_t value) {
assert((i & 0b111) == 0);
uint64_t dram_address = (i >> kWordBits) << kWordBits;
Write32(dram_address, value & 0xFFFFFFFF);
Write32(dram_address + 4, (value >> 32) & 0xFFFFFFFF);
}
bool MemoryWrapper::operator==(MemoryWrapper &r) {
return (mapping_ == r.mapping_ && assigned_ == r.assigned_);
}
bool MemoryWrapper::operator!=(MemoryWrapper &r) {
return (mapping_ != r.mapping_ || assigned_ != r.assigned_);
}
} // namespace RISCV_EMULATOR