traffic_gen.cc revision 10138
19241Sandreas.hansson@arm.com/*
29717Sandreas.hansson@arm.com * Copyright (c) 2012-2013 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 */
419241Sandreas.hansson@arm.com
429241Sandreas.hansson@arm.com#include <sstream>
439241Sandreas.hansson@arm.com
4410138Sneha.agarwal@arm.com#include "base/intmath.hh"
459241Sandreas.hansson@arm.com#include "base/random.hh"
469241Sandreas.hansson@arm.com#include "cpu/testers/traffic_gen/traffic_gen.hh"
479241Sandreas.hansson@arm.com#include "debug/Checkpoint.hh"
489241Sandreas.hansson@arm.com#include "debug/TrafficGen.hh"
499241Sandreas.hansson@arm.com#include "sim/stats.hh"
509241Sandreas.hansson@arm.com#include "sim/system.hh"
519241Sandreas.hansson@arm.com
529241Sandreas.hansson@arm.comusing namespace std;
539241Sandreas.hansson@arm.com
549241Sandreas.hansson@arm.comTrafficGen::TrafficGen(const TrafficGenParams* p)
559241Sandreas.hansson@arm.com    : MemObject(p),
569241Sandreas.hansson@arm.com      system(p->system),
579241Sandreas.hansson@arm.com      masterID(system->getMasterId(name())),
589718Sandreas.hansson@arm.com      configFile(p->config_file),
599720Sandreas.hansson@arm.com      elasticReq(p->elastic_req),
609717Sandreas.hansson@arm.com      nextTransitionTick(0),
619719Sandreas.hansson@arm.com      nextPacketTick(0),
629241Sandreas.hansson@arm.com      port(name() + ".port", *this),
639719Sandreas.hansson@arm.com      retryPkt(NULL),
649719Sandreas.hansson@arm.com      retryPktTick(0),
659719Sandreas.hansson@arm.com      updateEvent(this),
669719Sandreas.hansson@arm.com      drainManager(NULL)
679241Sandreas.hansson@arm.com{
689241Sandreas.hansson@arm.com}
699241Sandreas.hansson@arm.com
709241Sandreas.hansson@arm.comTrafficGen*
719241Sandreas.hansson@arm.comTrafficGenParams::create()
729241Sandreas.hansson@arm.com{
739241Sandreas.hansson@arm.com    return new TrafficGen(this);
749241Sandreas.hansson@arm.com}
759241Sandreas.hansson@arm.com
769294Sandreas.hansson@arm.comBaseMasterPort&
779294Sandreas.hansson@arm.comTrafficGen::getMasterPort(const string& if_name, PortID idx)
789241Sandreas.hansson@arm.com{
799241Sandreas.hansson@arm.com    if (if_name == "port") {
809241Sandreas.hansson@arm.com        return port;
819241Sandreas.hansson@arm.com    } else {
829241Sandreas.hansson@arm.com        return MemObject::getMasterPort(if_name, idx);
839241Sandreas.hansson@arm.com    }
849241Sandreas.hansson@arm.com}
859241Sandreas.hansson@arm.com
869241Sandreas.hansson@arm.comvoid
879241Sandreas.hansson@arm.comTrafficGen::init()
889241Sandreas.hansson@arm.com{
899241Sandreas.hansson@arm.com    if (!port.isConnected())
909241Sandreas.hansson@arm.com        fatal("The port of %s is not connected!\n", name());
919241Sandreas.hansson@arm.com
929241Sandreas.hansson@arm.com    // if the system is in timing mode active the request generator
939524SAndreas.Sandberg@ARM.com    if (system->isTimingMode()) {
949241Sandreas.hansson@arm.com        DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
959241Sandreas.hansson@arm.com
969718Sandreas.hansson@arm.com        parseConfig();
979718Sandreas.hansson@arm.com
989241Sandreas.hansson@arm.com        // enter initial state
999717Sandreas.hansson@arm.com        enterState(currState);
1009241Sandreas.hansson@arm.com    } else {
1019241Sandreas.hansson@arm.com        DPRINTF(TrafficGen,
1029241Sandreas.hansson@arm.com                "Traffic generator is only active in timing mode\n");
1039241Sandreas.hansson@arm.com    }
1049241Sandreas.hansson@arm.com}
1059241Sandreas.hansson@arm.com
1069241Sandreas.hansson@arm.comvoid
1079241Sandreas.hansson@arm.comTrafficGen::initState()
1089241Sandreas.hansson@arm.com{
1099241Sandreas.hansson@arm.com    // when not restoring from a checkpoint, make sure we kick things off
1109524SAndreas.Sandberg@ARM.com    if (system->isTimingMode()) {
1119719Sandreas.hansson@arm.com        // call nextPacketTick on the state to advance it
1129720Sandreas.hansson@arm.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
1139719Sandreas.hansson@arm.com        schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick));
1149241Sandreas.hansson@arm.com    } else {
1159241Sandreas.hansson@arm.com        DPRINTF(TrafficGen,
1169241Sandreas.hansson@arm.com                "Traffic generator is only active in timing mode\n");
1179241Sandreas.hansson@arm.com    }
1189241Sandreas.hansson@arm.com}
1199241Sandreas.hansson@arm.com
1209241Sandreas.hansson@arm.comunsigned int
1219342SAndreas.Sandberg@arm.comTrafficGen::drain(DrainManager *dm)
1229241Sandreas.hansson@arm.com{
12310051Srioshering@gmail.com    if (!updateEvent.scheduled()) {
12410051Srioshering@gmail.com        // no event has been scheduled yet (e.g. switched from atomic mode)
12510051Srioshering@gmail.com        return 0;
12610051Srioshering@gmail.com    }
12710051Srioshering@gmail.com
1289719Sandreas.hansson@arm.com    if (retryPkt == NULL) {
1299719Sandreas.hansson@arm.com        // shut things down
1309719Sandreas.hansson@arm.com        nextPacketTick = MaxTick;
1319719Sandreas.hansson@arm.com        nextTransitionTick = MaxTick;
1329719Sandreas.hansson@arm.com        deschedule(updateEvent);
1339719Sandreas.hansson@arm.com        return 0;
1349719Sandreas.hansson@arm.com    } else {
1359719Sandreas.hansson@arm.com        drainManager = dm;
1369719Sandreas.hansson@arm.com        return 1;
1379719Sandreas.hansson@arm.com    }
1389241Sandreas.hansson@arm.com}
1399241Sandreas.hansson@arm.com
1409241Sandreas.hansson@arm.comvoid
1419241Sandreas.hansson@arm.comTrafficGen::serialize(ostream &os)
1429241Sandreas.hansson@arm.com{
1439241Sandreas.hansson@arm.com    DPRINTF(Checkpoint, "Serializing TrafficGen\n");
1449241Sandreas.hansson@arm.com
1459241Sandreas.hansson@arm.com    // save ticks of the graph event if it is scheduled
1469719Sandreas.hansson@arm.com    Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;
1479241Sandreas.hansson@arm.com
1489719Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);
1499241Sandreas.hansson@arm.com
1509717Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextEvent);
1519241Sandreas.hansson@arm.com
1529241Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextTransitionTick);
1539241Sandreas.hansson@arm.com
1549719Sandreas.hansson@arm.com    SERIALIZE_SCALAR(nextPacketTick);
1559719Sandreas.hansson@arm.com
1569719Sandreas.hansson@arm.com    SERIALIZE_SCALAR(currState);
1579241Sandreas.hansson@arm.com}
1589241Sandreas.hansson@arm.com
1599241Sandreas.hansson@arm.comvoid
1609241Sandreas.hansson@arm.comTrafficGen::unserialize(Checkpoint* cp, const string& section)
1619241Sandreas.hansson@arm.com{
1629241Sandreas.hansson@arm.com    // restore scheduled events
1639717Sandreas.hansson@arm.com    Tick nextEvent;
1649717Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextEvent);
1659717Sandreas.hansson@arm.com    if (nextEvent != 0) {
1669717Sandreas.hansson@arm.com        schedule(updateEvent, nextEvent);
1679241Sandreas.hansson@arm.com    }
1689241Sandreas.hansson@arm.com
1699241Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextTransitionTick);
1709719Sandreas.hansson@arm.com
1719719Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(nextPacketTick);
1729719Sandreas.hansson@arm.com
1739719Sandreas.hansson@arm.com    // @todo In the case of a stateful generator state such as the
1749719Sandreas.hansson@arm.com    // trace player we would also have to restore the position in the
1759720Sandreas.hansson@arm.com    // trace playback and the tick offset
1769719Sandreas.hansson@arm.com    UNSERIALIZE_SCALAR(currState);
1779241Sandreas.hansson@arm.com}
1789241Sandreas.hansson@arm.com
1799241Sandreas.hansson@arm.comvoid
1809717Sandreas.hansson@arm.comTrafficGen::update()
1819241Sandreas.hansson@arm.com{
1829717Sandreas.hansson@arm.com    // if we have reached the time for the next state transition, then
1839717Sandreas.hansson@arm.com    // perform the transition
1849717Sandreas.hansson@arm.com    if (curTick() >= nextTransitionTick) {
1859717Sandreas.hansson@arm.com        transition();
1869717Sandreas.hansson@arm.com    } else {
1879719Sandreas.hansson@arm.com        assert(curTick() >= nextPacketTick);
1889719Sandreas.hansson@arm.com        // get the next packet and try to send it
1899718Sandreas.hansson@arm.com        PacketPtr pkt = states[currState]->getNextPacket();
1909719Sandreas.hansson@arm.com        numPackets++;
1919719Sandreas.hansson@arm.com        if (!port.sendTimingReq(pkt)) {
1929719Sandreas.hansson@arm.com            retryPkt = pkt;
1939719Sandreas.hansson@arm.com            retryPktTick = curTick();
1949719Sandreas.hansson@arm.com        }
1959719Sandreas.hansson@arm.com    }
1969719Sandreas.hansson@arm.com
1979719Sandreas.hansson@arm.com    // if we are waiting for a retry, do not schedule any further
1989719Sandreas.hansson@arm.com    // events, in the case of a transition or a successful send, go
1999719Sandreas.hansson@arm.com    // ahead and determine when the next update should take place
2009719Sandreas.hansson@arm.com    if (retryPkt == NULL) {
2019719Sandreas.hansson@arm.com        // schedule next update event based on either the next execute
2029719Sandreas.hansson@arm.com        // tick or the next transition, which ever comes first
2039720Sandreas.hansson@arm.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
2049719Sandreas.hansson@arm.com        Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
2059719Sandreas.hansson@arm.com        DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
2069719Sandreas.hansson@arm.com        schedule(updateEvent, nextEventTick);
2079717Sandreas.hansson@arm.com    }
2089241Sandreas.hansson@arm.com}
2099241Sandreas.hansson@arm.com
2109241Sandreas.hansson@arm.comvoid
2119718Sandreas.hansson@arm.comTrafficGen::parseConfig()
2129241Sandreas.hansson@arm.com{
2139241Sandreas.hansson@arm.com    // keep track of the transitions parsed to create the matrix when
2149241Sandreas.hansson@arm.com    // done
2159241Sandreas.hansson@arm.com    vector<Transition> transitions;
2169241Sandreas.hansson@arm.com
2179241Sandreas.hansson@arm.com    // open input file
2189241Sandreas.hansson@arm.com    ifstream infile;
2199718Sandreas.hansson@arm.com    infile.open(configFile.c_str(), ifstream::in);
2209241Sandreas.hansson@arm.com    if (!infile.is_open()) {
2219241Sandreas.hansson@arm.com        fatal("Traffic generator %s config file not found at %s\n",
2229718Sandreas.hansson@arm.com              name(), configFile);
2239241Sandreas.hansson@arm.com    }
2249241Sandreas.hansson@arm.com
22510128Sstan.czerniawski@arm.com    bool init_state_set = false;
22610128Sstan.czerniawski@arm.com
2279241Sandreas.hansson@arm.com    // read line by line and determine the action based on the first
2289241Sandreas.hansson@arm.com    // keyword
2299241Sandreas.hansson@arm.com    string keyword;
2309241Sandreas.hansson@arm.com    string line;
2319241Sandreas.hansson@arm.com
2329241Sandreas.hansson@arm.com    while (getline(infile, line).good()) {
2339241Sandreas.hansson@arm.com        // see if this line is a comment line, and if so skip it
2349241Sandreas.hansson@arm.com        if (line.find('#') != 1) {
2359241Sandreas.hansson@arm.com            // create an input stream for the tokenization
2369241Sandreas.hansson@arm.com            istringstream is(line);
2379241Sandreas.hansson@arm.com
2389241Sandreas.hansson@arm.com            // determine the keyword
2399241Sandreas.hansson@arm.com            is >> keyword;
2409241Sandreas.hansson@arm.com
2419241Sandreas.hansson@arm.com            if (keyword == "STATE") {
2429241Sandreas.hansson@arm.com                // parse the behaviour of this state
2439241Sandreas.hansson@arm.com                uint32_t id;
2449241Sandreas.hansson@arm.com                Tick duration;
2459241Sandreas.hansson@arm.com                string mode;
2469241Sandreas.hansson@arm.com
2479241Sandreas.hansson@arm.com                is >> id >> duration >> mode;
2489241Sandreas.hansson@arm.com
2499241Sandreas.hansson@arm.com                if (mode == "TRACE") {
2509241Sandreas.hansson@arm.com                    string traceFile;
2519241Sandreas.hansson@arm.com                    Addr addrOffset;
2529241Sandreas.hansson@arm.com
2539241Sandreas.hansson@arm.com                    is >> traceFile >> addrOffset;
2549241Sandreas.hansson@arm.com
2559718Sandreas.hansson@arm.com                    states[id] = new TraceGen(name(), masterID, duration,
2569241Sandreas.hansson@arm.com                                              traceFile, addrOffset);
2579241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
2589241Sandreas.hansson@arm.com                } else if (mode == "IDLE") {
2599718Sandreas.hansson@arm.com                    states[id] = new IdleGen(name(), masterID, duration);
2609241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
26110138Sneha.agarwal@arm.com                } else if (mode == "LINEAR" || mode == "RANDOM" ||
26210138Sneha.agarwal@arm.com                           mode == "DRAM") {
2639241Sandreas.hansson@arm.com                    uint32_t read_percent;
2649241Sandreas.hansson@arm.com                    Addr start_addr;
2659241Sandreas.hansson@arm.com                    Addr end_addr;
2669241Sandreas.hansson@arm.com                    Addr blocksize;
2679241Sandreas.hansson@arm.com                    Tick min_period;
2689241Sandreas.hansson@arm.com                    Tick max_period;
2699241Sandreas.hansson@arm.com                    Addr data_limit;
2709241Sandreas.hansson@arm.com
2719241Sandreas.hansson@arm.com                    is >> read_percent >> start_addr >> end_addr >>
2729241Sandreas.hansson@arm.com                        blocksize >> min_period >> max_period >> data_limit;
2739241Sandreas.hansson@arm.com
2749241Sandreas.hansson@arm.com                    DPRINTF(TrafficGen, "%s, addr %x to %x, size %d,"
2759241Sandreas.hansson@arm.com                            " period %d to %d, %d%% reads\n",
2769241Sandreas.hansson@arm.com                            mode, start_addr, end_addr, blocksize, min_period,
2779241Sandreas.hansson@arm.com                            max_period, read_percent);
2789241Sandreas.hansson@arm.com
2799718Sandreas.hansson@arm.com
2809814Sandreas.hansson@arm.com                    if (blocksize > system->cacheLineSize())
2819718Sandreas.hansson@arm.com                        fatal("TrafficGen %s block size (%d) is larger than "
28210138Sneha.agarwal@arm.com                              "cache line size (%d)\n", name(),
2839814Sandreas.hansson@arm.com                              blocksize, system->cacheLineSize());
2849718Sandreas.hansson@arm.com
2859241Sandreas.hansson@arm.com                    if (read_percent > 100)
2869718Sandreas.hansson@arm.com                        fatal("%s cannot have more than 100% reads", name());
2879241Sandreas.hansson@arm.com
2889722Ssascha.bischoff@arm.com                    if (min_period > max_period)
2899722Ssascha.bischoff@arm.com                        fatal("%s cannot have min_period > max_period", name());
2909722Ssascha.bischoff@arm.com
2919241Sandreas.hansson@arm.com                    if (mode == "LINEAR") {
2929718Sandreas.hansson@arm.com                        states[id] = new LinearGen(name(), masterID,
2939241Sandreas.hansson@arm.com                                                   duration, start_addr,
2949241Sandreas.hansson@arm.com                                                   end_addr, blocksize,
2959241Sandreas.hansson@arm.com                                                   min_period, max_period,
2969241Sandreas.hansson@arm.com                                                   read_percent, data_limit);
2979241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
2989241Sandreas.hansson@arm.com                    } else if (mode == "RANDOM") {
2999718Sandreas.hansson@arm.com                        states[id] = new RandomGen(name(), masterID,
3009241Sandreas.hansson@arm.com                                                   duration, start_addr,
3019241Sandreas.hansson@arm.com                                                   end_addr, blocksize,
3029241Sandreas.hansson@arm.com                                                   min_period, max_period,
3039241Sandreas.hansson@arm.com                                                   read_percent, data_limit);
3049241Sandreas.hansson@arm.com                        DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
30510138Sneha.agarwal@arm.com                    } else if (mode == "DRAM") {
30610138Sneha.agarwal@arm.com                        // stride size (bytes) of the request for achieving
30710138Sneha.agarwal@arm.com                        // required hit length
30810138Sneha.agarwal@arm.com                        unsigned int stride_size;
30910138Sneha.agarwal@arm.com                        unsigned int page_size;
31010138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_DRAM;
31110138Sneha.agarwal@arm.com                        unsigned int nbr_of_banks_util;
31210138Sneha.agarwal@arm.com                        unsigned int addr_mapping;
31310138Sneha.agarwal@arm.com
31410138Sneha.agarwal@arm.com                        is >> stride_size >> page_size >> nbr_of_banks_DRAM >>
31510138Sneha.agarwal@arm.com                            nbr_of_banks_util >> addr_mapping;
31610138Sneha.agarwal@arm.com
31710138Sneha.agarwal@arm.com                        if (stride_size > page_size)
31810138Sneha.agarwal@arm.com                            warn("DRAM generator stride size (%d) is greater "
31910138Sneha.agarwal@arm.com                                 "than page size (%d)  of the memory\n",
32010138Sneha.agarwal@arm.com                                 blocksize, page_size);
32110138Sneha.agarwal@arm.com
32210138Sneha.agarwal@arm.com                        if (nbr_of_banks_util > nbr_of_banks_DRAM)
32310138Sneha.agarwal@arm.com                            fatal("Attempting to use more banks (%) than "
32410138Sneha.agarwal@arm.com                                  "what is available (%)\n",
32510138Sneha.agarwal@arm.com                                  nbr_of_banks_util, nbr_of_banks_DRAM);
32610138Sneha.agarwal@arm.com
32710138Sneha.agarwal@arm.com                        if (nbr_of_banks_util > nbr_of_banks_DRAM)
32810138Sneha.agarwal@arm.com                            fatal("Attempting to use more banks (%) than "
32910138Sneha.agarwal@arm.com                                  "what is available (%)\n",
33010138Sneha.agarwal@arm.com                                  nbr_of_banks_util, nbr_of_banks_DRAM);
33110138Sneha.agarwal@arm.com
33210138Sneha.agarwal@arm.com                        // count the number of sequential packets to
33310138Sneha.agarwal@arm.com                        // generate
33410138Sneha.agarwal@arm.com                        unsigned int num_seq_pkts = 1;
33510138Sneha.agarwal@arm.com
33610138Sneha.agarwal@arm.com                        if (stride_size > blocksize) {
33710138Sneha.agarwal@arm.com                            num_seq_pkts = divCeil(stride_size, blocksize);
33810138Sneha.agarwal@arm.com                            DPRINTF(TrafficGen, "stride size: %d "
33910138Sneha.agarwal@arm.com                                    "block size: %d, num_seq_pkts: %d\n",
34010138Sneha.agarwal@arm.com                                    stride_size, blocksize, num_seq_pkts);
34110138Sneha.agarwal@arm.com                        }
34210138Sneha.agarwal@arm.com
34310138Sneha.agarwal@arm.com                        states[id] = new DramGen(name(), masterID,
34410138Sneha.agarwal@arm.com                                                 duration, start_addr,
34510138Sneha.agarwal@arm.com                                                 end_addr, blocksize,
34610138Sneha.agarwal@arm.com                                                 min_period, max_period,
34710138Sneha.agarwal@arm.com                                                 read_percent, data_limit,
34810138Sneha.agarwal@arm.com                                                 num_seq_pkts, page_size,
34910138Sneha.agarwal@arm.com                                                 nbr_of_banks_DRAM,
35010138Sneha.agarwal@arm.com                                                 nbr_of_banks_util,
35110138Sneha.agarwal@arm.com                                                 addr_mapping);
35210138Sneha.agarwal@arm.com                        DPRINTF(TrafficGen, "State: %d DramGen\n", id);
3539241Sandreas.hansson@arm.com                    }
3549241Sandreas.hansson@arm.com                } else {
3559241Sandreas.hansson@arm.com                    fatal("%s: Unknown traffic generator mode: %s",
3569241Sandreas.hansson@arm.com                          name(), mode);
3579241Sandreas.hansson@arm.com                }
3589241Sandreas.hansson@arm.com            } else if (keyword == "TRANSITION") {
3599241Sandreas.hansson@arm.com                Transition transition;
3609241Sandreas.hansson@arm.com
3619241Sandreas.hansson@arm.com                is >> transition.from >> transition.to >> transition.p;
3629241Sandreas.hansson@arm.com
3639241Sandreas.hansson@arm.com                transitions.push_back(transition);
3649241Sandreas.hansson@arm.com
3659241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from,
3669241Sandreas.hansson@arm.com                        transition.to);
3679241Sandreas.hansson@arm.com            } else if (keyword == "INIT") {
3689241Sandreas.hansson@arm.com                // set the initial state as the active state
3699241Sandreas.hansson@arm.com                is >> currState;
3709241Sandreas.hansson@arm.com
37110128Sstan.czerniawski@arm.com                init_state_set = true;
37210128Sstan.czerniawski@arm.com
3739241Sandreas.hansson@arm.com                DPRINTF(TrafficGen, "Initial state: %d\n", currState);
3749241Sandreas.hansson@arm.com            }
3759241Sandreas.hansson@arm.com        }
3769241Sandreas.hansson@arm.com    }
3779241Sandreas.hansson@arm.com
37810128Sstan.czerniawski@arm.com    if (!init_state_set)
37910128Sstan.czerniawski@arm.com        fatal("%s: initial state not specified (add 'INIT <id>' line "
38010128Sstan.czerniawski@arm.com              "to the config file)\n", name());
38110128Sstan.czerniawski@arm.com
3829241Sandreas.hansson@arm.com    // resize and populate state transition matrix
3839721Ssascha.bischoff@arm.com    transitionMatrix.resize(states.size());
3849721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
3859721Ssascha.bischoff@arm.com        transitionMatrix[i].resize(states.size());
3869241Sandreas.hansson@arm.com    }
3879241Sandreas.hansson@arm.com
3889241Sandreas.hansson@arm.com    for (vector<Transition>::iterator t = transitions.begin();
3899241Sandreas.hansson@arm.com         t != transitions.end(); ++t) {
3909241Sandreas.hansson@arm.com        transitionMatrix[t->from][t->to] = t->p;
3919241Sandreas.hansson@arm.com    }
3929241Sandreas.hansson@arm.com
3939241Sandreas.hansson@arm.com    // ensure the egress edges do not have a probability larger than
3949241Sandreas.hansson@arm.com    // one
3959721Ssascha.bischoff@arm.com    for (size_t i = 0; i < states.size(); i++) {
3969241Sandreas.hansson@arm.com        double sum = 0;
3979721Ssascha.bischoff@arm.com        for (size_t j = 0; j < states.size(); j++) {
3989241Sandreas.hansson@arm.com            sum += transitionMatrix[i][j];
3999241Sandreas.hansson@arm.com        }
4009241Sandreas.hansson@arm.com
4019241Sandreas.hansson@arm.com        // avoid comparing floating point numbers
4029241Sandreas.hansson@arm.com        if (abs(sum - 1.0) > 0.001)
4039241Sandreas.hansson@arm.com            fatal("%s has transition probability != 1 for state %d\n",
4049241Sandreas.hansson@arm.com                  name(), i);
4059241Sandreas.hansson@arm.com    }
4069241Sandreas.hansson@arm.com
4079241Sandreas.hansson@arm.com    // close input file
4089241Sandreas.hansson@arm.com    infile.close();
4099241Sandreas.hansson@arm.com}
4109241Sandreas.hansson@arm.com
4119241Sandreas.hansson@arm.comvoid
4129717Sandreas.hansson@arm.comTrafficGen::transition()
4139241Sandreas.hansson@arm.com{
4149241Sandreas.hansson@arm.com    // exit the current state
4159241Sandreas.hansson@arm.com    states[currState]->exit();
4169241Sandreas.hansson@arm.com
4179241Sandreas.hansson@arm.com    // determine next state
4189241Sandreas.hansson@arm.com    double p = random_mt.gen_real1();
4199241Sandreas.hansson@arm.com    assert(currState < transitionMatrix.size());
4209584Sandreas@sandberg.pp.se    double cumulative = 0.0;
4219584Sandreas@sandberg.pp.se    size_t i = 0;
4229584Sandreas@sandberg.pp.se    do {
4239241Sandreas.hansson@arm.com        cumulative += transitionMatrix[currState][i];
4249241Sandreas.hansson@arm.com        ++i;
4259584Sandreas@sandberg.pp.se    } while (cumulative < p && i < transitionMatrix[currState].size());
4269584Sandreas@sandberg.pp.se
4279584Sandreas@sandberg.pp.se    enterState(i - 1);
4289241Sandreas.hansson@arm.com}
4299241Sandreas.hansson@arm.com
4309241Sandreas.hansson@arm.comvoid
4319717Sandreas.hansson@arm.comTrafficGen::enterState(uint32_t newState)
4329241Sandreas.hansson@arm.com{
4339241Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Transition to state %d\n", newState);
4349241Sandreas.hansson@arm.com
4359241Sandreas.hansson@arm.com    currState = newState;
4369719Sandreas.hansson@arm.com    // we could have been delayed and not transitioned on the exact
4379719Sandreas.hansson@arm.com    // tick when we were supposed to (due to back pressure when
4389719Sandreas.hansson@arm.com    // sending a packet)
4399719Sandreas.hansson@arm.com    nextTransitionTick = curTick() + states[currState]->duration;
4409241Sandreas.hansson@arm.com    states[currState]->enter();
4419241Sandreas.hansson@arm.com}
4429241Sandreas.hansson@arm.com
4439719Sandreas.hansson@arm.comvoid
4449719Sandreas.hansson@arm.comTrafficGen::recvRetry()
4459719Sandreas.hansson@arm.com{
4469719Sandreas.hansson@arm.com    assert(retryPkt != NULL);
4479719Sandreas.hansson@arm.com
4489719Sandreas.hansson@arm.com    DPRINTF(TrafficGen, "Received retry\n");
4499719Sandreas.hansson@arm.com    numRetries++;
4509719Sandreas.hansson@arm.com    // attempt to send the packet, and if we are successful start up
4519719Sandreas.hansson@arm.com    // the machinery again
4529719Sandreas.hansson@arm.com    if (port.sendTimingReq(retryPkt)) {
4539719Sandreas.hansson@arm.com        retryPkt = NULL;
4549719Sandreas.hansson@arm.com        // remember how much delay was incurred due to back-pressure
4559720Sandreas.hansson@arm.com        // when sending the request, we also use this to derive
4569720Sandreas.hansson@arm.com        // the tick for the next packet
4579719Sandreas.hansson@arm.com        Tick delay = curTick() - retryPktTick;
4589719Sandreas.hansson@arm.com        retryPktTick = 0;
4599719Sandreas.hansson@arm.com        retryTicks += delay;
4609719Sandreas.hansson@arm.com
4619719Sandreas.hansson@arm.com        if (drainManager == NULL) {
4629719Sandreas.hansson@arm.com            // packet is sent, so find out when the next one is due
4639720Sandreas.hansson@arm.com            nextPacketTick = states[currState]->nextPacketTick(elasticReq,
4649720Sandreas.hansson@arm.com                                                               delay);
4659719Sandreas.hansson@arm.com            Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
4669719Sandreas.hansson@arm.com            schedule(updateEvent, std::max(curTick(), nextEventTick));
4679719Sandreas.hansson@arm.com        } else {
4689719Sandreas.hansson@arm.com            // shut things down
4699719Sandreas.hansson@arm.com            nextPacketTick = MaxTick;
4709719Sandreas.hansson@arm.com            nextTransitionTick = MaxTick;
4719719Sandreas.hansson@arm.com            drainManager->signalDrainDone();
4729719Sandreas.hansson@arm.com            // Clear the drain event once we're done with it.
4739719Sandreas.hansson@arm.com            drainManager = NULL;
4749719Sandreas.hansson@arm.com        }
4759719Sandreas.hansson@arm.com    }
4769719Sandreas.hansson@arm.com}
4779719Sandreas.hansson@arm.com
4789719Sandreas.hansson@arm.comvoid
4799719Sandreas.hansson@arm.comTrafficGen::regStats()
4809719Sandreas.hansson@arm.com{
4819719Sandreas.hansson@arm.com    // Initialise all the stats
4829719Sandreas.hansson@arm.com    using namespace Stats;
4839719Sandreas.hansson@arm.com
4849719Sandreas.hansson@arm.com    numPackets
4859719Sandreas.hansson@arm.com        .name(name() + ".numPackets")
4869719Sandreas.hansson@arm.com        .desc("Number of packets generated");
4879719Sandreas.hansson@arm.com
4889719Sandreas.hansson@arm.com    numRetries
4899719Sandreas.hansson@arm.com        .name(name() + ".numRetries")
4909719Sandreas.hansson@arm.com        .desc("Number of retries");
4919719Sandreas.hansson@arm.com
4929719Sandreas.hansson@arm.com    retryTicks
4939719Sandreas.hansson@arm.com        .name(name() + ".retryTicks")
4949719Sandreas.hansson@arm.com        .desc("Time spent waiting due to back-pressure (ticks)");
4959719Sandreas.hansson@arm.com}
4969719Sandreas.hansson@arm.com
4979241Sandreas.hansson@arm.combool
4989241Sandreas.hansson@arm.comTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
4999241Sandreas.hansson@arm.com{
5009241Sandreas.hansson@arm.com    delete pkt->req;
5019241Sandreas.hansson@arm.com    delete pkt;
5029241Sandreas.hansson@arm.com
5039241Sandreas.hansson@arm.com    return true;
5049241Sandreas.hansson@arm.com}
505