AbstractController.cc revision 11523:81332eb10367
112837Sgabeblack@google.com/* 212837Sgabeblack@google.com * Copyright (c) 2011-2014 Mark D. Hill and David A. Wood 312837Sgabeblack@google.com * All rights reserved. 412837Sgabeblack@google.com * 512837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without 612837Sgabeblack@google.com * modification, are permitted provided that the following conditions are 712837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright 812837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer; 912837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright 1012837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the 1112837Sgabeblack@google.com * documentation and/or other materials provided with the distribution; 1212837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its 1312837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from 1412837Sgabeblack@google.com * this software without specific prior written permission. 1512837Sgabeblack@google.com * 1612837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112837Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212837Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312837Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412837Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612837Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712837Sgabeblack@google.com */ 2812837Sgabeblack@google.com 2912837Sgabeblack@google.com#include "mem/ruby/slicc_interface/AbstractController.hh" 3012837Sgabeblack@google.com 3112837Sgabeblack@google.com#include "debug/RubyQueue.hh" 3212837Sgabeblack@google.com#include "mem/protocol/MemoryMsg.hh" 3312837Sgabeblack@google.com#include "mem/ruby/system/RubySystem.hh" 3412837Sgabeblack@google.com#include "mem/ruby/system/Sequencer.hh" 3512837Sgabeblack@google.com#include "mem/ruby/system/GPUCoalescer.hh" 3612837Sgabeblack@google.com#include "sim/system.hh" 3712837Sgabeblack@google.com 3812837Sgabeblack@google.comAbstractController::AbstractController(const Params *p) 3912837Sgabeblack@google.com : MemObject(p), Consumer(this), m_version(p->version), 4012837Sgabeblack@google.com m_clusterID(p->cluster_id), 4112837Sgabeblack@google.com m_masterId(p->system->getMasterId(name())), m_is_blocking(false), 4212837Sgabeblack@google.com m_number_of_TBEs(p->number_of_TBEs), 4312837Sgabeblack@google.com m_transitions_per_cycle(p->transitions_per_cycle), 4412837Sgabeblack@google.com m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency), 4512837Sgabeblack@google.com memoryPort(csprintf("%s.memory", name()), this, "") 4612837Sgabeblack@google.com{ 4712837Sgabeblack@google.com if (m_version == 0) { 4812837Sgabeblack@google.com // Combine the statistics from all controllers 4912837Sgabeblack@google.com // of this particular type. 5012837Sgabeblack@google.com Stats::registerDumpCallback(new StatsCallback(this)); 5112837Sgabeblack@google.com } 5212837Sgabeblack@google.com} 5312837Sgabeblack@google.com 5412837Sgabeblack@google.comvoid 5512837Sgabeblack@google.comAbstractController::init() 5612837Sgabeblack@google.com{ 5712837Sgabeblack@google.com params()->ruby_system->registerAbstractController(this); 5812837Sgabeblack@google.com m_delayHistogram.init(10); 5912837Sgabeblack@google.com uint32_t size = Network::getNumberOfVirtualNetworks(); 6012837Sgabeblack@google.com for (uint32_t i = 0; i < size; i++) { 6112837Sgabeblack@google.com m_delayVCHistogram.push_back(new Stats::Histogram()); 6212837Sgabeblack@google.com m_delayVCHistogram[i]->init(10); 6312837Sgabeblack@google.com } 6412837Sgabeblack@google.com} 6512837Sgabeblack@google.com 6612837Sgabeblack@google.comvoid 6712837Sgabeblack@google.comAbstractController::resetStats() 6812837Sgabeblack@google.com{ 6912837Sgabeblack@google.com m_delayHistogram.reset(); 7012837Sgabeblack@google.com uint32_t size = Network::getNumberOfVirtualNetworks(); 7112837Sgabeblack@google.com for (uint32_t i = 0; i < size; i++) { 7212837Sgabeblack@google.com m_delayVCHistogram[i]->reset(); 7312837Sgabeblack@google.com } 7412837Sgabeblack@google.com} 7512837Sgabeblack@google.com 7612837Sgabeblack@google.comvoid 7712837Sgabeblack@google.comAbstractController::regStats() 7812837Sgabeblack@google.com{ 7912837Sgabeblack@google.com MemObject::regStats(); 8012837Sgabeblack@google.com 8112837Sgabeblack@google.com m_fully_busy_cycles 8212837Sgabeblack@google.com .name(name() + ".fully_busy_cycles") 8312837Sgabeblack@google.com .desc("cycles for which number of transistions == max transitions") 8412837Sgabeblack@google.com .flags(Stats::nozero); 8512837Sgabeblack@google.com} 8612837Sgabeblack@google.com 8712837Sgabeblack@google.comvoid 8812837Sgabeblack@google.comAbstractController::profileMsgDelay(uint32_t virtualNetwork, Cycles delay) 8912837Sgabeblack@google.com{ 9012837Sgabeblack@google.com assert(virtualNetwork < m_delayVCHistogram.size()); 9112837Sgabeblack@google.com m_delayHistogram.sample(delay); 9212837Sgabeblack@google.com m_delayVCHistogram[virtualNetwork]->sample(delay); 9312837Sgabeblack@google.com} 9412837Sgabeblack@google.com 9512837Sgabeblack@google.comvoid 9612837Sgabeblack@google.comAbstractController::stallBuffer(MessageBuffer* buf, Addr addr) 9712837Sgabeblack@google.com{ 9812837Sgabeblack@google.com if (m_waiting_buffers.count(addr) == 0) { 9912837Sgabeblack@google.com MsgVecType* msgVec = new MsgVecType; 10012837Sgabeblack@google.com msgVec->resize(m_in_ports, NULL); 10112837Sgabeblack@google.com m_waiting_buffers[addr] = msgVec; 10212837Sgabeblack@google.com } 10312837Sgabeblack@google.com DPRINTF(RubyQueue, "stalling %s port %d addr %#x\n", buf, m_cur_in_port, 10412837Sgabeblack@google.com addr); 10512837Sgabeblack@google.com assert(m_in_ports > m_cur_in_port); 10612837Sgabeblack@google.com (*(m_waiting_buffers[addr]))[m_cur_in_port] = buf; 10712837Sgabeblack@google.com} 10812837Sgabeblack@google.com 10912837Sgabeblack@google.comvoid 11012837Sgabeblack@google.comAbstractController::wakeUpBuffers(Addr addr) 11112837Sgabeblack@google.com{ 11212837Sgabeblack@google.com if (m_waiting_buffers.count(addr) > 0) { 11312837Sgabeblack@google.com // 11412837Sgabeblack@google.com // Wake up all possible lower rank (i.e. lower priority) buffers that could 11512837Sgabeblack@google.com // be waiting on this message. 11612837Sgabeblack@google.com // 11712837Sgabeblack@google.com for (int in_port_rank = m_cur_in_port - 1; 11812837Sgabeblack@google.com in_port_rank >= 0; 11912837Sgabeblack@google.com in_port_rank--) { 12012837Sgabeblack@google.com if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 12112837Sgabeblack@google.com (*(m_waiting_buffers[addr]))[in_port_rank]-> 12212837Sgabeblack@google.com reanalyzeMessages(addr, clockEdge()); 12312837Sgabeblack@google.com } 12412837Sgabeblack@google.com } 12512837Sgabeblack@google.com delete m_waiting_buffers[addr]; 12612837Sgabeblack@google.com m_waiting_buffers.erase(addr); 12712837Sgabeblack@google.com } 12812837Sgabeblack@google.com} 12912837Sgabeblack@google.com 13012837Sgabeblack@google.comvoid 13112837Sgabeblack@google.comAbstractController::wakeUpAllBuffers(Addr addr) 13212837Sgabeblack@google.com{ 13312837Sgabeblack@google.com if (m_waiting_buffers.count(addr) > 0) { 13412837Sgabeblack@google.com // 13512837Sgabeblack@google.com // Wake up all possible lower rank (i.e. lower priority) buffers that could 13612837Sgabeblack@google.com // be waiting on this message. 13712837Sgabeblack@google.com // 13812837Sgabeblack@google.com for (int in_port_rank = m_in_ports - 1; 13912837Sgabeblack@google.com in_port_rank >= 0; 14012837Sgabeblack@google.com in_port_rank--) { 14112837Sgabeblack@google.com if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 14212837Sgabeblack@google.com (*(m_waiting_buffers[addr]))[in_port_rank]-> 14312837Sgabeblack@google.com reanalyzeMessages(addr, clockEdge()); 14412837Sgabeblack@google.com } 14512837Sgabeblack@google.com } 14612837Sgabeblack@google.com delete m_waiting_buffers[addr]; 14712837Sgabeblack@google.com m_waiting_buffers.erase(addr); 14812837Sgabeblack@google.com } 14912837Sgabeblack@google.com} 15012837Sgabeblack@google.com 15112837Sgabeblack@google.comvoid 15212837Sgabeblack@google.comAbstractController::wakeUpAllBuffers() 15312837Sgabeblack@google.com{ 15412837Sgabeblack@google.com // 15512837Sgabeblack@google.com // Wake up all possible buffers that could be waiting on any message. 15612837Sgabeblack@google.com // 15712837Sgabeblack@google.com 15812837Sgabeblack@google.com std::vector<MsgVecType*> wokeUpMsgVecs; 15912837Sgabeblack@google.com MsgBufType wokeUpMsgBufs; 16012837Sgabeblack@google.com 16112837Sgabeblack@google.com if (m_waiting_buffers.size() > 0) { 16212837Sgabeblack@google.com for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin(); 16312837Sgabeblack@google.com buf_iter != m_waiting_buffers.end(); 16412837Sgabeblack@google.com ++buf_iter) { 16512837Sgabeblack@google.com for (MsgVecType::iterator vec_iter = buf_iter->second->begin(); 16612837Sgabeblack@google.com vec_iter != buf_iter->second->end(); 16712837Sgabeblack@google.com ++vec_iter) { 16812837Sgabeblack@google.com // 16912837Sgabeblack@google.com // Make sure the MessageBuffer has not already be reanalyzed 17012837Sgabeblack@google.com // 17112837Sgabeblack@google.com if (*vec_iter != NULL && 17212837Sgabeblack@google.com (wokeUpMsgBufs.count(*vec_iter) == 0)) { 17312837Sgabeblack@google.com (*vec_iter)->reanalyzeAllMessages(clockEdge()); 17412837Sgabeblack@google.com wokeUpMsgBufs.insert(*vec_iter); 17512837Sgabeblack@google.com } 17612837Sgabeblack@google.com } 17712837Sgabeblack@google.com wokeUpMsgVecs.push_back(buf_iter->second); 17812837Sgabeblack@google.com } 17912837Sgabeblack@google.com 18012837Sgabeblack@google.com for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin(); 18112837Sgabeblack@google.com wb_iter != wokeUpMsgVecs.end(); 18212837Sgabeblack@google.com ++wb_iter) { 18312837Sgabeblack@google.com delete (*wb_iter); 18412837Sgabeblack@google.com } 18512837Sgabeblack@google.com 18612837Sgabeblack@google.com m_waiting_buffers.clear(); 18712837Sgabeblack@google.com } 18812837Sgabeblack@google.com} 18912837Sgabeblack@google.com 19012837Sgabeblack@google.comvoid 19112837Sgabeblack@google.comAbstractController::blockOnQueue(Addr addr, MessageBuffer* port) 19212837Sgabeblack@google.com{ 19312837Sgabeblack@google.com m_is_blocking = true; 19412837Sgabeblack@google.com m_block_map[addr] = port; 19512837Sgabeblack@google.com} 19612837Sgabeblack@google.com 19712837Sgabeblack@google.combool 19812837Sgabeblack@google.comAbstractController::isBlocked(Addr addr) const 19912837Sgabeblack@google.com{ 20012837Sgabeblack@google.com return m_is_blocking && (m_block_map.find(addr) != m_block_map.end()); 20112837Sgabeblack@google.com} 20212837Sgabeblack@google.com 20312837Sgabeblack@google.comvoid 20412837Sgabeblack@google.comAbstractController::unblock(Addr addr) 20512837Sgabeblack@google.com{ 20612837Sgabeblack@google.com m_block_map.erase(addr); 20712837Sgabeblack@google.com if (m_block_map.size() == 0) { 20812837Sgabeblack@google.com m_is_blocking = false; 20912837Sgabeblack@google.com } 21012837Sgabeblack@google.com} 21112837Sgabeblack@google.com 21212837Sgabeblack@google.combool 21312837Sgabeblack@google.comAbstractController::isBlocked(Addr addr) 21412837Sgabeblack@google.com{ 21512837Sgabeblack@google.com return (m_block_map.count(addr) > 0); 21612837Sgabeblack@google.com} 21712837Sgabeblack@google.com 21812837Sgabeblack@google.comBaseMasterPort & 21912837Sgabeblack@google.comAbstractController::getMasterPort(const std::string &if_name, 22012837Sgabeblack@google.com PortID idx) 22112837Sgabeblack@google.com{ 22212837Sgabeblack@google.com return memoryPort; 22312837Sgabeblack@google.com} 22412837Sgabeblack@google.com 22512837Sgabeblack@google.comvoid 22612837Sgabeblack@google.comAbstractController::queueMemoryRead(const MachineID &id, Addr addr, 22712837Sgabeblack@google.com Cycles latency) 22812837Sgabeblack@google.com{ 22912837Sgabeblack@google.com RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 23012837Sgabeblack@google.com m_masterId); 23112837Sgabeblack@google.com 23212837Sgabeblack@google.com PacketPtr pkt = Packet::createRead(req); 23312837Sgabeblack@google.com uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()]; 23412837Sgabeblack@google.com pkt->dataDynamic(newData); 23512837Sgabeblack@google.com 23612837Sgabeblack@google.com SenderState *s = new SenderState(id); 23712837Sgabeblack@google.com pkt->pushSenderState(s); 23812837Sgabeblack@google.com 23912837Sgabeblack@google.com // Use functional rather than timing accesses during warmup 24012837Sgabeblack@google.com if (RubySystem::getWarmupEnabled()) { 24112837Sgabeblack@google.com memoryPort.sendFunctional(pkt); 24212837Sgabeblack@google.com recvTimingResp(pkt); 24312837Sgabeblack@google.com return; 24412837Sgabeblack@google.com } 24512837Sgabeblack@google.com 24612837Sgabeblack@google.com memoryPort.schedTimingReq(pkt, clockEdge(latency)); 24712837Sgabeblack@google.com} 24812837Sgabeblack@google.com 24912837Sgabeblack@google.comvoid 25012837Sgabeblack@google.comAbstractController::queueMemoryWrite(const MachineID &id, Addr addr, 25112837Sgabeblack@google.com Cycles latency, const DataBlock &block) 25212837Sgabeblack@google.com{ 25312837Sgabeblack@google.com RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 25412837Sgabeblack@google.com m_masterId); 25512837Sgabeblack@google.com 25612837Sgabeblack@google.com PacketPtr pkt = Packet::createWrite(req); 25712837Sgabeblack@google.com uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()]; 25812837Sgabeblack@google.com pkt->dataDynamic(newData); 25912837Sgabeblack@google.com memcpy(newData, block.getData(0, RubySystem::getBlockSizeBytes()), 26012837Sgabeblack@google.com RubySystem::getBlockSizeBytes()); 26112837Sgabeblack@google.com 26212837Sgabeblack@google.com SenderState *s = new SenderState(id); 26312837Sgabeblack@google.com pkt->pushSenderState(s); 26412837Sgabeblack@google.com 26512837Sgabeblack@google.com // Use functional rather than timing accesses during warmup 26612837Sgabeblack@google.com if (RubySystem::getWarmupEnabled()) { 26712837Sgabeblack@google.com memoryPort.sendFunctional(pkt); 26812837Sgabeblack@google.com recvTimingResp(pkt); 26912837Sgabeblack@google.com return; 27012837Sgabeblack@google.com } 27112837Sgabeblack@google.com 27212837Sgabeblack@google.com // Create a block and copy data from the block. 27312837Sgabeblack@google.com memoryPort.schedTimingReq(pkt, clockEdge(latency)); 27412837Sgabeblack@google.com} 27512837Sgabeblack@google.com 27612837Sgabeblack@google.comvoid 27712837Sgabeblack@google.comAbstractController::queueMemoryWritePartial(const MachineID &id, Addr addr, 27812837Sgabeblack@google.com Cycles latency, 27912837Sgabeblack@google.com const DataBlock &block, int size) 28012900Sgabeblack@google.com{ 28112900Sgabeblack@google.com RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 28212900Sgabeblack@google.com m_masterId); 28312900Sgabeblack@google.com 28412900Sgabeblack@google.com PacketPtr pkt = Packet::createWrite(req); 28512900Sgabeblack@google.com uint8_t *newData = new uint8_t[size]; 28612900Sgabeblack@google.com pkt->dataDynamic(newData); 28712915Sgabeblack@google.com memcpy(newData, block.getData(getOffset(addr), size), size); 28812915Sgabeblack@google.com 28912915Sgabeblack@google.com SenderState *s = new SenderState(id); 29012915Sgabeblack@google.com pkt->pushSenderState(s); 29112915Sgabeblack@google.com 29212915Sgabeblack@google.com // Create a block and copy data from the block. 29312915Sgabeblack@google.com memoryPort.schedTimingReq(pkt, clockEdge(latency)); 29412915Sgabeblack@google.com} 29512915Sgabeblack@google.com 29612915Sgabeblack@google.comvoid 29712915Sgabeblack@google.comAbstractController::functionalMemoryRead(PacketPtr pkt) 29812915Sgabeblack@google.com{ 29912837Sgabeblack@google.com memoryPort.sendFunctional(pkt); 30012837Sgabeblack@google.com} 30112837Sgabeblack@google.com 30212837Sgabeblack@google.comint 30312837Sgabeblack@google.comAbstractController::functionalMemoryWrite(PacketPtr pkt) 30412837Sgabeblack@google.com{ 30512837Sgabeblack@google.com int num_functional_writes = 0; 30612837Sgabeblack@google.com 30712837Sgabeblack@google.com // Check the buffer from the controller to the memory. 30812837Sgabeblack@google.com if (memoryPort.checkFunctional(pkt)) { 30912837Sgabeblack@google.com num_functional_writes++; 31012837Sgabeblack@google.com } 31112837Sgabeblack@google.com 31212837Sgabeblack@google.com // Update memory itself. 31312837Sgabeblack@google.com memoryPort.sendFunctional(pkt); 31412837Sgabeblack@google.com return num_functional_writes + 1; 31512837Sgabeblack@google.com} 31612837Sgabeblack@google.com 31712837Sgabeblack@google.comvoid 31812837Sgabeblack@google.comAbstractController::recvTimingResp(PacketPtr pkt) 31912837Sgabeblack@google.com{ 32012837Sgabeblack@google.com assert(getMemoryQueue()); 32112837Sgabeblack@google.com assert(pkt->isResponse()); 32212837Sgabeblack@google.com 32312837Sgabeblack@google.com std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge()); 32412837Sgabeblack@google.com (*msg).m_addr = pkt->getAddr(); 32512837Sgabeblack@google.com (*msg).m_Sender = m_machineID; 32612837Sgabeblack@google.com 32712837Sgabeblack@google.com SenderState *s = dynamic_cast<SenderState *>(pkt->senderState); 32812837Sgabeblack@google.com (*msg).m_OriginalRequestorMachId = s->id; 32912837Sgabeblack@google.com delete s; 33012837Sgabeblack@google.com 33112837Sgabeblack@google.com if (pkt->isRead()) { 33212837Sgabeblack@google.com (*msg).m_Type = MemoryRequestType_MEMORY_READ; 33312837Sgabeblack@google.com (*msg).m_MessageSize = MessageSizeType_Response_Data; 33412837Sgabeblack@google.com 33512837Sgabeblack@google.com // Copy data from the packet 33612837Sgabeblack@google.com (*msg).m_DataBlk.setData(pkt->getPtr<uint8_t>(), 0, 33712837Sgabeblack@google.com RubySystem::getBlockSizeBytes()); 33812837Sgabeblack@google.com } else if (pkt->isWrite()) { 33912837Sgabeblack@google.com (*msg).m_Type = MemoryRequestType_MEMORY_WB; 34012837Sgabeblack@google.com (*msg).m_MessageSize = MessageSizeType_Writeback_Control; 34112837Sgabeblack@google.com } else { 342 panic("Incorrect packet type received from memory controller!"); 343 } 344 345 getMemoryQueue()->enqueue(msg, clockEdge(), cyclesToTicks(Cycles(1))); 346 delete pkt->req; 347 delete pkt; 348} 349 350bool 351AbstractController::MemoryPort::recvTimingResp(PacketPtr pkt) 352{ 353 controller->recvTimingResp(pkt); 354 return true; 355} 356 357AbstractController::MemoryPort::MemoryPort(const std::string &_name, 358 AbstractController *_controller, 359 const std::string &_label) 360 : QueuedMasterPort(_name, _controller, reqQueue, snoopRespQueue), 361 reqQueue(*_controller, *this, _label), 362 snoopRespQueue(*_controller, *this, _label), 363 controller(_controller) 364{ 365} 366