sim-ruby: checkpointing fixes and dependent eventq improvements
[gem5.git] / src / mem / ruby / system / PersistentTable.cc
1 /*
2 * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "mem/ruby/system/PersistentTable.hh"
30
31 using namespace std;
32
33 // randomize so that handoffs are not locality-aware
34 #if 0
35 int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6,
36 10, 14, 3, 7, 11, 15};
37 int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
38 10, 11, 12, 13, 14, 15};
39 #endif
40
41 PersistentTable::PersistentTable()
42 {
43 }
44
45 PersistentTable::~PersistentTable()
46 {
47 }
48
49 void
50 PersistentTable::persistentRequestLock(const Address& address,
51 MachineID locker,
52 AccessType type)
53 {
54 #if 0
55 if (locker == m_chip_ptr->getID())
56 cout << "Chip " << m_chip_ptr->getID() << ": " << llocker
57 << " requesting lock for " << address << endl;
58
59 MachineID locker = (MachineID) persistent_randomize[llocker];
60 #endif
61
62 assert(address == line_address(address));
63
64 static const PersistentTableEntry dflt;
65 pair<AddressMap::iterator, bool> r =
66 m_map.insert(AddressMap::value_type(address, dflt));
67 bool present = !r.second;
68 AddressMap::iterator i = r.first;
69 PersistentTableEntry &entry = i->second;
70
71 if (present) {
72 // Make sure we're not already in the locked set
73 assert(!(entry.m_starving.isElement(locker)));
74 }
75
76 entry.m_starving.add(locker);
77 if (type == AccessType_Write)
78 entry.m_request_to_write.add(locker);
79
80 if (present)
81 assert(entry.m_marked.isSubset(entry.m_starving));
82 }
83
84 void
85 PersistentTable::persistentRequestUnlock(const Address& address,
86 MachineID unlocker)
87 {
88 #if 0
89 if (unlocker == m_chip_ptr->getID())
90 cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker
91 << " requesting unlock for " << address << endl;
92
93 MachineID unlocker = (MachineID) persistent_randomize[uunlocker];
94 #endif
95
96 assert(address == line_address(address));
97 assert(m_map.count(address));
98 PersistentTableEntry& entry = m_map[address];
99
100 //
101 // Make sure we're in the locked set
102 //
103 assert(entry.m_starving.isElement(unlocker));
104 assert(entry.m_marked.isSubset(entry.m_starving));
105 entry.m_starving.remove(unlocker);
106 entry.m_marked.remove(unlocker);
107 entry.m_request_to_write.remove(unlocker);
108 assert(entry.m_marked.isSubset(entry.m_starving));
109
110 // Deallocate if empty
111 if (entry.m_starving.isEmpty()) {
112 assert(entry.m_marked.isEmpty());
113 m_map.erase(address);
114 }
115 }
116
117 bool
118 PersistentTable::okToIssueStarving(const Address& address,
119 MachineID machId) const
120 {
121 assert(address == line_address(address));
122
123 AddressMap::const_iterator i = m_map.find(address);
124 if (i == m_map.end()) {
125 // No entry present
126 return true;
127 }
128
129 const PersistentTableEntry &entry = i->second;
130
131 if (entry.m_starving.isElement(machId)) {
132 // We can't issue another lockdown until are previous unlock
133 // has occurred
134 return false;
135 }
136
137 return entry.m_marked.isEmpty();
138 }
139
140 MachineID
141 PersistentTable::findSmallest(const Address& address) const
142 {
143 assert(address == line_address(address));
144 AddressMap::const_iterator i = m_map.find(address);
145 assert(i != m_map.end());
146 const PersistentTableEntry& entry = i->second;
147 return entry.m_starving.smallestElement();
148 }
149
150 AccessType
151 PersistentTable::typeOfSmallest(const Address& address) const
152 {
153 assert(address == line_address(address));
154 AddressMap::const_iterator i = m_map.find(address);
155 assert(i != m_map.end());
156 const PersistentTableEntry& entry = i->second;
157 if (entry.m_request_to_write.
158 isElement(entry.m_starving.smallestElement())) {
159 return AccessType_Write;
160 } else {
161 return AccessType_Read;
162 }
163 }
164
165 void
166 PersistentTable::markEntries(const Address& address)
167 {
168 assert(address == line_address(address));
169 AddressMap::iterator i = m_map.find(address);
170 if (i == m_map.end())
171 return;
172
173 PersistentTableEntry& entry = i->second;
174
175 // None should be marked
176 assert(entry.m_marked.isEmpty());
177
178 // Mark all the nodes currently in the table
179 entry.m_marked = entry.m_starving;
180 }
181
182 bool
183 PersistentTable::isLocked(const Address& address) const
184 {
185 assert(address == line_address(address));
186
187 // If an entry is present, it must be locked
188 return m_map.count(address) > 0;
189 }
190
191 int
192 PersistentTable::countStarvingForAddress(const Address& address) const
193 {
194 assert(address == line_address(address));
195 AddressMap::const_iterator i = m_map.find(address);
196 if (i == m_map.end())
197 return 0;
198
199 const PersistentTableEntry& entry = i->second;
200 return entry.m_starving.count();
201 }
202
203 int
204 PersistentTable::countReadStarvingForAddress(const Address& address) const
205 {
206 assert(address == line_address(address));
207 AddressMap::const_iterator i = m_map.find(address);
208 if (i == m_map.end())
209 return 0;
210
211 const PersistentTableEntry& entry = i->second;
212 return entry.m_starving.count() - entry.m_request_to_write.count();
213 }
214
215 void
216 PersistentTable::print(ostream& out) const
217 {
218 }
219