PersistentTable.cc revision 6791
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 "PersistentTable.hh" 31#include "NetDest.h" 32#include "Map.h" 33#include "Address.h" 34#include "AbstractChip.h" 35#include "util.h" 36 37// randomize so that handoffs are not locality-aware 38// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15}; 39// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; 40 41 42class PersistentTableEntry { 43public: 44 NetDest m_starving; 45 NetDest m_marked; 46 NetDest m_request_to_write; 47}; 48 49PersistentTable::PersistentTable(AbstractChip* chip_ptr, int version) 50{ 51 m_chip_ptr = chip_ptr; 52 m_map_ptr = new Map<Address, PersistentTableEntry>; 53 m_version = version; 54} 55 56PersistentTable::~PersistentTable() 57{ 58 delete m_map_ptr; 59 m_map_ptr = NULL; 60 m_chip_ptr = NULL; 61} 62 63void PersistentTable::persistentRequestLock(const Address& address, MachineID locker, AccessType type) 64{ 65 66 // if (locker == m_chip_ptr->getID() ) 67 // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker << " requesting lock for " << address << endl; 68 69 // MachineID locker = (MachineID) persistent_randomize[llocker]; 70 71 assert(address == line_address(address)); 72 if (!m_map_ptr->exist(address)) { 73 // Allocate if not present 74 PersistentTableEntry entry; 75 entry.m_starving.add(locker); 76 if (type == AccessType_Write) { 77 entry.m_request_to_write.add(locker); 78 } 79 m_map_ptr->add(address, entry); 80 } else { 81 PersistentTableEntry& entry = m_map_ptr->lookup(address); 82 assert(!(entry.m_starving.isElement(locker))); // Make sure we're not already in the locked set 83 84 entry.m_starving.add(locker); 85 if (type == AccessType_Write) { 86 entry.m_request_to_write.add(locker); 87 } 88 assert(entry.m_marked.isSubset(entry.m_starving)); 89 } 90} 91 92void PersistentTable::persistentRequestUnlock(const Address& address, MachineID unlocker) 93{ 94 // if (unlocker == m_chip_ptr->getID() ) 95 // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker << " requesting unlock for " << address << endl; 96 97 // MachineID unlocker = (MachineID) persistent_randomize[uunlocker]; 98 99 assert(address == line_address(address)); 100 assert(m_map_ptr->exist(address)); 101 PersistentTableEntry& entry = m_map_ptr->lookup(address); 102 assert(entry.m_starving.isElement(unlocker)); // Make sure we're in the locked set 103 assert(entry.m_marked.isSubset(entry.m_starving)); 104 entry.m_starving.remove(unlocker); 105 entry.m_marked.remove(unlocker); 106 entry.m_request_to_write.remove(unlocker); 107 assert(entry.m_marked.isSubset(entry.m_starving)); 108 109 // Deallocate if empty 110 if (entry.m_starving.isEmpty()) { 111 assert(entry.m_marked.isEmpty()); 112 m_map_ptr->erase(address); 113 } 114} 115 116bool PersistentTable::okToIssueStarving(const Address& address) const 117{ 118 assert(address == line_address(address)); 119 if (!m_map_ptr->exist(address)) { 120 return true; // No entry present 121 } else if (m_map_ptr->lookup(address).m_starving.isElement( (MachineID) {MachineType_L1Cache, m_version})) { 122 return false; // We can't issue another lockdown until are previous unlock has occurred 123 } else { 124 return (m_map_ptr->lookup(address).m_marked.isEmpty()); 125 } 126} 127 128MachineID PersistentTable::findSmallest(const Address& address) const 129{ 130 assert(address == line_address(address)); 131 assert(m_map_ptr->exist(address)); 132 const PersistentTableEntry& entry = m_map_ptr->lookup(address); 133 // cout << "Node " << m_chip_ptr->getID() << " returning " << persistent_randomize[entry.m_starving.smallestElement()] << " for findSmallest(" << address << ")" << endl; 134 // return (MachineID) persistent_randomize[entry.m_starving.smallestElement()]; 135 return (MachineID) { MachineType_L1Cache, entry.m_starving.smallestElement() }; 136} 137 138AccessType PersistentTable::typeOfSmallest(const Address& address) const 139{ 140 assert(address == line_address(address)); 141 assert(m_map_ptr->exist(address)); 142 const PersistentTableEntry& entry = m_map_ptr->lookup(address); 143 if (entry.m_request_to_write.isElement((MachineID) {MachineType_L1Cache, entry.m_starving.smallestElement()})) { 144 return AccessType_Write; 145 } else { 146 return AccessType_Read; 147 } 148} 149 150void PersistentTable::markEntries(const Address& address) 151{ 152 assert(address == line_address(address)); 153 if (m_map_ptr->exist(address)) { 154 PersistentTableEntry& entry = m_map_ptr->lookup(address); 155 assert(entry.m_marked.isEmpty()); // None should be marked 156 entry.m_marked = entry.m_starving; // Mark all the nodes currently in the table 157 } 158} 159 160bool PersistentTable::isLocked(const Address& address) const 161{ 162 assert(address == line_address(address)); 163 // If an entry is present, it must be locked 164 return (m_map_ptr->exist(address)); 165} 166 167int PersistentTable::countStarvingForAddress(const Address& address) const 168{ 169 if (m_map_ptr->exist(address)) { 170 PersistentTableEntry& entry = m_map_ptr->lookup(address); 171 return (entry.m_starving.count()); 172 } 173 else { 174 return 0; 175 } 176} 177 178int PersistentTable::countReadStarvingForAddress(const Address& address) const 179{ 180 int count = 0; 181 if (m_map_ptr->exist(address)) { 182 PersistentTableEntry& entry = m_map_ptr->lookup(address); 183 return (entry.m_starving.count() - entry.m_request_to_write.count()); 184 } 185 else { 186 return 0; 187 } 188} 189 190 191