traffic_gen.cc revision 12397
19241Sandreas.hansson@arm.com/*
212397SRiken.Gohil@arm.com * Copyright (c) 2012-2013, 2016-2017 ARM Limited
39241Sandreas.hansson@arm.com * All rights reserved
49241Sandreas.hansson@arm.com *
59241Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall
69241Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual
79241Sandreas.hansson@arm.com * property including but not limited to intellectual property relating
89241Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software
99241Sandreas.hansson@arm.com * licensed hereunder.  You may use the software subject to the license
109241Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated
119241Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software,
129241Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form.
139241Sandreas.hansson@arm.com *
149241Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without
159241Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are
169241Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright
179241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer;
189241Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright
199241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the
209241Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution;
219241Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its
229241Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from
239241Sandreas.hansson@arm.com * this software without specific prior written permission.
249241Sandreas.hansson@arm.com *
259241Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
269241Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
279241Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
289241Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
299241Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
309241Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
319241Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
329241Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
339241Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
349241Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
359241Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369241Sandreas.hansson@arm.com *
379241Sandreas.hansson@arm.com * Authors: Thomas Grass
389241Sandreas.hansson@arm.com *          Andreas Hansson
399241Sandreas.hansson@arm.com *          Sascha Bischoff
409241Sandreas.hansson@arm.com */
4111540Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/traffic_gen.hh"
4211540Sandreas.sandberg@arm.com
4311540Sandreas.sandberg@arm.com#include <libgen.h>
4411540Sandreas.sandberg@arm.com#include <unistd.h>
459241Sandreas.hansson@arm.com
469241Sandreas.hansson@arm.com#include <sstream>
479241Sandreas.hansson@arm.com
4810138Sneha.agarwal@arm.com#include "base/intmath.hh"
499241Sandreas.hansson@arm.com#include "base/random.hh"
509241Sandreas.hansson@arm.com#include "debug/Checkpoint.hh"
519241Sandreas.hansson@arm.com#include "debug/TrafficGen.hh"
529241Sandreas.hansson@arm.com#include "sim/stats.hh"
539241Sandreas.hansson@arm.com#include "sim/system.hh"
549241Sandreas.hansson@arm.com
559241Sandreas.hansson@arm.comusing namespace std;
569241Sandreas.hansson@arm.com
579241Sandreas.hansson@arm.comTrafficGen::TrafficGen(const TrafficGenParams* p)
589241Sandreas.hansson@arm.com    : MemObject(p),
599241Sandreas.hansson@arm.com      system(p->system),
609241Sandreas.hansson@arm.com      masterID(system->getMasterId(name())),
619718Sandreas.hansson@arm.com      configFile(p->config_file),
629720Sandreas.hansson@arm.com      elasticReq(p->elastic_req),
6311491Sandreas.hansson@arm.com      progressCheck(p->progress_check),
6412085Sspwilson2@wisc.edu      noProgressEvent([this]{ noProgress(); }, name()),
659717Sandreas.hansson@arm.com      nextTransitionTick(0),
669719Sandreas.hansson@arm.com      nextPacketTick(0),
6710360Sandreas.hansson@arm.com      currState(0),
689241Sandreas.hansson@arm.com      port(name() + ".port", *this),
699719Sandreas.hansson@arm.com      retryPkt(NULL),
709719Sandreas.hansson@arm.com      retryPktTick(0),
7112085Sspwilson2@wisc.edu      updateEvent([this]{ update(); }, name()),
7211393Sandreas.hansson@arm.com      numSuppressed(0)
739241Sandreas.hansson@arm.com{
749241Sandreas.hansson@arm.com}
759241Sandreas.hansson@arm.com
769241Sandreas.hansson@arm.comTrafficGen*
779241Sandreas.hansson@arm.comTrafficGenParams::create()
789241Sandreas.hansson@arm.com{
799241Sandreas.hansson@arm.com    return new TrafficGen(this);
809241Sandreas.hansson@arm.com}
819241Sandreas.hansson@arm.com
829294Sandreas.hansson@arm.comBaseMasterPort&
839294Sandreas.hansson@arm.comTrafficGen::getMasterPort(const string& if_name, PortID idx)
849241Sandreas.hansson@arm.com{
859241Sandreas.hansson@arm.com    if (if_name == "port") {
869241Sandreas.hansson@arm.com        return port;
879241Sandreas.hansson@arm.com    } else {
889241Sandreas.hansson@arm.com        return MemObject::getMasterPort(if_name, idx);
899241Sandreas.hansson@arm.com    }
909241Sandreas.hansson@arm.com}
919241Sandreas.hansson@arm.com
929241Sandreas.hansson@arm.comvoid
939241Sandreas.hansson@arm.comTrafficGen::init()
949241Sandreas.hansson@arm.com{
959241Sandreas.hansson@arm.com    if (!port.isConnected())
969241Sandreas.hansson@arm.com        fatal("The port of %s is not connected!\n", name());
979241Sandreas.hansson@arm.com
989241Sandreas.hansson@arm.com    // if the system is in timing mode active the request generator
999524SAndreas.Sandberg@ARM.com    if (system->isTimingMode()) {
1009241Sandreas.hansson@arm.com        DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
1019241Sandreas.hansson@arm.com
1029718Sandreas.hansson@arm.com        parseConfig();
1039718Sandreas.hansson@arm.com
1049241Sandreas.hansson@arm.com        // enter initial state
1059717Sandreas.hansson@arm.com        enterState(currState);
1069241Sandreas.hansson@arm.com    } else {
1079241Sandreas.hansson@arm.com        DPRINTF(TrafficGen,
1089241Sandreas.hansson@arm.com                "Traffic generator is only active in timing mode\n");
1099241Sandreas.hansson@arm.com    }
1109241Sandreas.hansson@arm.com}
1119241Sandreas.hansson@arm.com
1129241Sandreas.hansson@arm.comvoid
1139241Sandreas.hansson@arm.comTrafficGen::initState()
1149241Sandreas.hansson@arm.com{
1159241Sandreas.hansson@arm.com    // when not restoring from a checkpoint, make sure we kick things off
1169524SAndreas.Sandberg@ARM.com    if (system->isTimingMode()) {
1179719Sandreas.hansson@arm.com        // call nextPacketTick on the state to advance it
1189720Sandreas.hansson@arm.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
1199719Sandreas.hansson@arm.com        schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick));
1209241Sandreas.hansson@arm.com    } else {
1219241Sandreas.hansson@arm.com        DPRINTF(TrafficGen,
1229241Sandreas.hansson@arm.com                "Traffic generator is only active in timing mode\n");
1239241Sandreas.hansson@arm.com    }
1249241Sandreas.hansson@arm.com}
1259241Sandreas.hansson@arm.com
12610913Sandreas.sandberg@arm.comDrainState
12710913Sandreas.sandberg@arm.comTrafficGen::drain()
1289241Sandreas.hansson@arm.com{
12910051Srioshering@gmail.com    if (!updateEvent.scheduled()) {
13010051Srioshering@gmail.com        // no event has been scheduled yet (e.g. switched from atomic mode)
13110913Sandreas.sandberg@arm.com        return DrainState::Drained;
13210051Srioshering@gmail.com    }
13310051Srioshering@gmail.com
1349719Sandreas.hansson@arm.com    if (retryPkt == NULL) {
1359719Sandreas.hansson@arm.com        // shut things down
1369719Sandreas.hansson@arm.com        nextPacketTick = MaxTick;
1379719Sandreas.hansson@arm.com        nextTransitionTick = MaxTick;
1389719Sandreas.hansson@arm.com        deschedule(updateEvent);
13910913Sandreas.sandberg@arm.com        return DrainState::Drained;
1409719Sandreas.hansson@arm.com    } else {
14110913Sandreas.sandberg@arm.com        return DrainState::Draining;
1429719Sandreas.hansson@arm.com    }
1439241Sandreas.hansson@arm.com}
1449241Sandreas.hansson@arm.com
1459241Sandreas.hansson@arm.comvoid
14610905Sandreas.sandberg@arm.comTrafficGen::serialize(CheckpointOut &cp) const
1479241Sandreas.hansson@arm.com{
1489241Sandreas.hansson@arm.com    DPRINTF(Checkpoint, "Serializing TrafficGen\n");
1499241Sandreas.hansson@arm.com
1509241Sandreas.hansson@arm.com    // save ticks of the graph event if it is scheduled
1519719Sandreas.hansson@arm.com    Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;
1529241Sandreas.hansson@arm.com
1539719Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);
1549241Sandreas.hansson@arm.com
1559717Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextEvent);
1569241Sandreas.hansson@arm.com
1579241Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextTransitionTick);
1589241Sandreas.hansson@arm.com
1599719Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextPacketTick);
1609719Sandreas.hansson@arm.com
1619719Sandreas.hansson@arm.com    SERIALIZE_SCALAR(currState);
1629241Sandreas.hansson@arm.com}
1639241Sandreas.hansson@arm.com
1649241Sandreas.hansson@arm.comvoid
16510905Sandreas.sandberg@arm.comTrafficGen::unserialize(CheckpointIn &cp)
1669241Sandreas.hansson@arm.com{
1679241Sandreas.hansson@arm.com    // restore scheduled events
1689717Sandreas.hansson@arm.com    Tick nextEvent;
1699717Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextEvent);
1709717Sandreas.hansson@arm.com    if (nextEvent != 0) {
1719717Sandreas.hansson@arm.com        schedule(updateEvent, nextEvent);
1729241Sandreas.hansson@arm.com    }
1739241Sandreas.hansson@arm.com
1749241Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextTransitionTick);
1759719Sandreas.hansson@arm.com
1769719Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextPacketTick);
1779719Sandreas.hansson@arm.com
1789719Sandreas.hansson@arm.com    // @todo In the case of a stateful generator state such as the
1799719Sandreas.hansson@arm.com    // trace player we would also have to restore the position in the
1809720Sandreas.hansson@arm.com    // trace playback and the tick offset
1819719Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(currState);
1829241Sandreas.hansson@arm.com}
1839241Sandreas.hansson@arm.com
1849241Sandreas.hansson@arm.comvoid
1859717Sandreas.hansson@arm.comTrafficGen::update()
1869241Sandreas.hansson@arm.com{
18711491Sandreas.hansson@arm.com    // shift our progress-tracking event forward
18811491Sandreas.hansson@arm.com    reschedule(noProgressEvent, curTick() + progressCheck, true);
18911491Sandreas.hansson@arm.com
1909717Sandreas.hansson@arm.com    // if we have reached the time for the next state transition, then
1919717Sandreas.hansson@arm.com    // perform the transition
1929717Sandreas.hansson@arm.com    if (curTick() >= nextTransitionTick) {
1939717Sandreas.hansson@arm.com        transition();
1949717Sandreas.hansson@arm.com    } else {
1959719Sandreas.hansson@arm.com        assert(curTick() >= nextPacketTick);
1969719Sandreas.hansson@arm.com        // get the next packet and try to send it
1979718Sandreas.hansson@arm.com        PacketPtr pkt = states[currState]->getNextPacket();
19810266Sandreas.hansson@arm.com
19910266Sandreas.hansson@arm.com        // suppress packets that are not destined for a memory, such as
20010266Sandreas.hansson@arm.com        // device accesses that could be part of a trace
20110266Sandreas.hansson@arm.com        if (system->isMemAddr(pkt->getAddr())) {
20210266Sandreas.hansson@arm.com            numPackets++;
20310266Sandreas.hansson@arm.com            if (!port.sendTimingReq(pkt)) {
20410266Sandreas.hansson@arm.com                retryPkt = pkt;
20510266Sandreas.hansson@arm.com                retryPktTick = curTick();
20610266Sandreas.hansson@arm.com            }
20710266Sandreas.hansson@arm.com        } else {
20810266Sandreas.hansson@arm.com            DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n",
20910266Sandreas.hansson@arm.com                    pkt->cmdString(), pkt->getAddr());
21011393Sandreas.hansson@arm.com
21111393Sandreas.hansson@arm.com            ++numSuppressed;
21211393Sandreas.hansson@arm.com            if (numSuppressed % 10000)
21311393Sandreas.hansson@arm.com                warn("%s suppressed %d packets with non-memory addresses\n",
21411393Sandreas.hansson@arm.com                     name(), numSuppressed);
21511393Sandreas.hansson@arm.com
21611222Sandreas.hansson@arm.com            delete pkt->req;
21711222Sandreas.hansson@arm.com            delete pkt;
21811222Sandreas.hansson@arm.com            pkt = nullptr;
2199719Sandreas.hansson@arm.com        }
2209719Sandreas.hansson@arm.com    }
2219719Sandreas.hansson@arm.com
2229719Sandreas.hansson@arm.com    // if we are waiting for a retry, do not schedule any further
2239719Sandreas.hansson@arm.com    // events, in the case of a transition or a successful send, go
2249719Sandreas.hansson@arm.com    // ahead and determine when the next update should take place
2259719Sandreas.hansson@arm.com    if (retryPkt == NULL) {
2269719Sandreas.hansson@arm.com        // schedule next update event based on either the next execute
2279719Sandreas.hansson@arm.com        // tick or the next transition, which ever comes first
2289720Sandreas.hansson@arm.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
2299719Sandreas.hansson@arm.com        Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
2309719Sandreas.hansson@arm.com        DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
2319719Sandreas.hansson@arm.com        schedule(updateEvent, nextEventTick);
2329717Sandreas.hansson@arm.com    }
2339241Sandreas.hansson@arm.com}
2349241Sandreas.hansson@arm.com
23511540Sandreas.sandberg@arm.comstd::string
23611540Sandreas.sandberg@arm.comTrafficGen::resolveFile(const std::string &name)
23711540Sandreas.sandberg@arm.com{
23811540Sandreas.sandberg@arm.com    // Do nothing for empty and absolute file names
23911540Sandreas.sandberg@arm.com    if (name.empty() || name[0] == '/')
24011540Sandreas.sandberg@arm.com        return name;
24111540Sandreas.sandberg@arm.com
24211540Sandreas.sandberg@arm.com    char *config_path = strdup(configFile.c_str());
24311540Sandreas.sandberg@arm.com    char *config_dir = dirname(config_path);
24411540Sandreas.sandberg@arm.com    const std::string config_rel = csprintf("%s/%s", config_dir, name);
24511540Sandreas.sandberg@arm.com    free(config_path);
24611540Sandreas.sandberg@arm.com
24711540Sandreas.sandberg@arm.com    // Check the path relative to the config file first
24811540Sandreas.sandberg@arm.com    if (access(config_rel.c_str(), R_OK) == 0)
24911540Sandreas.sandberg@arm.com        return config_rel;
25011540Sandreas.sandberg@arm.com
25111540Sandreas.sandberg@arm.com    // Fall back to the old behavior and search relative to the
25211540Sandreas.sandberg@arm.com    // current working directory.
25311540Sandreas.sandberg@arm.com    return name;
25411540Sandreas.sandberg@arm.com}
25511540Sandreas.sandberg@arm.com
2569241Sandreas.hansson@arm.comvoid
2579718Sandreas.hansson@arm.comTrafficGen::parseConfig()
2589241Sandreas.hansson@arm.com{
2599241Sandreas.hansson@arm.com    // keep track of the transitions parsed to create the matrix when
2609241Sandreas.hansson@arm.com    // done
2619241Sandreas.hansson@arm.com    vector<Transition> transitions;
2629241Sandreas.hansson@arm.com
2639241Sandreas.hansson@arm.com    // open input file
2649241Sandreas.hansson@arm.com    ifstream infile;
2659718Sandreas.hansson@arm.com    infile.open(configFile.c_str(), ifstream::in);
2669241Sandreas.hansson@arm.com    if (!infile.is_open()) {
2679241Sandreas.hansson@arm.com        fatal("Traffic generator %s config file not found at %s\n",
2689718Sandreas.hansson@arm.com              name(), configFile);
2699241Sandreas.hansson@arm.com    }
2709241Sandreas.hansson@arm.com
27110128Sstan.czerniawski@arm.com    bool init_state_set = false;
27210128Sstan.czerniawski@arm.com
2739241Sandreas.hansson@arm.com    // read line by line and determine the action based on the first
2749241Sandreas.hansson@arm.com    // keyword
2759241Sandreas.hansson@arm.com    string keyword;
2769241Sandreas.hansson@arm.com    string line;
2779241Sandreas.hansson@arm.com
2789241Sandreas.hansson@arm.com    while (getline(infile, line).good()) {
2799241Sandreas.hansson@arm.com        // see if this line is a comment line, and if so skip it
2809241Sandreas.hansson@arm.com        if (line.find('#') != 1) {
2819241Sandreas.hansson@arm.com            // create an input stream for the tokenization
2829241Sandreas.hansson@arm.com            istringstream is(line);
2839241Sandreas.hansson@arm.com
2849241Sandreas.hansson@arm.com            // determine the keyword
2859241Sandreas.hansson@arm.com            is >> keyword;
2869241Sandreas.hansson@arm.com
2879241Sandreas.hansson@arm.com            if (keyword == "STATE") {
2889241Sandreas.hansson@arm.com                // parse the behaviour of this state
2899241Sandreas.hansson@arm.com                uint32_t id;
2909241Sandreas.hansson@arm.com                Tick duration;
2919241Sandreas.hansson@arm.com                string mode;
2929241Sandreas.hansson@arm.com
2939241Sandreas.hansson@arm.com                is >> id >> duration >> mode;
2949241Sandreas.hansson@arm.com
2959241Sandreas.hansson@arm.com                if (mode == "TRACE") {
2969241Sandreas.hansson@arm.com                    string traceFile;
2979241Sandreas.hansson@arm.com                    Addr addrOffset;
2989241Sandreas.hansson@arm.com
2999241Sandreas.hansson@arm.com                    is >> traceFile >> addrOffset;
30011540Sandreas.sandberg@arm.com                    traceFile = resolveFile(traceFile);
3019241Sandreas.hansson@arm.com
3029718Sandreas.hansson@arm.com                    states[id] = new TraceGen(name(), masterID, duration,
3039241Sandreas.hansson@arm.com                                              traceFile, addrOffset);
3049241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
3059241Sandreas.hansson@arm.com                } else if (mode == "IDLE") {
3069718Sandreas.hansson@arm.com                    states[id] = new IdleGen(name(), masterID, duration);
3079241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
30812397SRiken.Gohil@arm.com                } else if (mode == "EXIT") {
30912397SRiken.Gohil@arm.com                    states[id] = new ExitGen(name(), masterID, duration);
31012397SRiken.Gohil@arm.com                    DPRINTF(TrafficGen, "State: %d ExitGen\n", id);
31110138Sneha.agarwal@arm.com                } else if (mode == "LINEAR" || mode == "RANDOM" ||
31210392Swendy.elsasser@arm.com                           mode == "DRAM"   || mode == "DRAM_ROTATE") {
3139241Sandreas.hansson@arm.com                    uint32_t read_percent;
3149241Sandreas.hansson@arm.com                    Addr start_addr;
3159241Sandreas.hansson@arm.com                    Addr end_addr;
3169241Sandreas.hansson@arm.com                    Addr blocksize;
3179241Sandreas.hansson@arm.com                    Tick min_period;
3189241Sandreas.hansson@arm.com                    Tick max_period;
3199241Sandreas.hansson@arm.com                    Addr data_limit;
3209241Sandreas.hansson@arm.com
3219241Sandreas.hansson@arm.com                    is >> read_percent >> start_addr >> end_addr >>
3229241Sandreas.hansson@arm.com                        blocksize >> min_period >> max_period >> data_limit;
3239241Sandreas.hansson@arm.com
3249241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "%s, addr %x to %x, size %d,"
3259241Sandreas.hansson@arm.com                            " period %d to %d, %d%% reads\n",
3269241Sandreas.hansson@arm.com                            mode, start_addr, end_addr, blocksize, min_period,
3279241Sandreas.hansson@arm.com                            max_period, read_percent);
3289241Sandreas.hansson@arm.com
3299718Sandreas.hansson@arm.com
3309814Sandreas.hansson@arm.com                    if (blocksize > system->cacheLineSize())
3319718Sandreas.hansson@arm.com                        fatal("TrafficGen %s block size (%d) is larger than "
33210138Sneha.agarwal@arm.com                              "cache line size (%d)\n", name(),
3339814Sandreas.hansson@arm.com                              blocksize, system->cacheLineSize());
3349718Sandreas.hansson@arm.com
3359241Sandreas.hansson@arm.com                    if (read_percent > 100)
3369718Sandreas.hansson@arm.com                        fatal("%s cannot have more than 100% reads", name());
3379241Sandreas.hansson@arm.com
3389722Ssascha.bischoff@arm.com                    if (min_period > max_period)
3399722Ssascha.bischoff@arm.com                        fatal("%s cannot have min_period > max_period", name());
3409722Ssascha.bischoff@arm.com
3419241Sandreas.hansson@arm.com                    if (mode == "LINEAR") {
3429718Sandreas.hansson@arm.com                        states[id] = new LinearGen(name(), masterID,
3439241Sandreas.hansson@arm.com                                                   duration, start_addr,
3449241Sandreas.hansson@arm.com                                                   end_addr, blocksize,
3459241Sandreas.hansson@arm.com                                                   min_period, max_period,
3469241Sandreas.hansson@arm.com                                                   read_percent, data_limit);
3479241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
3489241Sandreas.hansson@arm.com                    } else if (mode == "RANDOM") {
3499718Sandreas.hansson@arm.com                        states[id] = new RandomGen(name(), masterID,
3509241Sandreas.hansson@arm.com                                                   duration, start_addr,
3519241Sandreas.hansson@arm.com                                                   end_addr, blocksize,
3529241Sandreas.hansson@arm.com                                                   min_period, max_period,
3539241Sandreas.hansson@arm.com                                                   read_percent, data_limit);
3549241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
35510392Swendy.elsasser@arm.com                    } else if (mode == "DRAM" || mode == "DRAM_ROTATE") {
35610138Sneha.agarwal@arm.com                        // stride size (bytes) of the request for achieving
35710138Sneha.agarwal@arm.com                        // required hit length
35810138Sneha.agarwal@arm.com                        unsigned int stride_size;
35910138Sneha.agarwal@arm.com                        unsigned int page_size;
36010138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_DRAM;
36110138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_util;
36210138Sneha.agarwal@arm.com                        unsigned int addr_mapping;
36310392Swendy.elsasser@arm.com                        unsigned int nbr_of_ranks;
36410138Sneha.agarwal@arm.com
36510138Sneha.agarwal@arm.com                        is >> stride_size >> page_size >> nbr_of_banks_DRAM >>
36610392Swendy.elsasser@arm.com                            nbr_of_banks_util >> addr_mapping >>
36710392Swendy.elsasser@arm.com                            nbr_of_ranks;
36810138Sneha.agarwal@arm.com
36910138Sneha.agarwal@arm.com                        if (stride_size > page_size)
37010138Sneha.agarwal@arm.com                            warn("DRAM generator stride size (%d) is greater "
37110138Sneha.agarwal@arm.com                                 "than page size (%d)  of the memory\n",
37210138Sneha.agarwal@arm.com                                 blocksize, page_size);
37310138Sneha.agarwal@arm.com
37410138Sneha.agarwal@arm.com                        if (nbr_of_banks_util > nbr_of_banks_DRAM)
37510746Swendy.elsasser@arm.com                            fatal("Attempting to use more banks (%d) than "
37610746Swendy.elsasser@arm.com                                  "what is available (%d)\n",
37710138Sneha.agarwal@arm.com                                  nbr_of_banks_util, nbr_of_banks_DRAM);
37810138Sneha.agarwal@arm.com
37910138Sneha.agarwal@arm.com                        // count the number of sequential packets to
38010138Sneha.agarwal@arm.com                        // generate
38110138Sneha.agarwal@arm.com                        unsigned int num_seq_pkts = 1;
38210138Sneha.agarwal@arm.com
38310138Sneha.agarwal@arm.com                        if (stride_size > blocksize) {
38410138Sneha.agarwal@arm.com                            num_seq_pkts = divCeil(stride_size, blocksize);
38510138Sneha.agarwal@arm.com                            DPRINTF(TrafficGen, "stride size: %d "
38610138Sneha.agarwal@arm.com                                    "block size: %d, num_seq_pkts: %d\n",
38710138Sneha.agarwal@arm.com                                    stride_size, blocksize, num_seq_pkts);
38810138Sneha.agarwal@arm.com                        }
38910138Sneha.agarwal@arm.com
39010392Swendy.elsasser@arm.com                        if (mode == "DRAM") {
39110392Swendy.elsasser@arm.com                            states[id] = new DramGen(name(), masterID,
39210392Swendy.elsasser@arm.com                                                     duration, start_addr,
39310392Swendy.elsasser@arm.com                                                     end_addr, blocksize,
39410392Swendy.elsasser@arm.com                                                     min_period, max_period,
39510392Swendy.elsasser@arm.com                                                     read_percent, data_limit,
39610392Swendy.elsasser@arm.com                                                     num_seq_pkts, page_size,
39710392Swendy.elsasser@arm.com                                                     nbr_of_banks_DRAM,
39810392Swendy.elsasser@arm.com                                                     nbr_of_banks_util,
39910392Swendy.elsasser@arm.com                                                     addr_mapping,
40010392Swendy.elsasser@arm.com                                                     nbr_of_ranks);
40110392Swendy.elsasser@arm.com                            DPRINTF(TrafficGen, "State: %d DramGen\n", id);
40210392Swendy.elsasser@arm.com                        } else {
40310392Swendy.elsasser@arm.com                            // Will rotate to the next rank after rotating
40410392Swendy.elsasser@arm.com                            // through all banks, for each command type.
40510392Swendy.elsasser@arm.com                            // In the 50% read case, series will be issued
40610392Swendy.elsasser@arm.com                            // for both RD & WR before the rank in incremented
40710392Swendy.elsasser@arm.com                            unsigned int max_seq_count_per_rank =
40810392Swendy.elsasser@arm.com                                (read_percent == 50) ? nbr_of_banks_util * 2
40910392Swendy.elsasser@arm.com                                                     : nbr_of_banks_util;
41010392Swendy.elsasser@arm.com
41110392Swendy.elsasser@arm.com                            states[id] = new DramRotGen(name(), masterID,
41210392Swendy.elsasser@arm.com                                                     duration, start_addr,
41310392Swendy.elsasser@arm.com                                                     end_addr, blocksize,
41410392Swendy.elsasser@arm.com                                                     min_period, max_period,
41510392Swendy.elsasser@arm.com                                                     read_percent, data_limit,
41610392Swendy.elsasser@arm.com                                                     num_seq_pkts, page_size,
41710392Swendy.elsasser@arm.com                                                     nbr_of_banks_DRAM,
41810392Swendy.elsasser@arm.com                                                     nbr_of_banks_util,
41910392Swendy.elsasser@arm.com                                                     addr_mapping,
42010392Swendy.elsasser@arm.com                                                     nbr_of_ranks,
42110392Swendy.elsasser@arm.com                                                     max_seq_count_per_rank);
42210392Swendy.elsasser@arm.com                            DPRINTF(TrafficGen, "State: %d DramRotGen\n", id);
42310392Swendy.elsasser@arm.com                        }
4249241Sandreas.hansson@arm.com                    }
4259241Sandreas.hansson@arm.com                } else {
4269241Sandreas.hansson@arm.com                    fatal("%s: Unknown traffic generator mode: %s",
4279241Sandreas.hansson@arm.com                          name(), mode);
4289241Sandreas.hansson@arm.com                }
4299241Sandreas.hansson@arm.com            } else if (keyword == "TRANSITION") {
4309241Sandreas.hansson@arm.com                Transition transition;
4319241Sandreas.hansson@arm.com
4329241Sandreas.hansson@arm.com                is >> transition.from >> transition.to >> transition.p;
4339241Sandreas.hansson@arm.com
4349241Sandreas.hansson@arm.com                transitions.push_back(transition);
4359241Sandreas.hansson@arm.com
4369241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from,
4379241Sandreas.hansson@arm.com                        transition.to);
4389241Sandreas.hansson@arm.com            } else if (keyword == "INIT") {
4399241Sandreas.hansson@arm.com                // set the initial state as the active state
4409241Sandreas.hansson@arm.com                is >> currState;
4419241Sandreas.hansson@arm.com
44210128Sstan.czerniawski@arm.com                init_state_set = true;
44310128Sstan.czerniawski@arm.com
4449241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Initial state: %d\n", currState);
4459241Sandreas.hansson@arm.com            }
4469241Sandreas.hansson@arm.com        }
4479241Sandreas.hansson@arm.com    }
4489241Sandreas.hansson@arm.com
44910128Sstan.czerniawski@arm.com    if (!init_state_set)
45010128Sstan.czerniawski@arm.com        fatal("%s: initial state not specified (add 'INIT <id>' line "
45110128Sstan.czerniawski@arm.com              "to the config file)\n", name());
45210128Sstan.czerniawski@arm.com
4539241Sandreas.hansson@arm.com    // resize and populate state transition matrix
4549721Ssascha.bischoff@arm.com    transitionMatrix.resize(states.size());
4559721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
4569721Ssascha.bischoff@arm.com        transitionMatrix[i].resize(states.size());
4579241Sandreas.hansson@arm.com    }
4589241Sandreas.hansson@arm.com
4599241Sandreas.hansson@arm.com    for (vector<Transition>::iterator t = transitions.begin();
4609241Sandreas.hansson@arm.com         t != transitions.end(); ++t) {
4619241Sandreas.hansson@arm.com        transitionMatrix[t->from][t->to] = t->p;
4629241Sandreas.hansson@arm.com    }
4639241Sandreas.hansson@arm.com
4649241Sandreas.hansson@arm.com    // ensure the egress edges do not have a probability larger than
4659241Sandreas.hansson@arm.com    // one
4669721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
4679241Sandreas.hansson@arm.com        double sum = 0;
4689721Ssascha.bischoff@arm.com        for (size_t j = 0; j < states.size(); j++) {
4699241Sandreas.hansson@arm.com            sum += transitionMatrix[i][j];
4709241Sandreas.hansson@arm.com        }
4719241Sandreas.hansson@arm.com
4729241Sandreas.hansson@arm.com        // avoid comparing floating point numbers
4739241Sandreas.hansson@arm.com        if (abs(sum - 1.0) > 0.001)
4749241Sandreas.hansson@arm.com            fatal("%s has transition probability != 1 for state %d\n",
4759241Sandreas.hansson@arm.com                  name(), i);
4769241Sandreas.hansson@arm.com    }
4779241Sandreas.hansson@arm.com
4789241Sandreas.hansson@arm.com    // close input file
4799241Sandreas.hansson@arm.com    infile.close();
4809241Sandreas.hansson@arm.com}
4819241Sandreas.hansson@arm.com
4829241Sandreas.hansson@arm.comvoid
4839717Sandreas.hansson@arm.comTrafficGen::transition()
4849241Sandreas.hansson@arm.com{
4859241Sandreas.hansson@arm.com    // exit the current state
4869241Sandreas.hansson@arm.com    states[currState]->exit();
4879241Sandreas.hansson@arm.com
4889241Sandreas.hansson@arm.com    // determine next state
48910348Sandreas.hansson@arm.com    double p = random_mt.random<double>();
4909241Sandreas.hansson@arm.com    assert(currState < transitionMatrix.size());
4919584Sandreas@sandberg.pp.se    double cumulative = 0.0;
4929584Sandreas@sandberg.pp.se    size_t i = 0;
4939584Sandreas@sandberg.pp.se    do {
4949241Sandreas.hansson@arm.com        cumulative += transitionMatrix[currState][i];
4959241Sandreas.hansson@arm.com        ++i;
4969584Sandreas@sandberg.pp.se    } while (cumulative < p && i < transitionMatrix[currState].size());
4979584Sandreas@sandberg.pp.se
4989584Sandreas@sandberg.pp.se    enterState(i - 1);
4999241Sandreas.hansson@arm.com}
5009241Sandreas.hansson@arm.com
5019241Sandreas.hansson@arm.comvoid
5029717Sandreas.hansson@arm.comTrafficGen::enterState(uint32_t newState)
5039241Sandreas.hansson@arm.com{
5049241Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Transition to state %d\n", newState);
5059241Sandreas.hansson@arm.com
5069241Sandreas.hansson@arm.com    currState = newState;
5079719Sandreas.hansson@arm.com    // we could have been delayed and not transitioned on the exact
5089719Sandreas.hansson@arm.com    // tick when we were supposed to (due to back pressure when
5099719Sandreas.hansson@arm.com    // sending a packet)
5109719Sandreas.hansson@arm.com    nextTransitionTick = curTick() + states[currState]->duration;
5119241Sandreas.hansson@arm.com    states[currState]->enter();
5129241Sandreas.hansson@arm.com}
5139241Sandreas.hansson@arm.com
5149719Sandreas.hansson@arm.comvoid
51510713Sandreas.hansson@arm.comTrafficGen::recvReqRetry()
5169719Sandreas.hansson@arm.com{
5179719Sandreas.hansson@arm.com    assert(retryPkt != NULL);
5189719Sandreas.hansson@arm.com
5199719Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Received retry\n");
5209719Sandreas.hansson@arm.com    numRetries++;
5219719Sandreas.hansson@arm.com    // attempt to send the packet, and if we are successful start up
5229719Sandreas.hansson@arm.com    // the machinery again
5239719Sandreas.hansson@arm.com    if (port.sendTimingReq(retryPkt)) {
5249719Sandreas.hansson@arm.com        retryPkt = NULL;
5259719Sandreas.hansson@arm.com        // remember how much delay was incurred due to back-pressure
5269720Sandreas.hansson@arm.com        // when sending the request, we also use this to derive
5279720Sandreas.hansson@arm.com        // the tick for the next packet
5289719Sandreas.hansson@arm.com        Tick delay = curTick() - retryPktTick;
5299719Sandreas.hansson@arm.com        retryPktTick = 0;
5309719Sandreas.hansson@arm.com        retryTicks += delay;
5319719Sandreas.hansson@arm.com
53210913Sandreas.sandberg@arm.com        if (drainState() != DrainState::Draining) {
5339719Sandreas.hansson@arm.com            // packet is sent, so find out when the next one is due
5349720Sandreas.hansson@arm.com            nextPacketTick = states[currState]->nextPacketTick(elasticReq,
5359720Sandreas.hansson@arm.com                                                               delay);
5369719Sandreas.hansson@arm.com            Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
5379719Sandreas.hansson@arm.com            schedule(updateEvent, std::max(curTick(), nextEventTick));
5389719Sandreas.hansson@arm.com        } else {
5399719Sandreas.hansson@arm.com            // shut things down
5409719Sandreas.hansson@arm.com            nextPacketTick = MaxTick;
5419719Sandreas.hansson@arm.com            nextTransitionTick = MaxTick;
54210913Sandreas.sandberg@arm.com            signalDrainDone();
5439719Sandreas.hansson@arm.com        }
5449719Sandreas.hansson@arm.com    }
5459719Sandreas.hansson@arm.com}
5469719Sandreas.hansson@arm.com
5479719Sandreas.hansson@arm.comvoid
54811491Sandreas.hansson@arm.comTrafficGen::noProgress()
54911491Sandreas.hansson@arm.com{
55011491Sandreas.hansson@arm.com    fatal("TrafficGen %s spent %llu ticks without making progress",
55111491Sandreas.hansson@arm.com          name(), progressCheck);
55211491Sandreas.hansson@arm.com}
55311491Sandreas.hansson@arm.com
55411491Sandreas.hansson@arm.comvoid
5559719Sandreas.hansson@arm.comTrafficGen::regStats()
5569719Sandreas.hansson@arm.com{
55711522Sstephan.diestelhorst@arm.com    ClockedObject::regStats();
55811522Sstephan.diestelhorst@arm.com
5599719Sandreas.hansson@arm.com    // Initialise all the stats
5609719Sandreas.hansson@arm.com    using namespace Stats;
5619719Sandreas.hansson@arm.com
5629719Sandreas.hansson@arm.com    numPackets
5639719Sandreas.hansson@arm.com        .name(name() + ".numPackets")
5649719Sandreas.hansson@arm.com        .desc("Number of packets generated");
5659719Sandreas.hansson@arm.com
5669719Sandreas.hansson@arm.com    numRetries
5679719Sandreas.hansson@arm.com        .name(name() + ".numRetries")
5689719Sandreas.hansson@arm.com        .desc("Number of retries");
5699719Sandreas.hansson@arm.com
5709719Sandreas.hansson@arm.com    retryTicks
5719719Sandreas.hansson@arm.com        .name(name() + ".retryTicks")
5729719Sandreas.hansson@arm.com        .desc("Time spent waiting due to back-pressure (ticks)");
5739719Sandreas.hansson@arm.com}
5749719Sandreas.hansson@arm.com
5759241Sandreas.hansson@arm.combool
5769241Sandreas.hansson@arm.comTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
5779241Sandreas.hansson@arm.com{
5789241Sandreas.hansson@arm.com    delete pkt->req;
5799241Sandreas.hansson@arm.com    delete pkt;
5809241Sandreas.hansson@arm.com
5819241Sandreas.hansson@arm.com    return true;
5829241Sandreas.hansson@arm.com}
583