19241Sandreas.hansson@arm.com/*
212810Sandreas.sandberg@arm.com * Copyright (c) 2012-2013, 2016-2018 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
4612811Sandreas.sandberg@arm.com#include <fstream>
479241Sandreas.hansson@arm.com#include <sstream>
489241Sandreas.hansson@arm.com
4910138Sneha.agarwal@arm.com#include "base/intmath.hh"
509241Sandreas.hansson@arm.com#include "base/random.hh"
519241Sandreas.hansson@arm.com#include "debug/TrafficGen.hh"
5212810Sandreas.sandberg@arm.com#include "params/TrafficGen.hh"
539241Sandreas.hansson@arm.com#include "sim/stats.hh"
549241Sandreas.hansson@arm.com#include "sim/system.hh"
559241Sandreas.hansson@arm.com
569241Sandreas.hansson@arm.comusing namespace std;
579241Sandreas.hansson@arm.com
589241Sandreas.hansson@arm.comTrafficGen::TrafficGen(const TrafficGenParams* p)
5912810Sandreas.sandberg@arm.com    : BaseTrafficGen(p),
609718Sandreas.hansson@arm.com      configFile(p->config_file),
6112810Sandreas.sandberg@arm.com      currState(0)
629241Sandreas.hansson@arm.com{
639241Sandreas.hansson@arm.com}
649241Sandreas.hansson@arm.com
659241Sandreas.hansson@arm.comTrafficGen*
669241Sandreas.hansson@arm.comTrafficGenParams::create()
679241Sandreas.hansson@arm.com{
689241Sandreas.hansson@arm.com    return new TrafficGen(this);
699241Sandreas.hansson@arm.com}
709241Sandreas.hansson@arm.com
7112810Sandreas.sandberg@arm.comvoid
7212810Sandreas.sandberg@arm.comTrafficGen::init()
739241Sandreas.hansson@arm.com{
7412810Sandreas.sandberg@arm.com    BaseTrafficGen::init();
7512810Sandreas.sandberg@arm.com
7612810Sandreas.sandberg@arm.com    parseConfig();
779241Sandreas.hansson@arm.com}
789241Sandreas.hansson@arm.com
799241Sandreas.hansson@arm.comvoid
8012810Sandreas.sandberg@arm.comTrafficGen::initState()
819241Sandreas.hansson@arm.com{
8212810Sandreas.sandberg@arm.com    BaseTrafficGen::initState();
839241Sandreas.hansson@arm.com
8412810Sandreas.sandberg@arm.com    // when not restoring from a checkpoint, make sure we kick things off
859524SAndreas.Sandberg@ARM.com    if (system->isTimingMode()) {
869241Sandreas.hansson@arm.com        DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
8712810Sandreas.sandberg@arm.com        start();
889241Sandreas.hansson@arm.com    } else {
899241Sandreas.hansson@arm.com        DPRINTF(TrafficGen,
909241Sandreas.hansson@arm.com                "Traffic generator is only active in timing mode\n");
919241Sandreas.hansson@arm.com    }
929241Sandreas.hansson@arm.com}
939241Sandreas.hansson@arm.com
949241Sandreas.hansson@arm.comvoid
9510905Sandreas.sandberg@arm.comTrafficGen::serialize(CheckpointOut &cp) const
969241Sandreas.hansson@arm.com{
9712810Sandreas.sandberg@arm.com    SERIALIZE_SCALAR(currState);
989241Sandreas.hansson@arm.com
9912810Sandreas.sandberg@arm.com    BaseTrafficGen::serialize(cp);
1009241Sandreas.hansson@arm.com}
1019241Sandreas.hansson@arm.com
1029241Sandreas.hansson@arm.comvoid
10310905Sandreas.sandberg@arm.comTrafficGen::unserialize(CheckpointIn &cp)
1049241Sandreas.hansson@arm.com{
1059719Sandreas.hansson@arm.com    // @todo In the case of a stateful generator state such as the
1069719Sandreas.hansson@arm.com    // trace player we would also have to restore the position in the
1079720Sandreas.hansson@arm.com    // trace playback and the tick offset
1089719Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(currState);
1099241Sandreas.hansson@arm.com
11012810Sandreas.sandberg@arm.com    BaseTrafficGen::unserialize(cp);
1119241Sandreas.hansson@arm.com}
1129241Sandreas.hansson@arm.com
11311540Sandreas.sandberg@arm.comstd::string
11411540Sandreas.sandberg@arm.comTrafficGen::resolveFile(const std::string &name)
11511540Sandreas.sandberg@arm.com{
11611540Sandreas.sandberg@arm.com    // Do nothing for empty and absolute file names
11711540Sandreas.sandberg@arm.com    if (name.empty() || name[0] == '/')
11811540Sandreas.sandberg@arm.com        return name;
11911540Sandreas.sandberg@arm.com
12011540Sandreas.sandberg@arm.com    char *config_path = strdup(configFile.c_str());
12111540Sandreas.sandberg@arm.com    char *config_dir = dirname(config_path);
12211540Sandreas.sandberg@arm.com    const std::string config_rel = csprintf("%s/%s", config_dir, name);
12311540Sandreas.sandberg@arm.com    free(config_path);
12411540Sandreas.sandberg@arm.com
12511540Sandreas.sandberg@arm.com    // Check the path relative to the config file first
12611540Sandreas.sandberg@arm.com    if (access(config_rel.c_str(), R_OK) == 0)
12711540Sandreas.sandberg@arm.com        return config_rel;
12811540Sandreas.sandberg@arm.com
12911540Sandreas.sandberg@arm.com    // Fall back to the old behavior and search relative to the
13011540Sandreas.sandberg@arm.com    // current working directory.
13111540Sandreas.sandberg@arm.com    return name;
13211540Sandreas.sandberg@arm.com}
13311540Sandreas.sandberg@arm.com
1349241Sandreas.hansson@arm.comvoid
1359718Sandreas.hansson@arm.comTrafficGen::parseConfig()
1369241Sandreas.hansson@arm.com{
1379241Sandreas.hansson@arm.com    // keep track of the transitions parsed to create the matrix when
1389241Sandreas.hansson@arm.com    // done
1399241Sandreas.hansson@arm.com    vector<Transition> transitions;
1409241Sandreas.hansson@arm.com
1419241Sandreas.hansson@arm.com    // open input file
1429241Sandreas.hansson@arm.com    ifstream infile;
1439718Sandreas.hansson@arm.com    infile.open(configFile.c_str(), ifstream::in);
1449241Sandreas.hansson@arm.com    if (!infile.is_open()) {
1459241Sandreas.hansson@arm.com        fatal("Traffic generator %s config file not found at %s\n",
1469718Sandreas.hansson@arm.com              name(), configFile);
1479241Sandreas.hansson@arm.com    }
1489241Sandreas.hansson@arm.com
14910128Sstan.czerniawski@arm.com    bool init_state_set = false;
15010128Sstan.czerniawski@arm.com
1519241Sandreas.hansson@arm.com    // read line by line and determine the action based on the first
1529241Sandreas.hansson@arm.com    // keyword
1539241Sandreas.hansson@arm.com    string keyword;
1549241Sandreas.hansson@arm.com    string line;
1559241Sandreas.hansson@arm.com
1569241Sandreas.hansson@arm.com    while (getline(infile, line).good()) {
1579241Sandreas.hansson@arm.com        // see if this line is a comment line, and if so skip it
1589241Sandreas.hansson@arm.com        if (line.find('#') != 1) {
1599241Sandreas.hansson@arm.com            // create an input stream for the tokenization
1609241Sandreas.hansson@arm.com            istringstream is(line);
1619241Sandreas.hansson@arm.com
1629241Sandreas.hansson@arm.com            // determine the keyword
1639241Sandreas.hansson@arm.com            is >> keyword;
1649241Sandreas.hansson@arm.com
1659241Sandreas.hansson@arm.com            if (keyword == "STATE") {
1669241Sandreas.hansson@arm.com                // parse the behaviour of this state
1679241Sandreas.hansson@arm.com                uint32_t id;
1689241Sandreas.hansson@arm.com                Tick duration;
1699241Sandreas.hansson@arm.com                string mode;
1709241Sandreas.hansson@arm.com
1719241Sandreas.hansson@arm.com                is >> id >> duration >> mode;
1729241Sandreas.hansson@arm.com
1739241Sandreas.hansson@arm.com                if (mode == "TRACE") {
1749241Sandreas.hansson@arm.com                    string traceFile;
1759241Sandreas.hansson@arm.com                    Addr addrOffset;
1769241Sandreas.hansson@arm.com
1779241Sandreas.hansson@arm.com                    is >> traceFile >> addrOffset;
17811540Sandreas.sandberg@arm.com                    traceFile = resolveFile(traceFile);
1799241Sandreas.hansson@arm.com
18012811Sandreas.sandberg@arm.com                    states[id] = createTrace(duration, traceFile, addrOffset);
1819241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
1829241Sandreas.hansson@arm.com                } else if (mode == "IDLE") {
18312811Sandreas.sandberg@arm.com                    states[id] = createIdle(duration);
1849241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
18512397SRiken.Gohil@arm.com                } else if (mode == "EXIT") {
18612811Sandreas.sandberg@arm.com                    states[id] = createExit(duration);
18712397SRiken.Gohil@arm.com                    DPRINTF(TrafficGen, "State: %d ExitGen\n", id);
18810138Sneha.agarwal@arm.com                } else if (mode == "LINEAR" || mode == "RANDOM" ||
18910392Swendy.elsasser@arm.com                           mode == "DRAM"   || mode == "DRAM_ROTATE") {
1909241Sandreas.hansson@arm.com                    uint32_t read_percent;
1919241Sandreas.hansson@arm.com                    Addr start_addr;
1929241Sandreas.hansson@arm.com                    Addr end_addr;
1939241Sandreas.hansson@arm.com                    Addr blocksize;
1949241Sandreas.hansson@arm.com                    Tick min_period;
1959241Sandreas.hansson@arm.com                    Tick max_period;
1969241Sandreas.hansson@arm.com                    Addr data_limit;
1979241Sandreas.hansson@arm.com
1989241Sandreas.hansson@arm.com                    is >> read_percent >> start_addr >> end_addr >>
1999241Sandreas.hansson@arm.com                        blocksize >> min_period >> max_period >> data_limit;
2009241Sandreas.hansson@arm.com
2019241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "%s, addr %x to %x, size %d,"
2029241Sandreas.hansson@arm.com                            " period %d to %d, %d%% reads\n",
2039241Sandreas.hansson@arm.com                            mode, start_addr, end_addr, blocksize, min_period,
2049241Sandreas.hansson@arm.com                            max_period, read_percent);
2059241Sandreas.hansson@arm.com
2069718Sandreas.hansson@arm.com
2079241Sandreas.hansson@arm.com                    if (mode == "LINEAR") {
20812811Sandreas.sandberg@arm.com                        states[id] = createLinear(duration, start_addr,
20912811Sandreas.sandberg@arm.com                                                  end_addr, blocksize,
21012811Sandreas.sandberg@arm.com                                                  min_period, max_period,
21112811Sandreas.sandberg@arm.com                                                  read_percent, data_limit);
2129241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
2139241Sandreas.hansson@arm.com                    } else if (mode == "RANDOM") {
21412811Sandreas.sandberg@arm.com                        states[id] = createRandom(duration, start_addr,
21512811Sandreas.sandberg@arm.com                                                  end_addr, blocksize,
21612811Sandreas.sandberg@arm.com                                                  min_period, max_period,
21712811Sandreas.sandberg@arm.com                                                  read_percent, data_limit);
2189241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
21910392Swendy.elsasser@arm.com                    } else if (mode == "DRAM" || mode == "DRAM_ROTATE") {
22010138Sneha.agarwal@arm.com                        // stride size (bytes) of the request for achieving
22110138Sneha.agarwal@arm.com                        // required hit length
22210138Sneha.agarwal@arm.com                        unsigned int stride_size;
22310138Sneha.agarwal@arm.com                        unsigned int page_size;
22410138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_DRAM;
22510138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_util;
22610138Sneha.agarwal@arm.com                        unsigned int addr_mapping;
22710392Swendy.elsasser@arm.com                        unsigned int nbr_of_ranks;
22810138Sneha.agarwal@arm.com
22910138Sneha.agarwal@arm.com                        is >> stride_size >> page_size >> nbr_of_banks_DRAM >>
23010392Swendy.elsasser@arm.com                            nbr_of_banks_util >> addr_mapping >>
23110392Swendy.elsasser@arm.com                            nbr_of_ranks;
23210138Sneha.agarwal@arm.com
23310138Sneha.agarwal@arm.com                        if (stride_size > page_size)
23410138Sneha.agarwal@arm.com                            warn("DRAM generator stride size (%d) is greater "
23510138Sneha.agarwal@arm.com                                 "than page size (%d)  of the memory\n",
23610138Sneha.agarwal@arm.com                                 blocksize, page_size);
23710138Sneha.agarwal@arm.com
23810138Sneha.agarwal@arm.com                        // count the number of sequential packets to
23910138Sneha.agarwal@arm.com                        // generate
24010138Sneha.agarwal@arm.com                        unsigned int num_seq_pkts = 1;
24110138Sneha.agarwal@arm.com
24210138Sneha.agarwal@arm.com                        if (stride_size > blocksize) {
24310138Sneha.agarwal@arm.com                            num_seq_pkts = divCeil(stride_size, blocksize);
24410138Sneha.agarwal@arm.com                            DPRINTF(TrafficGen, "stride size: %d "
24510138Sneha.agarwal@arm.com                                    "block size: %d, num_seq_pkts: %d\n",
24610138Sneha.agarwal@arm.com                                    stride_size, blocksize, num_seq_pkts);
24710138Sneha.agarwal@arm.com                        }
24810138Sneha.agarwal@arm.com
24910392Swendy.elsasser@arm.com                        if (mode == "DRAM") {
25012811Sandreas.sandberg@arm.com                            states[id] = createDram(duration, start_addr,
25112811Sandreas.sandberg@arm.com                                                    end_addr, blocksize,
25212811Sandreas.sandberg@arm.com                                                    min_period, max_period,
25312811Sandreas.sandberg@arm.com                                                    read_percent, data_limit,
25412811Sandreas.sandberg@arm.com                                                    num_seq_pkts, page_size,
25512811Sandreas.sandberg@arm.com                                                    nbr_of_banks_DRAM,
25612811Sandreas.sandberg@arm.com                                                    nbr_of_banks_util,
25712811Sandreas.sandberg@arm.com                                                    addr_mapping,
25812811Sandreas.sandberg@arm.com                                                    nbr_of_ranks);
25910392Swendy.elsasser@arm.com                            DPRINTF(TrafficGen, "State: %d DramGen\n", id);
26010392Swendy.elsasser@arm.com                        } else {
26110392Swendy.elsasser@arm.com                            // Will rotate to the next rank after rotating
26210392Swendy.elsasser@arm.com                            // through all banks, for each command type.
26310392Swendy.elsasser@arm.com                            // In the 50% read case, series will be issued
26410392Swendy.elsasser@arm.com                            // for both RD & WR before the rank in incremented
26510392Swendy.elsasser@arm.com                            unsigned int max_seq_count_per_rank =
26610392Swendy.elsasser@arm.com                                (read_percent == 50) ? nbr_of_banks_util * 2
26710392Swendy.elsasser@arm.com                                                     : nbr_of_banks_util;
26810392Swendy.elsasser@arm.com
26912811Sandreas.sandberg@arm.com                            states[id] = createDramRot(duration, start_addr,
27012811Sandreas.sandberg@arm.com                                                       end_addr, blocksize,
27112811Sandreas.sandberg@arm.com                                                       min_period, max_period,
27212811Sandreas.sandberg@arm.com                                                       read_percent,
27312811Sandreas.sandberg@arm.com                                                       data_limit,
27412811Sandreas.sandberg@arm.com                                                       num_seq_pkts, page_size,
27512811Sandreas.sandberg@arm.com                                                       nbr_of_banks_DRAM,
27612811Sandreas.sandberg@arm.com                                                       nbr_of_banks_util,
27712811Sandreas.sandberg@arm.com                                                       addr_mapping,
27812811Sandreas.sandberg@arm.com                                                       nbr_of_ranks,
27912811Sandreas.sandberg@arm.com                                                       max_seq_count_per_rank);
28010392Swendy.elsasser@arm.com                            DPRINTF(TrafficGen, "State: %d DramRotGen\n", id);
28110392Swendy.elsasser@arm.com                        }
2829241Sandreas.hansson@arm.com                    }
2839241Sandreas.hansson@arm.com                } else {
2849241Sandreas.hansson@arm.com                    fatal("%s: Unknown traffic generator mode: %s",
2859241Sandreas.hansson@arm.com                          name(), mode);
2869241Sandreas.hansson@arm.com                }
2879241Sandreas.hansson@arm.com            } else if (keyword == "TRANSITION") {
2889241Sandreas.hansson@arm.com                Transition transition;
2899241Sandreas.hansson@arm.com
2909241Sandreas.hansson@arm.com                is >> transition.from >> transition.to >> transition.p;
2919241Sandreas.hansson@arm.com
2929241Sandreas.hansson@arm.com                transitions.push_back(transition);
2939241Sandreas.hansson@arm.com
2949241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from,
2959241Sandreas.hansson@arm.com                        transition.to);
2969241Sandreas.hansson@arm.com            } else if (keyword == "INIT") {
2979241Sandreas.hansson@arm.com                // set the initial state as the active state
2989241Sandreas.hansson@arm.com                is >> currState;
2999241Sandreas.hansson@arm.com
30010128Sstan.czerniawski@arm.com                init_state_set = true;
30110128Sstan.czerniawski@arm.com
3029241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Initial state: %d\n", currState);
3039241Sandreas.hansson@arm.com            }
3049241Sandreas.hansson@arm.com        }
3059241Sandreas.hansson@arm.com    }
3069241Sandreas.hansson@arm.com
30710128Sstan.czerniawski@arm.com    if (!init_state_set)
30810128Sstan.czerniawski@arm.com        fatal("%s: initial state not specified (add 'INIT <id>' line "
30910128Sstan.czerniawski@arm.com              "to the config file)\n", name());
31010128Sstan.czerniawski@arm.com
3119241Sandreas.hansson@arm.com    // resize and populate state transition matrix
3129721Ssascha.bischoff@arm.com    transitionMatrix.resize(states.size());
3139721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
3149721Ssascha.bischoff@arm.com        transitionMatrix[i].resize(states.size());
3159241Sandreas.hansson@arm.com    }
3169241Sandreas.hansson@arm.com
3179241Sandreas.hansson@arm.com    for (vector<Transition>::iterator t = transitions.begin();
3189241Sandreas.hansson@arm.com         t != transitions.end(); ++t) {
3199241Sandreas.hansson@arm.com        transitionMatrix[t->from][t->to] = t->p;
3209241Sandreas.hansson@arm.com    }
3219241Sandreas.hansson@arm.com
3229241Sandreas.hansson@arm.com    // ensure the egress edges do not have a probability larger than
3239241Sandreas.hansson@arm.com    // one
3249721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
3259241Sandreas.hansson@arm.com        double sum = 0;
3269721Ssascha.bischoff@arm.com        for (size_t j = 0; j < states.size(); j++) {
3279241Sandreas.hansson@arm.com            sum += transitionMatrix[i][j];
3289241Sandreas.hansson@arm.com        }
3299241Sandreas.hansson@arm.com
3309241Sandreas.hansson@arm.com        // avoid comparing floating point numbers
3319241Sandreas.hansson@arm.com        if (abs(sum - 1.0) > 0.001)
3329241Sandreas.hansson@arm.com            fatal("%s has transition probability != 1 for state %d\n",
3339241Sandreas.hansson@arm.com                  name(), i);
3349241Sandreas.hansson@arm.com    }
3359241Sandreas.hansson@arm.com
3369241Sandreas.hansson@arm.com    // close input file
3379241Sandreas.hansson@arm.com    infile.close();
3389241Sandreas.hansson@arm.com}
3399241Sandreas.hansson@arm.com
34012810Sandreas.sandberg@arm.comsize_t
34112810Sandreas.sandberg@arm.comTrafficGen::nextState()
3429241Sandreas.hansson@arm.com{
34310348Sandreas.hansson@arm.com    double p = random_mt.random<double>();
3449241Sandreas.hansson@arm.com    assert(currState < transitionMatrix.size());
3459584Sandreas@sandberg.pp.se    double cumulative = 0.0;
3469584Sandreas@sandberg.pp.se    size_t i = 0;
3479584Sandreas@sandberg.pp.se    do {
3489241Sandreas.hansson@arm.com        cumulative += transitionMatrix[currState][i];
3499241Sandreas.hansson@arm.com        ++i;
3509584Sandreas@sandberg.pp.se    } while (cumulative < p && i < transitionMatrix[currState].size());
3519584Sandreas@sandberg.pp.se
35212810Sandreas.sandberg@arm.com    return i - 1;
3539241Sandreas.hansson@arm.com}
3549241Sandreas.hansson@arm.com
35512810Sandreas.sandberg@arm.comstd::shared_ptr<BaseGen>
35612810Sandreas.sandberg@arm.comTrafficGen::nextGenerator()
3579241Sandreas.hansson@arm.com{
35812810Sandreas.sandberg@arm.com    // Return the initial state if there isn't an active generator,
35912810Sandreas.sandberg@arm.com    // otherwise perform a state transition.
36012810Sandreas.sandberg@arm.com    if (activeGenerator)
36112810Sandreas.sandberg@arm.com        currState = nextState();
3629241Sandreas.hansson@arm.com
36312810Sandreas.sandberg@arm.com    DPRINTF(TrafficGen, "Transition to state %d\n", currState);
36412810Sandreas.sandberg@arm.com    return states[currState];
3659241Sandreas.hansson@arm.com}
366