PersistentTable.cc revision 6797
16145Snate@binkert.org
26145Snate@binkert.org/*
36145Snate@binkert.org * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
46145Snate@binkert.org * All rights reserved.
56145Snate@binkert.org *
66145Snate@binkert.org * Redistribution and use in source and binary forms, with or without
76145Snate@binkert.org * modification, are permitted provided that the following conditions are
86145Snate@binkert.org * met: redistributions of source code must retain the above copyright
96145Snate@binkert.org * notice, this list of conditions and the following disclaimer;
106145Snate@binkert.org * redistributions in binary form must reproduce the above copyright
116145Snate@binkert.org * notice, this list of conditions and the following disclaimer in the
126145Snate@binkert.org * documentation and/or other materials provided with the distribution;
136145Snate@binkert.org * neither the name of the copyright holders nor the names of its
146145Snate@binkert.org * contributors may be used to endorse or promote products derived from
156145Snate@binkert.org * this software without specific prior written permission.
166145Snate@binkert.org *
176145Snate@binkert.org * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
186145Snate@binkert.org * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
196145Snate@binkert.org * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
206145Snate@binkert.org * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
216145Snate@binkert.org * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
226145Snate@binkert.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
236145Snate@binkert.org * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
246145Snate@binkert.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
256145Snate@binkert.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
266145Snate@binkert.org * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
276145Snate@binkert.org * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
286145Snate@binkert.org */
296145Snate@binkert.org
306145Snate@binkert.org#include "mem/ruby/system/PersistentTable.hh"
316145Snate@binkert.org#include "mem/gems_common/util.hh"
326145Snate@binkert.org
336145Snate@binkert.org// randomize so that handoffs are not locality-aware
346145Snate@binkert.org// int persistent_randomize[] = {0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15};
357002Snate@binkert.org// int persistent_randomize[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
367002Snate@binkert.org
377002Snate@binkert.org
386154Snate@binkert.orgPersistentTable::PersistentTable()
396145Snate@binkert.org{
407002Snate@binkert.org  m_map_ptr = new Map<Address, PersistentTableEntry>;
417002Snate@binkert.org}
426145Snate@binkert.org
436145Snate@binkert.orgPersistentTable::~PersistentTable()
446145Snate@binkert.org{
456145Snate@binkert.org  delete m_map_ptr;
466145Snate@binkert.org  m_map_ptr = NULL;
476145Snate@binkert.org}
486145Snate@binkert.org
496145Snate@binkert.orgvoid PersistentTable::persistentRequestLock(const Address& address,
506145Snate@binkert.org                                            MachineID locker,
516145Snate@binkert.org                                            AccessType type)
526145Snate@binkert.org{
536145Snate@binkert.org
546145Snate@binkert.org  // if (locker == m_chip_ptr->getID()  )
556145Snate@binkert.org  // cout << "Chip " << m_chip_ptr->getID() << ": " << llocker
566145Snate@binkert.org  //      << " requesting lock for " << address << endl;
576145Snate@binkert.org
586145Snate@binkert.org  // MachineID locker = (MachineID) persistent_randomize[llocker];
596145Snate@binkert.org
606145Snate@binkert.org  assert(address == line_address(address));
616145Snate@binkert.org  if (!m_map_ptr->exist(address)) {
626145Snate@binkert.org    // Allocate if not present
636145Snate@binkert.org    PersistentTableEntry entry;
646145Snate@binkert.org    entry.m_starving.add(locker);
656145Snate@binkert.org    if (type == AccessType_Write) {
666145Snate@binkert.org      entry.m_request_to_write.add(locker);
676145Snate@binkert.org    }
686145Snate@binkert.org    m_map_ptr->add(address, entry);
696145Snate@binkert.org  } else {
706145Snate@binkert.org    PersistentTableEntry& entry = m_map_ptr->lookup(address);
716145Snate@binkert.org
726145Snate@binkert.org    //
736145Snate@binkert.org    // Make sure we're not already in the locked set
746145Snate@binkert.org    //
756145Snate@binkert.org    assert(!(entry.m_starving.isElement(locker)));
766145Snate@binkert.org
776145Snate@binkert.org    entry.m_starving.add(locker);
786145Snate@binkert.org    if (type == AccessType_Write) {
796145Snate@binkert.org      entry.m_request_to_write.add(locker);
806145Snate@binkert.org    }
816145Snate@binkert.org    assert(entry.m_marked.isSubset(entry.m_starving));
826145Snate@binkert.org  }
836145Snate@binkert.org}
846145Snate@binkert.org
856145Snate@binkert.orgvoid PersistentTable::persistentRequestUnlock(const Address& address,
866145Snate@binkert.org                                              MachineID unlocker)
876145Snate@binkert.org{
886145Snate@binkert.org  // if (unlocker == m_chip_ptr->getID() )
896145Snate@binkert.org  // cout << "Chip " << m_chip_ptr->getID() << ": " << uunlocker
906145Snate@binkert.org  //      << " requesting unlock for " << address << endl;
916145Snate@binkert.org
926145Snate@binkert.org  // MachineID unlocker = (MachineID) persistent_randomize[uunlocker];
936145Snate@binkert.org
946145Snate@binkert.org  assert(address == line_address(address));
956145Snate@binkert.org  assert(m_map_ptr->exist(address));
966145Snate@binkert.org  PersistentTableEntry& entry = m_map_ptr->lookup(address);
976145Snate@binkert.org
986145Snate@binkert.org  //
996145Snate@binkert.org  // Make sure we're in the locked set
1006145Snate@binkert.org  //
1016145Snate@binkert.org  assert(entry.m_starving.isElement(unlocker));
1026145Snate@binkert.org  assert(entry.m_marked.isSubset(entry.m_starving));
1036145Snate@binkert.org  entry.m_starving.remove(unlocker);
1046145Snate@binkert.org  entry.m_marked.remove(unlocker);
1056145Snate@binkert.org  entry.m_request_to_write.remove(unlocker);
1066145Snate@binkert.org  assert(entry.m_marked.isSubset(entry.m_starving));
1076145Snate@binkert.org
1086145Snate@binkert.org  // Deallocate if empty
1096145Snate@binkert.org  if (entry.m_starving.isEmpty()) {
1106145Snate@binkert.org    assert(entry.m_marked.isEmpty());
1116145Snate@binkert.org    m_map_ptr->erase(address);
1126145Snate@binkert.org  }
1136145Snate@binkert.org}
1146145Snate@binkert.org
1156145Snate@binkert.orgbool PersistentTable::okToIssueStarving(const Address& address,
1166145Snate@binkert.org                                        MachineID machId) const
1176145Snate@binkert.org{
1186145Snate@binkert.org  assert(address == line_address(address));
1196145Snate@binkert.org  if (!m_map_ptr->exist(address)) {
1206145Snate@binkert.org    //
1216145Snate@binkert.org    // No entry present
1226145Snate@binkert.org    //
1236145Snate@binkert.org    return true;
1246145Snate@binkert.org  } else if (m_map_ptr->lookup(address).m_starving.isElement(machId)) {
1256145Snate@binkert.org    //
1266145Snate@binkert.org    // We can't issue another lockdown until are previous unlock has occurred
1276145Snate@binkert.org    //
1286145Snate@binkert.org    return false;
1296145Snate@binkert.org  } else {
1306145Snate@binkert.org    return (m_map_ptr->lookup(address).m_marked.isEmpty());
1316145Snate@binkert.org  }
1326145Snate@binkert.org}
1336145Snate@binkert.org
1346145Snate@binkert.orgMachineID PersistentTable::findSmallest(const Address& address) const
1356145Snate@binkert.org{
1366145Snate@binkert.org  assert(address == line_address(address));
1376145Snate@binkert.org  assert(m_map_ptr->exist(address));
1386145Snate@binkert.org  const PersistentTableEntry& entry = m_map_ptr->lookup(address);
1396145Snate@binkert.org  return entry.m_starving.smallestElement();
1406145Snate@binkert.org}
1416145Snate@binkert.org
1426145Snate@binkert.orgAccessType PersistentTable::typeOfSmallest(const Address& address) const
1436145Snate@binkert.org{
1446145Snate@binkert.org  assert(address == line_address(address));
1456145Snate@binkert.org  assert(m_map_ptr->exist(address));
1466145Snate@binkert.org  const PersistentTableEntry& entry = m_map_ptr->lookup(address);
1476145Snate@binkert.org  if (entry.m_request_to_write.isElement(entry.m_starving.smallestElement())) {
1486145Snate@binkert.org    return AccessType_Write;
1496145Snate@binkert.org  } else {
1506145Snate@binkert.org    return AccessType_Read;
1516145Snate@binkert.org  }
1526145Snate@binkert.org}
1536145Snate@binkert.org
1546145Snate@binkert.orgvoid PersistentTable::markEntries(const Address& address)
1556145Snate@binkert.org{
1566145Snate@binkert.org  assert(address == line_address(address));
1576145Snate@binkert.org  if (m_map_ptr->exist(address)) {
1586145Snate@binkert.org    PersistentTableEntry& entry = m_map_ptr->lookup(address);
1596145Snate@binkert.org
1606145Snate@binkert.org    //
1616145Snate@binkert.org    // None should be marked
1626145Snate@binkert.org    //
1636145Snate@binkert.org    assert(entry.m_marked.isEmpty());
1646145Snate@binkert.org
1656145Snate@binkert.org    //
1666145Snate@binkert.org    // Mark all the nodes currently in the table
1676145Snate@binkert.org    //
1686145Snate@binkert.org    entry.m_marked = entry.m_starving;
1696145Snate@binkert.org  }
1706145Snate@binkert.org}
1716145Snate@binkert.org
1726145Snate@binkert.orgbool PersistentTable::isLocked(const Address& address) const
1736145Snate@binkert.org{
1746145Snate@binkert.org  assert(address == line_address(address));
1756145Snate@binkert.org  // If an entry is present, it must be locked
1766145Snate@binkert.org  return (m_map_ptr->exist(address));
1776145Snate@binkert.org}
1786145Snate@binkert.org
1796145Snate@binkert.orgint PersistentTable::countStarvingForAddress(const Address& address) const
1806145Snate@binkert.org{
1816145Snate@binkert.org  if (m_map_ptr->exist(address)) {
1826145Snate@binkert.org    PersistentTableEntry& entry = m_map_ptr->lookup(address);
1836145Snate@binkert.org    return (entry.m_starving.count());
1846145Snate@binkert.org  }
1856145Snate@binkert.org  else {
1866145Snate@binkert.org    return 0;
1876145Snate@binkert.org  }
1886145Snate@binkert.org}
1896145Snate@binkert.org
1906145Snate@binkert.orgint 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