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