-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathaddr_trans_table.h
147 lines (117 loc) · 4.01 KB
/
addr_trans_table.h
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
// addr_trans_table.h
// Copyright (c) 2014 Jinglei Ren <jinglei@ren.systems>
#ifndef SEXAIN_ADDR_TRANS_TABLE_H_
#define SEXAIN_ADDR_TRANS_TABLE_H_
#include <cerrno>
#include <cstdint>
#include <vector>
#include <unordered_map>
#include <initializer_list>
#include "index_queue.h"
#include "profiler.h"
typedef int64_t Tag; // never negative
typedef uint64_t Addr;
struct ATTEntry {
enum State {
CLEAN = 0,
LOAN,
FREE,
DIRTY, // max queue index
HIDDEN,
TEMP,
STAINED,
};
Tag phy_tag;
Addr mach_base;
IndexNode queue_node;
State state;
// Statistics
int epoch_reads;
int epoch_writes;
static const char* state_strings[];
ATTEntry() : epoch_reads(0), epoch_writes(0) { }
const char* StateString() const {
return state_strings[state];
}
static int StateIndex(State state) {
return state < DIRTY ? state : DIRTY;
}
};
class AddrTransTable : public IndexArray {
public:
AddrTransTable(int length, int block_bits);
int Lookup(Tag phy_tag, Profiler& pf);
int Setup(Tag phy_tag, Addr mach_base, ATTEntry::State state, Profiler& pf);
void ShiftState(int index, ATTEntry::State state, Profiler& pf);
void Reset(int index, Addr new_base, ATTEntry::State new_state, Profiler& pf);
int VisitQueue(ATTEntry::State state, QueueVisitor* visitor);
bool Contains(Addr phy_addr, Profiler& pf) const;
const ATTEntry& At(int i) const;
bool IsEmpty(ATTEntry::State state) const;
int GetLength(ATTEntry::State state) const;
int GetFront(ATTEntry::State state) const;
Tag ToTag(Addr addr) const { return Tag(addr >> block_bits_); }
Addr ToAddr(Tag tag) const { return Addr(tag) << block_bits_; }
Addr Translate(Addr phy_addr, Addr mach_base) const;
int length() const { return length_; }
int block_size() const { return 1 << block_bits_; }
int block_bits() const { return block_bits_; }
void AddBlockRead(int index) { ++entries_[index].epoch_reads; }
void AddBlockWrite(int index) { ++entries_[index].epoch_writes; }
void ClearStats(Profiler& pf);
const std::vector<ATTEntry>& entries() const { return entries_; }
IndexNode& operator[](int i) { return entries_[i].queue_node; }
const IndexQueue& GetQueue(ATTEntry::State state) const;
private:
const int length_;
const int block_bits_;
const Addr block_mask_;
std::unordered_map<Tag, int> tag_index_;
std::vector<ATTEntry> entries_;
std::vector<IndexQueue> queues_;
IndexQueue& GetQueue(ATTEntry::State state);
};
inline AddrTransTable::AddrTransTable(int length, int block_bits) :
length_(length), block_bits_(block_bits), block_mask_(block_size() - 1),
entries_(length_), queues_(ATTEntry::DIRTY + 1, *this) {
for (int i = 0; i < length_; ++i) {
GetQueue(ATTEntry::FREE).PushBack(i);
}
}
inline const ATTEntry& AddrTransTable::At(int i) const {
assert(i >= 0 && i < length_);
return entries_[i];
}
inline bool AddrTransTable::Contains(Addr phy_addr, Profiler& pf) const {
pf.AddTableOp();
return tag_index_.find(Tag(phy_addr)) != tag_index_.end();
}
inline int AddrTransTable::VisitQueue(ATTEntry::State state,
QueueVisitor* visitor) {
assert(state <= ATTEntry::DIRTY);
return GetQueue(state).Accept(visitor);
}
inline bool AddrTransTable::IsEmpty(ATTEntry::State state) const {
assert(state <= ATTEntry::DIRTY);
return GetQueue(state).Empty();
}
inline int AddrTransTable::GetLength(ATTEntry::State state) const {
assert(state <= ATTEntry::DIRTY);
return GetQueue(state).length();
}
inline int AddrTransTable::GetFront(ATTEntry::State state) const {
assert(state < ATTEntry::DIRTY);
return GetQueue(state).Front();
}
inline Addr AddrTransTable::Translate(
Addr phy_addr, Addr mach_base) const {
assert((mach_base & block_mask_) == 0);
return mach_base + (phy_addr & block_mask_);
}
inline const IndexQueue& AddrTransTable::GetQueue(ATTEntry::State state) const {
return queues_[ATTEntry::StateIndex(state)];
}
inline IndexQueue& AddrTransTable::GetQueue(ATTEntry::State state) {
return queues_[ATTEntry::StateIndex(state)];
}
#endif // SEXAIN_ADDR_TRANS_TABLE_H_