diff options
-rw-r--r-- | src/mem/ruby/system/RubyPort.cc | 187 | ||||
-rw-r--r-- | src/mem/ruby/system/RubyPort.hh | 2 | ||||
-rw-r--r-- | src/mem/ruby/system/System.cc | 176 | ||||
-rw-r--r-- | src/mem/ruby/system/System.hh | 3 |
4 files changed, 180 insertions, 188 deletions
diff --git a/src/mem/ruby/system/RubyPort.cc b/src/mem/ruby/system/RubyPort.cc index f269f17fe..dcedc7841 100644 --- a/src/mem/ruby/system/RubyPort.cc +++ b/src/mem/ruby/system/RubyPort.cc @@ -234,189 +234,6 @@ RubyPort::M5Port::recvTimingReq(PacketPtr pkt) return false; } -bool -RubyPort::M5Port::doFunctionalRead(PacketPtr pkt) -{ - Address address(pkt->getAddr()); - Address line_address(address); - line_address.makeLineAddress(); - - AccessPermission access_perm = AccessPermission_NotPresent; - int num_controllers = ruby_system->m_abs_cntrl_vec.size(); - - DPRINTF(RubyPort, "Functional Read request for %s\n",address); - - unsigned int num_ro = 0; - unsigned int num_rw = 0; - unsigned int num_busy = 0; - unsigned int num_backing_store = 0; - unsigned int num_invalid = 0; - - // In this loop we count the number of controllers that have the given - // address in read only, read write and busy states. - for (int i = 0; i < num_controllers; ++i) { - access_perm = ruby_system->m_abs_cntrl_vec[i]-> - getAccessPermission(line_address); - if (access_perm == AccessPermission_Read_Only) - num_ro++; - else if (access_perm == AccessPermission_Read_Write) - num_rw++; - else if (access_perm == AccessPermission_Busy) - num_busy++; - else if (access_perm == AccessPermission_Backing_Store) - // See RubySlicc_Exports.sm for details, but Backing_Store is meant - // to represent blocks in memory *for Broadcast/Snooping protocols*, - // where memory has no idea whether it has an exclusive copy of data - // or not. - num_backing_store++; - else if (access_perm == AccessPermission_Invalid || - access_perm == AccessPermission_NotPresent) - num_invalid++; - } - assert(num_rw <= 1); - - uint8_t *data = pkt->getPtr<uint8_t>(true); - unsigned int size_in_bytes = pkt->getSize(); - unsigned startByte = address.getAddress() - line_address.getAddress(); - - // This if case is meant to capture what happens in a Broadcast/Snoop - // protocol where the block does not exist in the cache hierarchy. You - // only want to read from the Backing_Store memory if there is no copy in - // the cache hierarchy, otherwise you want to try to read the RO or RW - // copies existing in the cache hierarchy (covered by the else statement). - // The reason is because the Backing_Store memory could easily be stale, if - // there are copies floating around the cache hierarchy, so you want to read - // it only if it's not in the cache hierarchy at all. - if (num_invalid == (num_controllers - 1) && - num_backing_store == 1) - { - DPRINTF(RubyPort, "only copy in Backing_Store memory, read from it\n"); - for (int i = 0; i < num_controllers; ++i) { - access_perm = ruby_system->m_abs_cntrl_vec[i] - ->getAccessPermission(line_address); - if (access_perm == AccessPermission_Backing_Store) { - DataBlock& block = ruby_system->m_abs_cntrl_vec[i] - ->getDataBlock(line_address); - - DPRINTF(RubyPort, "reading from %s block %s\n", - ruby_system->m_abs_cntrl_vec[i]->name(), block); - for (unsigned i = 0; i < size_in_bytes; ++i) { - data[i] = block.getByte(i + startByte); - } - return true; - } - } - } else { - // In Broadcast/Snoop protocols, this covers if you know the block - // exists somewhere in the caching hierarchy, then you want to read any - // valid RO or RW block. In directory protocols, same thing, you want - // to read any valid readable copy of the block. - DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n", - num_busy, num_ro, num_rw); - // In this loop, we try to figure which controller has a read only or - // a read write copy of the given address. Any valid copy would suffice - // for a functional read. - for(int i = 0;i < num_controllers;++i) { - access_perm = ruby_system->m_abs_cntrl_vec[i] - ->getAccessPermission(line_address); - if(access_perm == AccessPermission_Read_Only || - access_perm == AccessPermission_Read_Write) - { - DataBlock& block = ruby_system->m_abs_cntrl_vec[i] - ->getDataBlock(line_address); - - DPRINTF(RubyPort, "reading from %s block %s\n", - ruby_system->m_abs_cntrl_vec[i]->name(), block); - for (unsigned i = 0; i < size_in_bytes; ++i) { - data[i] = block.getByte(i + startByte); - } - return true; - } - } - } - return false; -} - -bool -RubyPort::M5Port::doFunctionalWrite(PacketPtr pkt) -{ - Address addr(pkt->getAddr()); - Address line_addr = line_address(addr); - AccessPermission access_perm = AccessPermission_NotPresent; - int num_controllers = ruby_system->m_abs_cntrl_vec.size(); - - DPRINTF(RubyPort, "Functional Write request for %s\n",addr); - - unsigned int num_ro = 0; - unsigned int num_rw = 0; - unsigned int num_busy = 0; - unsigned int num_backing_store = 0; - unsigned int num_invalid = 0; - - // In this loop we count the number of controllers that have the given - // address in read only, read write and busy states. - for(int i = 0;i < num_controllers;++i) { - access_perm = ruby_system->m_abs_cntrl_vec[i]-> - getAccessPermission(line_addr); - if (access_perm == AccessPermission_Read_Only) - num_ro++; - else if (access_perm == AccessPermission_Read_Write) - num_rw++; - else if (access_perm == AccessPermission_Busy) - num_busy++; - else if (access_perm == AccessPermission_Backing_Store) - // See RubySlicc_Exports.sm for details, but Backing_Store is meant - // to represent blocks in memory *for Broadcast/Snooping protocols*, - // where memory has no idea whether it has an exclusive copy of data - // or not. - num_backing_store++; - else if (access_perm == AccessPermission_Invalid || - access_perm == AccessPermission_NotPresent) - num_invalid++; - } - - // If the number of read write copies is more than 1, then there is bug in - // coherence protocol. Otherwise, if all copies are in stable states, i.e. - // num_busy == 0, we update all the copies. If there is at least one copy - // in busy state, then we check if there is read write copy. If yes, then - // also we let the access go through. Or, if there is no copy in the cache - // hierarchy at all, we still want to do the write to the memory - // (Backing_Store) instead of failing. - - DPRINTF(RubyPort, "num_busy = %d, num_ro = %d, num_rw = %d\n", - num_busy, num_ro, num_rw); - assert(num_rw <= 1); - - uint8_t *data = pkt->getPtr<uint8_t>(true); - unsigned int size_in_bytes = pkt->getSize(); - unsigned startByte = addr.getAddress() - line_addr.getAddress(); - - if ((num_busy == 0 && num_ro > 0) || num_rw == 1 || - (num_invalid == (num_controllers - 1) && num_backing_store == 1)) - { - for(int i = 0; i < num_controllers;++i) { - access_perm = ruby_system->m_abs_cntrl_vec[i]-> - getAccessPermission(line_addr); - if(access_perm == AccessPermission_Read_Only || - access_perm == AccessPermission_Read_Write|| - access_perm == AccessPermission_Maybe_Stale || - access_perm == AccessPermission_Backing_Store) - { - DataBlock& block = ruby_system->m_abs_cntrl_vec[i] - ->getDataBlock(line_addr); - - DPRINTF(RubyPort, "%s\n",block); - for (unsigned i = 0; i < size_in_bytes; ++i) { - block.setByte(i + startByte, data[i]); - } - DPRINTF(RubyPort, "%s\n",block); - } - } - return true; - } - return false; -} - void RubyPort::M5Port::recvFunctional(PacketPtr pkt) { @@ -441,9 +258,9 @@ RubyPort::M5Port::recvFunctional(PacketPtr pkt) // Do the functional access on ruby memory if (pkt->isRead()) { - accessSucceeded = doFunctionalRead(pkt); + accessSucceeded = ruby_system->functionalRead(pkt); } else if (pkt->isWrite()) { - accessSucceeded = doFunctionalWrite(pkt); + accessSucceeded = ruby_system->functionalWrite(pkt); } else { panic("RubyPort: unsupported functional command %s\n", pkt->cmdString()); diff --git a/src/mem/ruby/system/RubyPort.hh b/src/mem/ruby/system/RubyPort.hh index bb8ec7852..7cce6bac3 100644 --- a/src/mem/ruby/system/RubyPort.hh +++ b/src/mem/ruby/system/RubyPort.hh @@ -89,8 +89,6 @@ class RubyPort : public MemObject private: bool isPhysMemAddress(Addr addr); - bool doFunctionalRead(PacketPtr pkt); - bool doFunctionalWrite(PacketPtr pkt); }; friend class M5Port; diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index 8d8db7bbd..25857464d 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -34,6 +34,7 @@ #include "base/intmath.hh" #include "base/output.hh" #include "debug/RubyCacheTrace.hh" +#include "debug/RubySystem.hh" #include "mem/ruby/common/Address.hh" #include "mem/ruby/network/Network.hh" #include "mem/ruby/profiler/Profiler.hh" @@ -336,7 +337,7 @@ RubySystem::unserialize(Checkpoint *cp, const string §ion) Sequencer* t = NULL; for (int cntrl = 0; cntrl < m_abs_cntrl_vec.size(); cntrl++) { sequencer_map.push_back(m_abs_cntrl_vec[cntrl]->getSequencer()); - if(t == NULL) t = sequencer_map[cntrl]; + if (t == NULL) t = sequencer_map[cntrl]; } assert(t != NULL); @@ -396,6 +397,179 @@ RubySystem::clearStats() const m_network_ptr->clearStats(); } +bool +RubySystem::functionalRead(PacketPtr pkt) +{ + Address address(pkt->getAddr()); + Address line_address(address); + line_address.makeLineAddress(); + + AccessPermission access_perm = AccessPermission_NotPresent; + int num_controllers = m_abs_cntrl_vec.size(); + + DPRINTF(RubySystem, "Functional Read request for %s\n",address); + + unsigned int num_ro = 0; + unsigned int num_rw = 0; + unsigned int num_busy = 0; + unsigned int num_backing_store = 0; + unsigned int num_invalid = 0; + + // In this loop we count the number of controllers that have the given + // address in read only, read write and busy states. + for (int i = 0; i < num_controllers; ++i) { + access_perm = m_abs_cntrl_vec[i]-> getAccessPermission(line_address); + if (access_perm == AccessPermission_Read_Only) + num_ro++; + else if (access_perm == AccessPermission_Read_Write) + num_rw++; + else if (access_perm == AccessPermission_Busy) + num_busy++; + else if (access_perm == AccessPermission_Backing_Store) + // See RubySlicc_Exports.sm for details, but Backing_Store is meant + // to represent blocks in memory *for Broadcast/Snooping protocols*, + // where memory has no idea whether it has an exclusive copy of data + // or not. + num_backing_store++; + else if (access_perm == AccessPermission_Invalid || + access_perm == AccessPermission_NotPresent) + num_invalid++; + } + assert(num_rw <= 1); + + uint8_t *data = pkt->getPtr<uint8_t>(true); + unsigned int size_in_bytes = pkt->getSize(); + unsigned startByte = address.getAddress() - line_address.getAddress(); + + // This if case is meant to capture what happens in a Broadcast/Snoop + // protocol where the block does not exist in the cache hierarchy. You + // only want to read from the Backing_Store memory if there is no copy in + // the cache hierarchy, otherwise you want to try to read the RO or RW + // copies existing in the cache hierarchy (covered by the else statement). + // The reason is because the Backing_Store memory could easily be stale, if + // there are copies floating around the cache hierarchy, so you want to read + // it only if it's not in the cache hierarchy at all. + if (num_invalid == (num_controllers - 1) && + num_backing_store == 1) { + DPRINTF(RubySystem, "only copy in Backing_Store memory, read from it\n"); + for (int i = 0; i < num_controllers; ++i) { + access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address); + if (access_perm == AccessPermission_Backing_Store) { + DataBlock& block = m_abs_cntrl_vec[i]-> + getDataBlock(line_address); + + DPRINTF(RubySystem, "reading from %s block %s\n", + m_abs_cntrl_vec[i]->name(), block); + for (unsigned i = 0; i < size_in_bytes; ++i) { + data[i] = block.getByte(i + startByte); + } + return true; + } + } + } else { + // In Broadcast/Snoop protocols, this covers if you know the block + // exists somewhere in the caching hierarchy, then you want to read any + // valid RO or RW block. In directory protocols, same thing, you want + // to read any valid readable copy of the block. + DPRINTF(RubySystem, "num_busy = %d, num_ro = %d, num_rw = %d\n", + num_busy, num_ro, num_rw); + // In this loop, we try to figure which controller has a read only or + // a read write copy of the given address. Any valid copy would suffice + // for a functional read. + for (int i = 0;i < num_controllers;++i) { + access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_address); + if (access_perm == AccessPermission_Read_Only || + access_perm == AccessPermission_Read_Write) { + DataBlock& block = m_abs_cntrl_vec[i]-> + getDataBlock(line_address); + + DPRINTF(RubySystem, "reading from %s block %s\n", + m_abs_cntrl_vec[i]->name(), block); + for (unsigned i = 0; i < size_in_bytes; ++i) { + data[i] = block.getByte(i + startByte); + } + return true; + } + } + } + return false; +} + +bool +RubySystem::functionalWrite(PacketPtr pkt) +{ + Address addr(pkt->getAddr()); + Address line_addr = line_address(addr); + AccessPermission access_perm = AccessPermission_NotPresent; + int num_controllers = m_abs_cntrl_vec.size(); + + DPRINTF(RubySystem, "Functional Write request for %s\n",addr); + + unsigned int num_ro = 0; + unsigned int num_rw = 0; + unsigned int num_busy = 0; + unsigned int num_backing_store = 0; + unsigned int num_invalid = 0; + + // In this loop we count the number of controllers that have the given + // address in read only, read write and busy states. + for (int i = 0;i < num_controllers;++i) { + access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr); + if (access_perm == AccessPermission_Read_Only) + num_ro++; + else if (access_perm == AccessPermission_Read_Write) + num_rw++; + else if (access_perm == AccessPermission_Busy) + num_busy++; + else if (access_perm == AccessPermission_Backing_Store) + // See RubySlicc_Exports.sm for details, but Backing_Store is meant + // to represent blocks in memory *for Broadcast/Snooping protocols*, + // where memory has no idea whether it has an exclusive copy of data + // or not. + num_backing_store++; + else if (access_perm == AccessPermission_Invalid || + access_perm == AccessPermission_NotPresent) + num_invalid++; + } + + // If the number of read write copies is more than 1, then there is bug in + // coherence protocol. Otherwise, if all copies are in stable states, i.e. + // num_busy == 0, we update all the copies. If there is at least one copy + // in busy state, then we check if there is read write copy. If yes, then + // also we let the access go through. Or, if there is no copy in the cache + // hierarchy at all, we still want to do the write to the memory + // (Backing_Store) instead of failing. + + DPRINTF(RubySystem, "num_busy = %d, num_ro = %d, num_rw = %d\n", + num_busy, num_ro, num_rw); + assert(num_rw <= 1); + + uint8_t *data = pkt->getPtr<uint8_t>(true); + unsigned int size_in_bytes = pkt->getSize(); + unsigned startByte = addr.getAddress() - line_addr.getAddress(); + + if ((num_busy == 0 && num_ro > 0) || num_rw == 1 || + (num_invalid == (num_controllers - 1) && num_backing_store == 1)) { + for (int i = 0; i < num_controllers;++i) { + access_perm = m_abs_cntrl_vec[i]->getAccessPermission(line_addr); + if (access_perm == AccessPermission_Read_Only || + access_perm == AccessPermission_Read_Write|| + access_perm == AccessPermission_Maybe_Stale || + access_perm == AccessPermission_Backing_Store) { + + DataBlock& block = m_abs_cntrl_vec[i]->getDataBlock(line_addr); + DPRINTF(RubySystem, "%s\n",block); + for (unsigned i = 0; i < size_in_bytes; ++i) { + block.setByte(i + startByte, data[i]); + } + DPRINTF(RubySystem, "%s\n",block); + } + } + return true; + } + return false; +} + #ifdef CHECK_COHERENCE // This code will check for cases if the given cache block is exclusive in // one node and shared in another-- a coherence violation diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index f7e0efc2a..c0614cb1a 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -36,6 +36,7 @@ #define __MEM_RUBY_SYSTEM_SYSTEM_HH__ #include "base/callback.hh" +#include "mem/packet.hh" #include "mem/ruby/common/Global.hh" #include "mem/ruby/recorder/CacheRecorder.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" @@ -112,6 +113,8 @@ class RubySystem : public ClockedObject void unserialize(Checkpoint *cp, const std::string §ion); void process(); void startup(); + bool functionalRead(Packet *ptr); + bool functionalWrite(Packet *ptr); void registerNetwork(Network*); void registerProfiler(Profiler*); |