AbstractController.cc revision 11523:81332eb10367
112027Sjungma@eit.uni-kl.de/* 212027Sjungma@eit.uni-kl.de * Copyright (c) 2011-2014 Mark D. Hill and David A. Wood 312027Sjungma@eit.uni-kl.de * All rights reserved. 412027Sjungma@eit.uni-kl.de * 512027Sjungma@eit.uni-kl.de * Redistribution and use in source and binary forms, with or without 612027Sjungma@eit.uni-kl.de * modification, are permitted provided that the following conditions are 712027Sjungma@eit.uni-kl.de * met: redistributions of source code must retain the above copyright 812027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer; 912027Sjungma@eit.uni-kl.de * redistributions in binary form must reproduce the above copyright 1012027Sjungma@eit.uni-kl.de * notice, this list of conditions and the following disclaimer in the 1112027Sjungma@eit.uni-kl.de * documentation and/or other materials provided with the distribution; 1212027Sjungma@eit.uni-kl.de * neither the name of the copyright holders nor the names of its 1312027Sjungma@eit.uni-kl.de * contributors may be used to endorse or promote products derived from 1412027Sjungma@eit.uni-kl.de * this software without specific prior written permission. 1512027Sjungma@eit.uni-kl.de * 1612027Sjungma@eit.uni-kl.de * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712027Sjungma@eit.uni-kl.de * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812027Sjungma@eit.uni-kl.de * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912027Sjungma@eit.uni-kl.de * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012027Sjungma@eit.uni-kl.de * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112027Sjungma@eit.uni-kl.de * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212027Sjungma@eit.uni-kl.de * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312027Sjungma@eit.uni-kl.de * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412027Sjungma@eit.uni-kl.de * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512027Sjungma@eit.uni-kl.de * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612027Sjungma@eit.uni-kl.de * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712027Sjungma@eit.uni-kl.de */ 2812027Sjungma@eit.uni-kl.de 2912027Sjungma@eit.uni-kl.de#include "mem/ruby/slicc_interface/AbstractController.hh" 3012027Sjungma@eit.uni-kl.de 3112027Sjungma@eit.uni-kl.de#include "debug/RubyQueue.hh" 3212027Sjungma@eit.uni-kl.de#include "mem/protocol/MemoryMsg.hh" 3312027Sjungma@eit.uni-kl.de#include "mem/ruby/system/RubySystem.hh" 3412027Sjungma@eit.uni-kl.de#include "mem/ruby/system/Sequencer.hh" 3512027Sjungma@eit.uni-kl.de#include "mem/ruby/system/GPUCoalescer.hh" 3612027Sjungma@eit.uni-kl.de#include "sim/system.hh" 3712027Sjungma@eit.uni-kl.de 3812027Sjungma@eit.uni-kl.deAbstractController::AbstractController(const Params *p) 3912027Sjungma@eit.uni-kl.de : MemObject(p), Consumer(this), m_version(p->version), 4012027Sjungma@eit.uni-kl.de m_clusterID(p->cluster_id), 4112027Sjungma@eit.uni-kl.de m_masterId(p->system->getMasterId(name())), m_is_blocking(false), 4212027Sjungma@eit.uni-kl.de m_number_of_TBEs(p->number_of_TBEs), 4312027Sjungma@eit.uni-kl.de m_transitions_per_cycle(p->transitions_per_cycle), 4412027Sjungma@eit.uni-kl.de m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency), 4512027Sjungma@eit.uni-kl.de memoryPort(csprintf("%s.memory", name()), this, "") 4612027Sjungma@eit.uni-kl.de{ 4712027Sjungma@eit.uni-kl.de if (m_version == 0) { 4812027Sjungma@eit.uni-kl.de // Combine the statistics from all controllers 4912027Sjungma@eit.uni-kl.de // of this particular type. 5012027Sjungma@eit.uni-kl.de Stats::registerDumpCallback(new StatsCallback(this)); 5112027Sjungma@eit.uni-kl.de } 5212027Sjungma@eit.uni-kl.de} 5312027Sjungma@eit.uni-kl.de 5412027Sjungma@eit.uni-kl.devoid 5512027Sjungma@eit.uni-kl.deAbstractController::init() 5612027Sjungma@eit.uni-kl.de{ 5712027Sjungma@eit.uni-kl.de params()->ruby_system->registerAbstractController(this); 5812027Sjungma@eit.uni-kl.de m_delayHistogram.init(10); 5912027Sjungma@eit.uni-kl.de uint32_t size = Network::getNumberOfVirtualNetworks(); 6012027Sjungma@eit.uni-kl.de for (uint32_t i = 0; i < size; i++) { 6112027Sjungma@eit.uni-kl.de m_delayVCHistogram.push_back(new Stats::Histogram()); 6212027Sjungma@eit.uni-kl.de m_delayVCHistogram[i]->init(10); 6312027Sjungma@eit.uni-kl.de } 6412027Sjungma@eit.uni-kl.de} 6512027Sjungma@eit.uni-kl.de 6612027Sjungma@eit.uni-kl.devoid 6712027Sjungma@eit.uni-kl.deAbstractController::resetStats() 6812027Sjungma@eit.uni-kl.de{ 6912027Sjungma@eit.uni-kl.de m_delayHistogram.reset(); 7012027Sjungma@eit.uni-kl.de uint32_t size = Network::getNumberOfVirtualNetworks(); 7112027Sjungma@eit.uni-kl.de for (uint32_t i = 0; i < size; i++) { 7212027Sjungma@eit.uni-kl.de m_delayVCHistogram[i]->reset(); 7312027Sjungma@eit.uni-kl.de } 7412027Sjungma@eit.uni-kl.de} 7512027Sjungma@eit.uni-kl.de 7612027Sjungma@eit.uni-kl.devoid 7712027Sjungma@eit.uni-kl.deAbstractController::regStats() 7812027Sjungma@eit.uni-kl.de{ 7912027Sjungma@eit.uni-kl.de MemObject::regStats(); 8012027Sjungma@eit.uni-kl.de 8112027Sjungma@eit.uni-kl.de m_fully_busy_cycles 8212027Sjungma@eit.uni-kl.de .name(name() + ".fully_busy_cycles") 8312027Sjungma@eit.uni-kl.de .desc("cycles for which number of transistions == max transitions") 8412027Sjungma@eit.uni-kl.de .flags(Stats::nozero); 8512027Sjungma@eit.uni-kl.de} 8612027Sjungma@eit.uni-kl.de 8712027Sjungma@eit.uni-kl.devoid 8812027Sjungma@eit.uni-kl.deAbstractController::profileMsgDelay(uint32_t virtualNetwork, Cycles delay) 8912027Sjungma@eit.uni-kl.de{ 9012027Sjungma@eit.uni-kl.de assert(virtualNetwork < m_delayVCHistogram.size()); 9112027Sjungma@eit.uni-kl.de m_delayHistogram.sample(delay); 9212027Sjungma@eit.uni-kl.de m_delayVCHistogram[virtualNetwork]->sample(delay); 9312027Sjungma@eit.uni-kl.de} 9412027Sjungma@eit.uni-kl.de 9512027Sjungma@eit.uni-kl.devoid 9612027Sjungma@eit.uni-kl.deAbstractController::stallBuffer(MessageBuffer* buf, Addr addr) 9712027Sjungma@eit.uni-kl.de{ 9812027Sjungma@eit.uni-kl.de if (m_waiting_buffers.count(addr) == 0) { 9912027Sjungma@eit.uni-kl.de MsgVecType* msgVec = new MsgVecType; 10012027Sjungma@eit.uni-kl.de msgVec->resize(m_in_ports, NULL); 10112027Sjungma@eit.uni-kl.de m_waiting_buffers[addr] = msgVec; 10212027Sjungma@eit.uni-kl.de } 10312027Sjungma@eit.uni-kl.de DPRINTF(RubyQueue, "stalling %s port %d addr %#x\n", buf, m_cur_in_port, 10412027Sjungma@eit.uni-kl.de addr); 10512027Sjungma@eit.uni-kl.de assert(m_in_ports > m_cur_in_port); 10612027Sjungma@eit.uni-kl.de (*(m_waiting_buffers[addr]))[m_cur_in_port] = buf; 10712027Sjungma@eit.uni-kl.de} 10812027Sjungma@eit.uni-kl.de 10912027Sjungma@eit.uni-kl.devoid 11012027Sjungma@eit.uni-kl.deAbstractController::wakeUpBuffers(Addr addr) 11112027Sjungma@eit.uni-kl.de{ 11212027Sjungma@eit.uni-kl.de if (m_waiting_buffers.count(addr) > 0) { 11312027Sjungma@eit.uni-kl.de // 11412027Sjungma@eit.uni-kl.de // Wake up all possible lower rank (i.e. lower priority) buffers that could 11512027Sjungma@eit.uni-kl.de // be waiting on this message. 11612027Sjungma@eit.uni-kl.de // 11712027Sjungma@eit.uni-kl.de for (int in_port_rank = m_cur_in_port - 1; 11812027Sjungma@eit.uni-kl.de in_port_rank >= 0; 11912027Sjungma@eit.uni-kl.de in_port_rank--) { 12012027Sjungma@eit.uni-kl.de if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 12112027Sjungma@eit.uni-kl.de (*(m_waiting_buffers[addr]))[in_port_rank]-> 12212027Sjungma@eit.uni-kl.de reanalyzeMessages(addr, clockEdge()); 12312027Sjungma@eit.uni-kl.de } 12412027Sjungma@eit.uni-kl.de } 12512027Sjungma@eit.uni-kl.de delete m_waiting_buffers[addr]; 12612027Sjungma@eit.uni-kl.de m_waiting_buffers.erase(addr); 12712027Sjungma@eit.uni-kl.de } 12812027Sjungma@eit.uni-kl.de} 12912027Sjungma@eit.uni-kl.de 13012027Sjungma@eit.uni-kl.devoid 13112027Sjungma@eit.uni-kl.deAbstractController::wakeUpAllBuffers(Addr addr) 13212027Sjungma@eit.uni-kl.de{ 13312027Sjungma@eit.uni-kl.de if (m_waiting_buffers.count(addr) > 0) { 13412027Sjungma@eit.uni-kl.de // 13512027Sjungma@eit.uni-kl.de // Wake up all possible lower rank (i.e. lower priority) buffers that could 13612027Sjungma@eit.uni-kl.de // be waiting on this message. 13712027Sjungma@eit.uni-kl.de // 13812027Sjungma@eit.uni-kl.de for (int in_port_rank = m_in_ports - 1; 13912027Sjungma@eit.uni-kl.de in_port_rank >= 0; 14012027Sjungma@eit.uni-kl.de in_port_rank--) { 14112027Sjungma@eit.uni-kl.de if ((*(m_waiting_buffers[addr]))[in_port_rank] != NULL) { 14212027Sjungma@eit.uni-kl.de (*(m_waiting_buffers[addr]))[in_port_rank]-> 14312027Sjungma@eit.uni-kl.de reanalyzeMessages(addr, clockEdge()); 14412027Sjungma@eit.uni-kl.de } 14512027Sjungma@eit.uni-kl.de } 14612027Sjungma@eit.uni-kl.de delete m_waiting_buffers[addr]; 14712027Sjungma@eit.uni-kl.de m_waiting_buffers.erase(addr); 14812027Sjungma@eit.uni-kl.de } 14912027Sjungma@eit.uni-kl.de} 15012027Sjungma@eit.uni-kl.de 15112027Sjungma@eit.uni-kl.devoid 15212027Sjungma@eit.uni-kl.deAbstractController::wakeUpAllBuffers() 15312027Sjungma@eit.uni-kl.de{ 15412027Sjungma@eit.uni-kl.de // 15512027Sjungma@eit.uni-kl.de // Wake up all possible buffers that could be waiting on any message. 15612027Sjungma@eit.uni-kl.de // 15712027Sjungma@eit.uni-kl.de 15812027Sjungma@eit.uni-kl.de std::vector<MsgVecType*> wokeUpMsgVecs; 15912027Sjungma@eit.uni-kl.de MsgBufType wokeUpMsgBufs; 16012027Sjungma@eit.uni-kl.de 16112027Sjungma@eit.uni-kl.de if (m_waiting_buffers.size() > 0) { 16212027Sjungma@eit.uni-kl.de for (WaitingBufType::iterator buf_iter = m_waiting_buffers.begin(); 16312027Sjungma@eit.uni-kl.de buf_iter != m_waiting_buffers.end(); 16412027Sjungma@eit.uni-kl.de ++buf_iter) { 16512027Sjungma@eit.uni-kl.de for (MsgVecType::iterator vec_iter = buf_iter->second->begin(); 16612027Sjungma@eit.uni-kl.de vec_iter != buf_iter->second->end(); 16712027Sjungma@eit.uni-kl.de ++vec_iter) { 16812027Sjungma@eit.uni-kl.de // 16912027Sjungma@eit.uni-kl.de // Make sure the MessageBuffer has not already be reanalyzed 17012027Sjungma@eit.uni-kl.de // 17112027Sjungma@eit.uni-kl.de if (*vec_iter != NULL && 17212027Sjungma@eit.uni-kl.de (wokeUpMsgBufs.count(*vec_iter) == 0)) { 17312027Sjungma@eit.uni-kl.de (*vec_iter)->reanalyzeAllMessages(clockEdge()); 17412027Sjungma@eit.uni-kl.de wokeUpMsgBufs.insert(*vec_iter); 17512027Sjungma@eit.uni-kl.de } 17612027Sjungma@eit.uni-kl.de } 17712027Sjungma@eit.uni-kl.de wokeUpMsgVecs.push_back(buf_iter->second); 17812027Sjungma@eit.uni-kl.de } 17912027Sjungma@eit.uni-kl.de 18012027Sjungma@eit.uni-kl.de for (std::vector<MsgVecType*>::iterator wb_iter = wokeUpMsgVecs.begin(); 18112027Sjungma@eit.uni-kl.de wb_iter != wokeUpMsgVecs.end(); 18212027Sjungma@eit.uni-kl.de ++wb_iter) { 18312027Sjungma@eit.uni-kl.de delete (*wb_iter); 18412027Sjungma@eit.uni-kl.de } 18512027Sjungma@eit.uni-kl.de 18612027Sjungma@eit.uni-kl.de m_waiting_buffers.clear(); 18712027Sjungma@eit.uni-kl.de } 18812027Sjungma@eit.uni-kl.de} 18912027Sjungma@eit.uni-kl.de 19012027Sjungma@eit.uni-kl.devoid 19112027Sjungma@eit.uni-kl.deAbstractController::blockOnQueue(Addr addr, MessageBuffer* port) 19212027Sjungma@eit.uni-kl.de{ 19312027Sjungma@eit.uni-kl.de m_is_blocking = true; 19412027Sjungma@eit.uni-kl.de m_block_map[addr] = port; 19512027Sjungma@eit.uni-kl.de} 19612027Sjungma@eit.uni-kl.de 19712027Sjungma@eit.uni-kl.debool 19812027Sjungma@eit.uni-kl.deAbstractController::isBlocked(Addr addr) const 19912027Sjungma@eit.uni-kl.de{ 20012027Sjungma@eit.uni-kl.de return m_is_blocking && (m_block_map.find(addr) != m_block_map.end()); 20112027Sjungma@eit.uni-kl.de} 20212027Sjungma@eit.uni-kl.de 20312027Sjungma@eit.uni-kl.devoid 20412027Sjungma@eit.uni-kl.deAbstractController::unblock(Addr addr) 20512027Sjungma@eit.uni-kl.de{ 20612027Sjungma@eit.uni-kl.de m_block_map.erase(addr); 20712027Sjungma@eit.uni-kl.de if (m_block_map.size() == 0) { 20812027Sjungma@eit.uni-kl.de m_is_blocking = false; 20912027Sjungma@eit.uni-kl.de } 21012027Sjungma@eit.uni-kl.de} 21112027Sjungma@eit.uni-kl.de 21212027Sjungma@eit.uni-kl.debool 21312027Sjungma@eit.uni-kl.deAbstractController::isBlocked(Addr addr) 21412027Sjungma@eit.uni-kl.de{ 21512027Sjungma@eit.uni-kl.de return (m_block_map.count(addr) > 0); 21612027Sjungma@eit.uni-kl.de} 21712027Sjungma@eit.uni-kl.de 21812027Sjungma@eit.uni-kl.deBaseMasterPort & 21912027Sjungma@eit.uni-kl.deAbstractController::getMasterPort(const std::string &if_name, 22012027Sjungma@eit.uni-kl.de PortID idx) 22112027Sjungma@eit.uni-kl.de{ 22212027Sjungma@eit.uni-kl.de return memoryPort; 22312027Sjungma@eit.uni-kl.de} 22412027Sjungma@eit.uni-kl.de 22512027Sjungma@eit.uni-kl.devoid 22612027Sjungma@eit.uni-kl.deAbstractController::queueMemoryRead(const MachineID &id, Addr addr, 22712027Sjungma@eit.uni-kl.de Cycles latency) 22812027Sjungma@eit.uni-kl.de{ 229 RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 230 m_masterId); 231 232 PacketPtr pkt = Packet::createRead(req); 233 uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()]; 234 pkt->dataDynamic(newData); 235 236 SenderState *s = new SenderState(id); 237 pkt->pushSenderState(s); 238 239 // Use functional rather than timing accesses during warmup 240 if (RubySystem::getWarmupEnabled()) { 241 memoryPort.sendFunctional(pkt); 242 recvTimingResp(pkt); 243 return; 244 } 245 246 memoryPort.schedTimingReq(pkt, clockEdge(latency)); 247} 248 249void 250AbstractController::queueMemoryWrite(const MachineID &id, Addr addr, 251 Cycles latency, const DataBlock &block) 252{ 253 RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 254 m_masterId); 255 256 PacketPtr pkt = Packet::createWrite(req); 257 uint8_t *newData = new uint8_t[RubySystem::getBlockSizeBytes()]; 258 pkt->dataDynamic(newData); 259 memcpy(newData, block.getData(0, RubySystem::getBlockSizeBytes()), 260 RubySystem::getBlockSizeBytes()); 261 262 SenderState *s = new SenderState(id); 263 pkt->pushSenderState(s); 264 265 // Use functional rather than timing accesses during warmup 266 if (RubySystem::getWarmupEnabled()) { 267 memoryPort.sendFunctional(pkt); 268 recvTimingResp(pkt); 269 return; 270 } 271 272 // Create a block and copy data from the block. 273 memoryPort.schedTimingReq(pkt, clockEdge(latency)); 274} 275 276void 277AbstractController::queueMemoryWritePartial(const MachineID &id, Addr addr, 278 Cycles latency, 279 const DataBlock &block, int size) 280{ 281 RequestPtr req = new Request(addr, RubySystem::getBlockSizeBytes(), 0, 282 m_masterId); 283 284 PacketPtr pkt = Packet::createWrite(req); 285 uint8_t *newData = new uint8_t[size]; 286 pkt->dataDynamic(newData); 287 memcpy(newData, block.getData(getOffset(addr), size), size); 288 289 SenderState *s = new SenderState(id); 290 pkt->pushSenderState(s); 291 292 // Create a block and copy data from the block. 293 memoryPort.schedTimingReq(pkt, clockEdge(latency)); 294} 295 296void 297AbstractController::functionalMemoryRead(PacketPtr pkt) 298{ 299 memoryPort.sendFunctional(pkt); 300} 301 302int 303AbstractController::functionalMemoryWrite(PacketPtr pkt) 304{ 305 int num_functional_writes = 0; 306 307 // Check the buffer from the controller to the memory. 308 if (memoryPort.checkFunctional(pkt)) { 309 num_functional_writes++; 310 } 311 312 // Update memory itself. 313 memoryPort.sendFunctional(pkt); 314 return num_functional_writes + 1; 315} 316 317void 318AbstractController::recvTimingResp(PacketPtr pkt) 319{ 320 assert(getMemoryQueue()); 321 assert(pkt->isResponse()); 322 323 std::shared_ptr<MemoryMsg> msg = std::make_shared<MemoryMsg>(clockEdge()); 324 (*msg).m_addr = pkt->getAddr(); 325 (*msg).m_Sender = m_machineID; 326 327 SenderState *s = dynamic_cast<SenderState *>(pkt->senderState); 328 (*msg).m_OriginalRequestorMachId = s->id; 329 delete s; 330 331 if (pkt->isRead()) { 332 (*msg).m_Type = MemoryRequestType_MEMORY_READ; 333 (*msg).m_MessageSize = MessageSizeType_Response_Data; 334 335 // Copy data from the packet 336 (*msg).m_DataBlk.setData(pkt->getPtr<uint8_t>(), 0, 337 RubySystem::getBlockSizeBytes()); 338 } else if (pkt->isWrite()) { 339 (*msg).m_Type = MemoryRequestType_MEMORY_WB; 340 (*msg).m_MessageSize = MessageSizeType_Writeback_Control; 341 } 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