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