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