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