base.cc revision 14055
112810Sandreas.sandberg@arm.com/*
214054Stiago.muck@arm.com * Copyright (c) 2012-2013, 2016-2019 ARM Limited
312810Sandreas.sandberg@arm.com * All rights reserved
412810Sandreas.sandberg@arm.com *
512810Sandreas.sandberg@arm.com * The license below extends only to copyright in the software and shall
612810Sandreas.sandberg@arm.com * not be construed as granting a license to any other intellectual
712810Sandreas.sandberg@arm.com * property including but not limited to intellectual property relating
812810Sandreas.sandberg@arm.com * to a hardware implementation of the functionality of the software
912810Sandreas.sandberg@arm.com * licensed hereunder.  You may use the software subject to the license
1012810Sandreas.sandberg@arm.com * terms below provided that you ensure that this notice is replicated
1112810Sandreas.sandberg@arm.com * unmodified and in its entirety in all distributions of the software,
1212810Sandreas.sandberg@arm.com * modified or unmodified, in source code or in binary form.
1312810Sandreas.sandberg@arm.com *
1412810Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without
1512810Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are
1612810Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright
1712810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer;
1812810Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright
1912810Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the
2012810Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution;
2112810Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its
2212810Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from
2312810Sandreas.sandberg@arm.com * this software without specific prior written permission.
2412810Sandreas.sandberg@arm.com *
2512810Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612810Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712810Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812810Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912810Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012810Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3112810Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212810Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312810Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412810Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512810Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612810Sandreas.sandberg@arm.com *
3712810Sandreas.sandberg@arm.com * Authors: Thomas Grass
3812810Sandreas.sandberg@arm.com *          Andreas Hansson
3912810Sandreas.sandberg@arm.com *          Sascha Bischoff
4012810Sandreas.sandberg@arm.com */
4112810Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/base.hh"
4212810Sandreas.sandberg@arm.com
4312810Sandreas.sandberg@arm.com#include <sstream>
4412810Sandreas.sandberg@arm.com
4512810Sandreas.sandberg@arm.com#include "base/intmath.hh"
4612810Sandreas.sandberg@arm.com#include "base/random.hh"
4712811Sandreas.sandberg@arm.com#include "config/have_protobuf.hh"
4812810Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/base_gen.hh"
4912811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/dram_gen.hh"
5012811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/dram_rot_gen.hh"
5112811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/exit_gen.hh"
5212811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/idle_gen.hh"
5312811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/linear_gen.hh"
5412811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/random_gen.hh"
5512919Sgiacomo.travaglini@arm.com#include "cpu/testers/traffic_gen/stream_gen.hh"
5612810Sandreas.sandberg@arm.com#include "debug/Checkpoint.hh"
5712810Sandreas.sandberg@arm.com#include "debug/TrafficGen.hh"
5812810Sandreas.sandberg@arm.com#include "params/BaseTrafficGen.hh"
5912810Sandreas.sandberg@arm.com#include "sim/sim_exit.hh"
6012810Sandreas.sandberg@arm.com#include "sim/stats.hh"
6112810Sandreas.sandberg@arm.com#include "sim/system.hh"
6212810Sandreas.sandberg@arm.com
6312811Sandreas.sandberg@arm.com#if HAVE_PROTOBUF
6412811Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/trace_gen.hh"
6512811Sandreas.sandberg@arm.com#endif
6612811Sandreas.sandberg@arm.com
6712811Sandreas.sandberg@arm.com
6812810Sandreas.sandberg@arm.comusing namespace std;
6912810Sandreas.sandberg@arm.com
7012810Sandreas.sandberg@arm.comBaseTrafficGen::BaseTrafficGen(const BaseTrafficGenParams* p)
7113892Sgabeblack@google.com    : ClockedObject(p),
7212810Sandreas.sandberg@arm.com      system(p->system),
7312810Sandreas.sandberg@arm.com      elasticReq(p->elastic_req),
7412810Sandreas.sandberg@arm.com      progressCheck(p->progress_check),
7512810Sandreas.sandberg@arm.com      noProgressEvent([this]{ noProgress(); }, name()),
7612810Sandreas.sandberg@arm.com      nextTransitionTick(0),
7712810Sandreas.sandberg@arm.com      nextPacketTick(0),
7814054Stiago.muck@arm.com      maxOutstandingReqs(p->max_outstanding_reqs),
7912810Sandreas.sandberg@arm.com      port(name() + ".port", *this),
8012810Sandreas.sandberg@arm.com      retryPkt(NULL),
8114054Stiago.muck@arm.com      retryPktTick(0), blockedWaitingResp(false),
8212810Sandreas.sandberg@arm.com      updateEvent([this]{ update(); }, name()),
8312919Sgiacomo.travaglini@arm.com      masterID(system->getMasterId(this)),
8412919Sgiacomo.travaglini@arm.com      streamGenerator(StreamGen::create(p))
8512919Sgiacomo.travaglini@arm.com{
8612919Sgiacomo.travaglini@arm.com}
8712919Sgiacomo.travaglini@arm.com
8812919Sgiacomo.travaglini@arm.comBaseTrafficGen::~BaseTrafficGen()
8912810Sandreas.sandberg@arm.com{
9012810Sandreas.sandberg@arm.com}
9112810Sandreas.sandberg@arm.com
9213784Sgabeblack@google.comPort &
9313784Sgabeblack@google.comBaseTrafficGen::getPort(const string &if_name, PortID idx)
9412810Sandreas.sandberg@arm.com{
9512810Sandreas.sandberg@arm.com    if (if_name == "port") {
9612810Sandreas.sandberg@arm.com        return port;
9712810Sandreas.sandberg@arm.com    } else {
9813892Sgabeblack@google.com        return ClockedObject::getPort(if_name, idx);
9912810Sandreas.sandberg@arm.com    }
10012810Sandreas.sandberg@arm.com}
10112810Sandreas.sandberg@arm.com
10212810Sandreas.sandberg@arm.comvoid
10312810Sandreas.sandberg@arm.comBaseTrafficGen::init()
10412810Sandreas.sandberg@arm.com{
10513892Sgabeblack@google.com    ClockedObject::init();
10612810Sandreas.sandberg@arm.com
10712810Sandreas.sandberg@arm.com    if (!port.isConnected())
10812810Sandreas.sandberg@arm.com        fatal("The port of %s is not connected!\n", name());
10912810Sandreas.sandberg@arm.com}
11012810Sandreas.sandberg@arm.com
11112810Sandreas.sandberg@arm.comDrainState
11212810Sandreas.sandberg@arm.comBaseTrafficGen::drain()
11312810Sandreas.sandberg@arm.com{
11412810Sandreas.sandberg@arm.com    if (!updateEvent.scheduled()) {
11512810Sandreas.sandberg@arm.com        // no event has been scheduled yet (e.g. switched from atomic mode)
11612810Sandreas.sandberg@arm.com        return DrainState::Drained;
11712810Sandreas.sandberg@arm.com    }
11812810Sandreas.sandberg@arm.com
11912810Sandreas.sandberg@arm.com    if (retryPkt == NULL) {
12012810Sandreas.sandberg@arm.com        // shut things down
12112810Sandreas.sandberg@arm.com        nextPacketTick = MaxTick;
12212810Sandreas.sandberg@arm.com        nextTransitionTick = MaxTick;
12312810Sandreas.sandberg@arm.com        deschedule(updateEvent);
12412810Sandreas.sandberg@arm.com        return DrainState::Drained;
12512810Sandreas.sandberg@arm.com    } else {
12612810Sandreas.sandberg@arm.com        return DrainState::Draining;
12712810Sandreas.sandberg@arm.com    }
12812810Sandreas.sandberg@arm.com}
12912810Sandreas.sandberg@arm.com
13012810Sandreas.sandberg@arm.comvoid
13112810Sandreas.sandberg@arm.comBaseTrafficGen::serialize(CheckpointOut &cp) const
13212810Sandreas.sandberg@arm.com{
13312845Sgiacomo.travaglini@arm.com    warn("%s serialization does not keep all traffic generator"
13412845Sgiacomo.travaglini@arm.com         " internal state\n", name());
13512845Sgiacomo.travaglini@arm.com
13612810Sandreas.sandberg@arm.com    DPRINTF(Checkpoint, "Serializing BaseTrafficGen\n");
13712810Sandreas.sandberg@arm.com
13812810Sandreas.sandberg@arm.com    // save ticks of the graph event if it is scheduled
13912810Sandreas.sandberg@arm.com    Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;
14012810Sandreas.sandberg@arm.com
14112810Sandreas.sandberg@arm.com    DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);
14212810Sandreas.sandberg@arm.com
14312810Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(nextEvent);
14412810Sandreas.sandberg@arm.com
14512810Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(nextTransitionTick);
14612810Sandreas.sandberg@arm.com
14712810Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(nextPacketTick);
14812810Sandreas.sandberg@arm.com}
14912810Sandreas.sandberg@arm.com
15012810Sandreas.sandberg@arm.comvoid
15112810Sandreas.sandberg@arm.comBaseTrafficGen::unserialize(CheckpointIn &cp)
15212810Sandreas.sandberg@arm.com{
15312845Sgiacomo.travaglini@arm.com    warn("%s serialization does not restore all traffic generator"
15412845Sgiacomo.travaglini@arm.com         " internal state\n", name());
15512845Sgiacomo.travaglini@arm.com
15612810Sandreas.sandberg@arm.com    // restore scheduled events
15712810Sandreas.sandberg@arm.com    Tick nextEvent;
15812810Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(nextEvent);
15912810Sandreas.sandberg@arm.com    if (nextEvent != 0)
16012810Sandreas.sandberg@arm.com        schedule(updateEvent, nextEvent);
16112810Sandreas.sandberg@arm.com
16212810Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(nextTransitionTick);
16312810Sandreas.sandberg@arm.com
16412810Sandreas.sandberg@arm.com    UNSERIALIZE_SCALAR(nextPacketTick);
16512810Sandreas.sandberg@arm.com}
16612810Sandreas.sandberg@arm.com
16712810Sandreas.sandberg@arm.comvoid
16812810Sandreas.sandberg@arm.comBaseTrafficGen::update()
16912810Sandreas.sandberg@arm.com{
17012810Sandreas.sandberg@arm.com    // shift our progress-tracking event forward
17112810Sandreas.sandberg@arm.com    reschedule(noProgressEvent, curTick() + progressCheck, true);
17212810Sandreas.sandberg@arm.com
17312810Sandreas.sandberg@arm.com    // if we have reached the time for the next state transition, then
17412810Sandreas.sandberg@arm.com    // perform the transition
17512810Sandreas.sandberg@arm.com    if (curTick() >= nextTransitionTick) {
17612810Sandreas.sandberg@arm.com        transition();
17712810Sandreas.sandberg@arm.com    } else {
17812810Sandreas.sandberg@arm.com        assert(curTick() >= nextPacketTick);
17912810Sandreas.sandberg@arm.com        // get the next packet and try to send it
18012810Sandreas.sandberg@arm.com        PacketPtr pkt = activeGenerator->getNextPacket();
18112810Sandreas.sandberg@arm.com
18212919Sgiacomo.travaglini@arm.com        // If generating stream/substream IDs are enabled,
18312919Sgiacomo.travaglini@arm.com        // try to pick and assign them to the new packet
18412919Sgiacomo.travaglini@arm.com        if (streamGenerator) {
18512919Sgiacomo.travaglini@arm.com            auto sid = streamGenerator->pickStreamID();
18612919Sgiacomo.travaglini@arm.com            auto ssid = streamGenerator->pickSubStreamID();
18712919Sgiacomo.travaglini@arm.com
18812919Sgiacomo.travaglini@arm.com            pkt->req->setStreamId(sid);
18912919Sgiacomo.travaglini@arm.com
19012919Sgiacomo.travaglini@arm.com            if (streamGenerator->ssidValid()) {
19112919Sgiacomo.travaglini@arm.com                pkt->req->setSubStreamId(ssid);
19212919Sgiacomo.travaglini@arm.com            }
19312919Sgiacomo.travaglini@arm.com        }
19412919Sgiacomo.travaglini@arm.com
19512810Sandreas.sandberg@arm.com        // suppress packets that are not destined for a memory, such as
19612810Sandreas.sandberg@arm.com        // device accesses that could be part of a trace
19712812Sandreas.sandberg@arm.com        if (pkt && system->isMemAddr(pkt->getAddr())) {
19812810Sandreas.sandberg@arm.com            numPackets++;
19914054Stiago.muck@arm.com            // Only attempts to send if not blocked by pending responses
20014054Stiago.muck@arm.com            blockedWaitingResp = allocateWaitingRespSlot(pkt);
20114054Stiago.muck@arm.com            if (blockedWaitingResp || !port.sendTimingReq(pkt)) {
20212810Sandreas.sandberg@arm.com                retryPkt = pkt;
20312810Sandreas.sandberg@arm.com                retryPktTick = curTick();
20412810Sandreas.sandberg@arm.com            }
20512812Sandreas.sandberg@arm.com        } else if (pkt) {
20612810Sandreas.sandberg@arm.com            DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n",
20712810Sandreas.sandberg@arm.com                    pkt->cmdString(), pkt->getAddr());
20812810Sandreas.sandberg@arm.com
20912810Sandreas.sandberg@arm.com            ++numSuppressed;
21012918SMichiel.VanTol@arm.com            if (!(static_cast<int>(numSuppressed.value()) % 10000))
21112810Sandreas.sandberg@arm.com                warn("%s suppressed %d packets with non-memory addresses\n",
21212918SMichiel.VanTol@arm.com                     name(), numSuppressed.value());
21312810Sandreas.sandberg@arm.com
21412810Sandreas.sandberg@arm.com            delete pkt;
21512810Sandreas.sandberg@arm.com            pkt = nullptr;
21612810Sandreas.sandberg@arm.com        }
21712810Sandreas.sandberg@arm.com    }
21812810Sandreas.sandberg@arm.com
21914054Stiago.muck@arm.com    // if we are waiting for a retry or for a response, do not schedule any
22014054Stiago.muck@arm.com    // further events, in the case of a transition or a successful send, go
22112810Sandreas.sandberg@arm.com    // ahead and determine when the next update should take place
22212810Sandreas.sandberg@arm.com    if (retryPkt == NULL) {
22312810Sandreas.sandberg@arm.com        nextPacketTick = activeGenerator->nextPacketTick(elasticReq, 0);
22412810Sandreas.sandberg@arm.com        scheduleUpdate();
22512810Sandreas.sandberg@arm.com    }
22612810Sandreas.sandberg@arm.com}
22712810Sandreas.sandberg@arm.com
22812810Sandreas.sandberg@arm.comvoid
22912810Sandreas.sandberg@arm.comBaseTrafficGen::transition()
23012810Sandreas.sandberg@arm.com{
23112810Sandreas.sandberg@arm.com    if (activeGenerator)
23212810Sandreas.sandberg@arm.com        activeGenerator->exit();
23312810Sandreas.sandberg@arm.com
23412810Sandreas.sandberg@arm.com    activeGenerator = nextGenerator();
23512810Sandreas.sandberg@arm.com
23612810Sandreas.sandberg@arm.com    if (activeGenerator) {
23712810Sandreas.sandberg@arm.com        const Tick duration = activeGenerator->duration;
23812810Sandreas.sandberg@arm.com        if (duration != MaxTick && duration != 0) {
23912810Sandreas.sandberg@arm.com            // we could have been delayed and not transitioned on the
24012810Sandreas.sandberg@arm.com            // exact tick when we were supposed to (due to back
24112810Sandreas.sandberg@arm.com            // pressure when sending a packet)
24212810Sandreas.sandberg@arm.com            nextTransitionTick = curTick() + duration;
24312810Sandreas.sandberg@arm.com        } else {
24412810Sandreas.sandberg@arm.com            nextTransitionTick = MaxTick;
24512810Sandreas.sandberg@arm.com        }
24612810Sandreas.sandberg@arm.com
24712810Sandreas.sandberg@arm.com        activeGenerator->enter();
24812810Sandreas.sandberg@arm.com        nextPacketTick = activeGenerator->nextPacketTick(elasticReq, 0);
24912810Sandreas.sandberg@arm.com    } else {
25012810Sandreas.sandberg@arm.com        nextPacketTick = MaxTick;
25112810Sandreas.sandberg@arm.com        nextTransitionTick = MaxTick;
25212810Sandreas.sandberg@arm.com        assert(!updateEvent.scheduled());
25312810Sandreas.sandberg@arm.com    }
25412810Sandreas.sandberg@arm.com}
25512810Sandreas.sandberg@arm.com
25612810Sandreas.sandberg@arm.comvoid
25712810Sandreas.sandberg@arm.comBaseTrafficGen::scheduleUpdate()
25812810Sandreas.sandberg@arm.com{
25912812Sandreas.sandberg@arm.com    // Has the generator run out of work? In that case, force a
26012812Sandreas.sandberg@arm.com    // transition if a transition period hasn't been configured.
26112812Sandreas.sandberg@arm.com    while (activeGenerator &&
26212812Sandreas.sandberg@arm.com           nextPacketTick == MaxTick && nextTransitionTick == MaxTick) {
26312812Sandreas.sandberg@arm.com        transition();
26412812Sandreas.sandberg@arm.com    }
26512812Sandreas.sandberg@arm.com
26612812Sandreas.sandberg@arm.com    if (!activeGenerator)
26712812Sandreas.sandberg@arm.com        return;
26812812Sandreas.sandberg@arm.com
26912810Sandreas.sandberg@arm.com    // schedule next update event based on either the next execute
27012810Sandreas.sandberg@arm.com    // tick or the next transition, which ever comes first
27112810Sandreas.sandberg@arm.com    const Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
27212810Sandreas.sandberg@arm.com
27312810Sandreas.sandberg@arm.com    DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
27412810Sandreas.sandberg@arm.com
27512810Sandreas.sandberg@arm.com    // The next transition tick may be in the past if there was a
27612810Sandreas.sandberg@arm.com    // retry, so ensure that we don't schedule anything in the past.
27712810Sandreas.sandberg@arm.com    schedule(updateEvent, std::max(curTick(), nextEventTick));
27812810Sandreas.sandberg@arm.com}
27912810Sandreas.sandberg@arm.com
28012810Sandreas.sandberg@arm.comvoid
28112810Sandreas.sandberg@arm.comBaseTrafficGen::start()
28212810Sandreas.sandberg@arm.com{
28312810Sandreas.sandberg@arm.com    transition();
28412810Sandreas.sandberg@arm.com    scheduleUpdate();
28512810Sandreas.sandberg@arm.com}
28612810Sandreas.sandberg@arm.com
28712810Sandreas.sandberg@arm.comvoid
28812810Sandreas.sandberg@arm.comBaseTrafficGen::recvReqRetry()
28912810Sandreas.sandberg@arm.com{
29012810Sandreas.sandberg@arm.com    DPRINTF(TrafficGen, "Received retry\n");
29112810Sandreas.sandberg@arm.com    numRetries++;
29214054Stiago.muck@arm.com    retryReq();
29314054Stiago.muck@arm.com}
29414054Stiago.muck@arm.com
29514054Stiago.muck@arm.comvoid
29614054Stiago.muck@arm.comBaseTrafficGen::retryReq()
29714054Stiago.muck@arm.com{
29814054Stiago.muck@arm.com    assert(retryPkt != NULL);
29914054Stiago.muck@arm.com    assert(retryPktTick != 0);
30014054Stiago.muck@arm.com    assert(!blockedWaitingResp);
30114054Stiago.muck@arm.com
30212810Sandreas.sandberg@arm.com    // attempt to send the packet, and if we are successful start up
30312810Sandreas.sandberg@arm.com    // the machinery again
30412810Sandreas.sandberg@arm.com    if (port.sendTimingReq(retryPkt)) {
30512810Sandreas.sandberg@arm.com        retryPkt = NULL;
30612810Sandreas.sandberg@arm.com        // remember how much delay was incurred due to back-pressure
30712810Sandreas.sandberg@arm.com        // when sending the request, we also use this to derive
30812810Sandreas.sandberg@arm.com        // the tick for the next packet
30912810Sandreas.sandberg@arm.com        Tick delay = curTick() - retryPktTick;
31012810Sandreas.sandberg@arm.com        retryPktTick = 0;
31112810Sandreas.sandberg@arm.com        retryTicks += delay;
31212810Sandreas.sandberg@arm.com
31312810Sandreas.sandberg@arm.com        if (drainState() != DrainState::Draining) {
31412810Sandreas.sandberg@arm.com            // packet is sent, so find out when the next one is due
31512810Sandreas.sandberg@arm.com            nextPacketTick = activeGenerator->nextPacketTick(elasticReq,
31612810Sandreas.sandberg@arm.com                                                             delay);
31712810Sandreas.sandberg@arm.com            scheduleUpdate();
31812810Sandreas.sandberg@arm.com        } else {
31912810Sandreas.sandberg@arm.com            // shut things down
32012810Sandreas.sandberg@arm.com            nextPacketTick = MaxTick;
32112810Sandreas.sandberg@arm.com            nextTransitionTick = MaxTick;
32212810Sandreas.sandberg@arm.com            signalDrainDone();
32312810Sandreas.sandberg@arm.com        }
32412810Sandreas.sandberg@arm.com    }
32512810Sandreas.sandberg@arm.com}
32612810Sandreas.sandberg@arm.com
32712810Sandreas.sandberg@arm.comvoid
32812810Sandreas.sandberg@arm.comBaseTrafficGen::noProgress()
32912810Sandreas.sandberg@arm.com{
33012810Sandreas.sandberg@arm.com    fatal("BaseTrafficGen %s spent %llu ticks without making progress",
33112810Sandreas.sandberg@arm.com          name(), progressCheck);
33212810Sandreas.sandberg@arm.com}
33312810Sandreas.sandberg@arm.com
33412810Sandreas.sandberg@arm.comvoid
33512810Sandreas.sandberg@arm.comBaseTrafficGen::regStats()
33612810Sandreas.sandberg@arm.com{
33712810Sandreas.sandberg@arm.com    ClockedObject::regStats();
33812810Sandreas.sandberg@arm.com
33912810Sandreas.sandberg@arm.com    // Initialise all the stats
34012810Sandreas.sandberg@arm.com    using namespace Stats;
34112810Sandreas.sandberg@arm.com
34212810Sandreas.sandberg@arm.com    numPackets
34312810Sandreas.sandberg@arm.com        .name(name() + ".numPackets")
34412810Sandreas.sandberg@arm.com        .desc("Number of packets generated");
34512810Sandreas.sandberg@arm.com
34612918SMichiel.VanTol@arm.com    numSuppressed
34712918SMichiel.VanTol@arm.com        .name(name() + ".numSuppressed")
34812918SMichiel.VanTol@arm.com        .desc("Number of suppressed packets to non-memory space");
34912918SMichiel.VanTol@arm.com
35012810Sandreas.sandberg@arm.com    numRetries
35112810Sandreas.sandberg@arm.com        .name(name() + ".numRetries")
35212810Sandreas.sandberg@arm.com        .desc("Number of retries");
35312810Sandreas.sandberg@arm.com
35412810Sandreas.sandberg@arm.com    retryTicks
35512810Sandreas.sandberg@arm.com        .name(name() + ".retryTicks")
35612810Sandreas.sandberg@arm.com        .desc("Time spent waiting due to back-pressure (ticks)");
35714055Stiago.muck@arm.com
35814055Stiago.muck@arm.com    bytesRead
35914055Stiago.muck@arm.com        .name(name() + ".bytesRead")
36014055Stiago.muck@arm.com        .desc("Number of bytes read");
36114055Stiago.muck@arm.com
36214055Stiago.muck@arm.com    bytesWritten
36314055Stiago.muck@arm.com        .name(name() + ".bytesWritten")
36414055Stiago.muck@arm.com        .desc("Number of bytes written");
36514055Stiago.muck@arm.com
36614055Stiago.muck@arm.com    totalReadLatency
36714055Stiago.muck@arm.com        .name(name() + ".totalReadLatency")
36814055Stiago.muck@arm.com        .desc("Total latency of read requests");
36914055Stiago.muck@arm.com
37014055Stiago.muck@arm.com    totalWriteLatency
37114055Stiago.muck@arm.com        .name(name() + ".totalWriteLatency")
37214055Stiago.muck@arm.com        .desc("Total latency of write requests");
37314055Stiago.muck@arm.com
37414055Stiago.muck@arm.com    totalReads
37514055Stiago.muck@arm.com        .name(name() + ".totalReads")
37614055Stiago.muck@arm.com        .desc("Total num of reads");
37714055Stiago.muck@arm.com
37814055Stiago.muck@arm.com    totalWrites
37914055Stiago.muck@arm.com        .name(name() + ".totalWrites")
38014055Stiago.muck@arm.com        .desc("Total num of writes");
38114055Stiago.muck@arm.com
38214055Stiago.muck@arm.com    avgReadLatency
38314055Stiago.muck@arm.com        .name(name() + ".avgReadLatency")
38414055Stiago.muck@arm.com        .desc("Avg latency of read requests");
38514055Stiago.muck@arm.com    avgReadLatency = totalReadLatency / totalReads;
38614055Stiago.muck@arm.com
38714055Stiago.muck@arm.com    avgWriteLatency
38814055Stiago.muck@arm.com        .name(name() + ".avgWriteLatency")
38914055Stiago.muck@arm.com        .desc("Avg latency of write requests");
39014055Stiago.muck@arm.com    avgWriteLatency = totalWriteLatency / totalWrites;
39114055Stiago.muck@arm.com
39214055Stiago.muck@arm.com    readBW
39314055Stiago.muck@arm.com        .name(name() + ".readBW")
39414055Stiago.muck@arm.com        .desc("Read bandwidth in bytes/s");
39514055Stiago.muck@arm.com    readBW = bytesRead / simSeconds;
39614055Stiago.muck@arm.com
39714055Stiago.muck@arm.com    writeBW
39814055Stiago.muck@arm.com        .name(name() + ".writeBW")
39914055Stiago.muck@arm.com        .desc("Write bandwidth in bytes/s");
40014055Stiago.muck@arm.com    writeBW = bytesWritten / simSeconds;
40114055Stiago.muck@arm.com
40212810Sandreas.sandberg@arm.com}
40312810Sandreas.sandberg@arm.com
40412811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
40512811Sandreas.sandberg@arm.comBaseTrafficGen::createIdle(Tick duration)
40612811Sandreas.sandberg@arm.com{
40712844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new IdleGen(*this, masterID, duration));
40812811Sandreas.sandberg@arm.com}
40912811Sandreas.sandberg@arm.com
41012811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
41112811Sandreas.sandberg@arm.comBaseTrafficGen::createExit(Tick duration)
41212811Sandreas.sandberg@arm.com{
41312844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new ExitGen(*this, masterID, duration));
41412811Sandreas.sandberg@arm.com}
41512811Sandreas.sandberg@arm.com
41612811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
41712811Sandreas.sandberg@arm.comBaseTrafficGen::createLinear(Tick duration,
41812811Sandreas.sandberg@arm.com                             Addr start_addr, Addr end_addr, Addr blocksize,
41912811Sandreas.sandberg@arm.com                             Tick min_period, Tick max_period,
42012811Sandreas.sandberg@arm.com                             uint8_t read_percent, Addr data_limit)
42112811Sandreas.sandberg@arm.com{
42212844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new LinearGen(*this, masterID,
42312811Sandreas.sandberg@arm.com                                                  duration, start_addr,
42412811Sandreas.sandberg@arm.com                                                  end_addr, blocksize,
42512844Sgiacomo.travaglini@arm.com                                                  system->cacheLineSize(),
42612811Sandreas.sandberg@arm.com                                                  min_period, max_period,
42712811Sandreas.sandberg@arm.com                                                  read_percent, data_limit));
42812811Sandreas.sandberg@arm.com}
42912811Sandreas.sandberg@arm.com
43012811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
43112811Sandreas.sandberg@arm.comBaseTrafficGen::createRandom(Tick duration,
43212811Sandreas.sandberg@arm.com                             Addr start_addr, Addr end_addr, Addr blocksize,
43312811Sandreas.sandberg@arm.com                             Tick min_period, Tick max_period,
43412811Sandreas.sandberg@arm.com                             uint8_t read_percent, Addr data_limit)
43512811Sandreas.sandberg@arm.com{
43612844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new RandomGen(*this, masterID,
43712811Sandreas.sandberg@arm.com                                                  duration, start_addr,
43812811Sandreas.sandberg@arm.com                                                  end_addr, blocksize,
43912844Sgiacomo.travaglini@arm.com                                                  system->cacheLineSize(),
44012811Sandreas.sandberg@arm.com                                                  min_period, max_period,
44112811Sandreas.sandberg@arm.com                                                  read_percent, data_limit));
44212811Sandreas.sandberg@arm.com}
44312811Sandreas.sandberg@arm.com
44412811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
44512811Sandreas.sandberg@arm.comBaseTrafficGen::createDram(Tick duration,
44612811Sandreas.sandberg@arm.com                           Addr start_addr, Addr end_addr, Addr blocksize,
44712811Sandreas.sandberg@arm.com                           Tick min_period, Tick max_period,
44812811Sandreas.sandberg@arm.com                           uint8_t read_percent, Addr data_limit,
44912811Sandreas.sandberg@arm.com                           unsigned int num_seq_pkts, unsigned int page_size,
45012811Sandreas.sandberg@arm.com                           unsigned int nbr_of_banks_DRAM,
45112811Sandreas.sandberg@arm.com                           unsigned int nbr_of_banks_util,
45212811Sandreas.sandberg@arm.com                           unsigned int addr_mapping,
45312811Sandreas.sandberg@arm.com                           unsigned int nbr_of_ranks)
45412811Sandreas.sandberg@arm.com{
45512844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new DramGen(*this, masterID,
45612811Sandreas.sandberg@arm.com                                                duration, start_addr,
45712811Sandreas.sandberg@arm.com                                                end_addr, blocksize,
45812844Sgiacomo.travaglini@arm.com                                                system->cacheLineSize(),
45912811Sandreas.sandberg@arm.com                                                min_period, max_period,
46012811Sandreas.sandberg@arm.com                                                read_percent, data_limit,
46112811Sandreas.sandberg@arm.com                                                num_seq_pkts, page_size,
46212811Sandreas.sandberg@arm.com                                                nbr_of_banks_DRAM,
46312811Sandreas.sandberg@arm.com                                                nbr_of_banks_util,
46412811Sandreas.sandberg@arm.com                                                addr_mapping,
46512811Sandreas.sandberg@arm.com                                                nbr_of_ranks));
46612811Sandreas.sandberg@arm.com}
46712811Sandreas.sandberg@arm.com
46812811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
46912811Sandreas.sandberg@arm.comBaseTrafficGen::createDramRot(Tick duration,
47012811Sandreas.sandberg@arm.com                              Addr start_addr, Addr end_addr, Addr blocksize,
47112811Sandreas.sandberg@arm.com                              Tick min_period, Tick max_period,
47212811Sandreas.sandberg@arm.com                              uint8_t read_percent, Addr data_limit,
47312811Sandreas.sandberg@arm.com                              unsigned int num_seq_pkts,
47412811Sandreas.sandberg@arm.com                              unsigned int page_size,
47512811Sandreas.sandberg@arm.com                              unsigned int nbr_of_banks_DRAM,
47612811Sandreas.sandberg@arm.com                              unsigned int nbr_of_banks_util,
47712811Sandreas.sandberg@arm.com                              unsigned int addr_mapping,
47812811Sandreas.sandberg@arm.com                              unsigned int nbr_of_ranks,
47912811Sandreas.sandberg@arm.com                              unsigned int max_seq_count_per_rank)
48012811Sandreas.sandberg@arm.com{
48112844Sgiacomo.travaglini@arm.com    return std::shared_ptr<BaseGen>(new DramRotGen(*this, masterID,
48212811Sandreas.sandberg@arm.com                                                   duration, start_addr,
48312811Sandreas.sandberg@arm.com                                                   end_addr, blocksize,
48412844Sgiacomo.travaglini@arm.com                                                   system->cacheLineSize(),
48512811Sandreas.sandberg@arm.com                                                   min_period, max_period,
48612811Sandreas.sandberg@arm.com                                                   read_percent, data_limit,
48712811Sandreas.sandberg@arm.com                                                   num_seq_pkts, page_size,
48812811Sandreas.sandberg@arm.com                                                   nbr_of_banks_DRAM,
48912811Sandreas.sandberg@arm.com                                                   nbr_of_banks_util,
49012811Sandreas.sandberg@arm.com                                                   addr_mapping,
49112811Sandreas.sandberg@arm.com                                                   nbr_of_ranks,
49212811Sandreas.sandberg@arm.com                                                   max_seq_count_per_rank));
49312811Sandreas.sandberg@arm.com}
49412811Sandreas.sandberg@arm.com
49512811Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
49612811Sandreas.sandberg@arm.comBaseTrafficGen::createTrace(Tick duration,
49712811Sandreas.sandberg@arm.com                            const std::string& trace_file, Addr addr_offset)
49812811Sandreas.sandberg@arm.com{
49912811Sandreas.sandberg@arm.com#if HAVE_PROTOBUF
50012811Sandreas.sandberg@arm.com    return std::shared_ptr<BaseGen>(
50112844Sgiacomo.travaglini@arm.com        new TraceGen(*this, masterID, duration, trace_file, addr_offset));
50212811Sandreas.sandberg@arm.com#else
50312811Sandreas.sandberg@arm.com    panic("Can't instantiate trace generation without Protobuf support!\n");
50412811Sandreas.sandberg@arm.com#endif
50512811Sandreas.sandberg@arm.com}
50612811Sandreas.sandberg@arm.com
50712810Sandreas.sandberg@arm.combool
50814054Stiago.muck@arm.comBaseTrafficGen::recvTimingResp(PacketPtr pkt)
50912810Sandreas.sandberg@arm.com{
51014054Stiago.muck@arm.com    auto iter = waitingResp.find(pkt->req);
51114054Stiago.muck@arm.com
51214054Stiago.muck@arm.com    panic_if(iter == waitingResp.end(), "%s: "
51314054Stiago.muck@arm.com            "Received unexpected response [%s reqPtr=%x]\n",
51414054Stiago.muck@arm.com               pkt->print(), pkt->req);
51514054Stiago.muck@arm.com
51614054Stiago.muck@arm.com    assert(iter->second <= curTick());
51714054Stiago.muck@arm.com
51814055Stiago.muck@arm.com    if (pkt->isWrite()) {
51914055Stiago.muck@arm.com        ++totalWrites;
52014055Stiago.muck@arm.com        bytesWritten += pkt->req->getSize();
52114055Stiago.muck@arm.com        totalWriteLatency += curTick() - iter->second;
52214055Stiago.muck@arm.com    } else {
52314055Stiago.muck@arm.com        ++totalReads;
52414055Stiago.muck@arm.com        bytesRead += pkt->req->getSize();
52514055Stiago.muck@arm.com        totalReadLatency += curTick() - iter->second;
52614055Stiago.muck@arm.com    }
52714055Stiago.muck@arm.com
52814054Stiago.muck@arm.com    waitingResp.erase(iter);
52914054Stiago.muck@arm.com
53012810Sandreas.sandberg@arm.com    delete pkt;
53112810Sandreas.sandberg@arm.com
53214054Stiago.muck@arm.com    // Sends up the request if we were blocked
53314054Stiago.muck@arm.com    if (blockedWaitingResp) {
53414054Stiago.muck@arm.com        blockedWaitingResp = false;
53514054Stiago.muck@arm.com        retryReq();
53614054Stiago.muck@arm.com    }
53714054Stiago.muck@arm.com
53812810Sandreas.sandberg@arm.com    return true;
53912810Sandreas.sandberg@arm.com}
540