traffic_gen.cc revision 10392
112837Sgabeblack@google.com/*
212837Sgabeblack@google.com * Copyright (c) 2012-2013 ARM Limited
312837Sgabeblack@google.com * All rights reserved
412837Sgabeblack@google.com *
512837Sgabeblack@google.com * The license below extends only to copyright in the software and shall
612837Sgabeblack@google.com * not be construed as granting a license to any other intellectual
712837Sgabeblack@google.com * property including but not limited to intellectual property relating
812837Sgabeblack@google.com * to a hardware implementation of the functionality of the software
912837Sgabeblack@google.com * licensed hereunder.  You may use the software subject to the license
1012837Sgabeblack@google.com * terms below provided that you ensure that this notice is replicated
1112837Sgabeblack@google.com * unmodified and in its entirety in all distributions of the software,
1212837Sgabeblack@google.com * modified or unmodified, in source code or in binary form.
1312837Sgabeblack@google.com *
1412837Sgabeblack@google.com * Redistribution and use in source and binary forms, with or without
1512837Sgabeblack@google.com * modification, are permitted provided that the following conditions are
1612837Sgabeblack@google.com * met: redistributions of source code must retain the above copyright
1712837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer;
1812837Sgabeblack@google.com * redistributions in binary form must reproduce the above copyright
1912837Sgabeblack@google.com * notice, this list of conditions and the following disclaimer in the
2012837Sgabeblack@google.com * documentation and/or other materials provided with the distribution;
2112837Sgabeblack@google.com * neither the name of the copyright holders nor the names of its
2212837Sgabeblack@google.com * contributors may be used to endorse or promote products derived from
2312837Sgabeblack@google.com * this software without specific prior written permission.
2412837Sgabeblack@google.com *
2512837Sgabeblack@google.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2612837Sgabeblack@google.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2712837Sgabeblack@google.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2812837Sgabeblack@google.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2912837Sgabeblack@google.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3012901Sgabeblack@google.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3113135Sgabeblack@google.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3212901Sgabeblack@google.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3312901Sgabeblack@google.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3412837Sgabeblack@google.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3512982Sgabeblack@google.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3612951Sgabeblack@google.com *
3712953Sgabeblack@google.com * Authors: Thomas Grass
3813155Sgabeblack@google.com *          Andreas Hansson
3912837Sgabeblack@google.com *          Sascha Bischoff
4012951Sgabeblack@google.com */
4113155Sgabeblack@google.com
4213135Sgabeblack@google.com#include <sstream>
4312837Sgabeblack@google.com
4412952Sgabeblack@google.com#include "base/intmath.hh"
4512952Sgabeblack@google.com#include "base/random.hh"
4612952Sgabeblack@google.com#include "cpu/testers/traffic_gen/traffic_gen.hh"
4712952Sgabeblack@google.com#include "debug/Checkpoint.hh"
4812952Sgabeblack@google.com#include "debug/TrafficGen.hh"
4912952Sgabeblack@google.com#include "sim/stats.hh"
5013135Sgabeblack@google.com#include "sim/system.hh"
5113135Sgabeblack@google.com
5213135Sgabeblack@google.comusing namespace std;
5313135Sgabeblack@google.com
5413135Sgabeblack@google.comTrafficGen::TrafficGen(const TrafficGenParams* p)
5513135Sgabeblack@google.com    : MemObject(p),
5613135Sgabeblack@google.com      system(p->system),
5713135Sgabeblack@google.com      masterID(system->getMasterId(name())),
5812993Sgabeblack@google.com      configFile(p->config_file),
5912993Sgabeblack@google.com      elasticReq(p->elastic_req),
6012952Sgabeblack@google.com      nextTransitionTick(0),
6112952Sgabeblack@google.com      nextPacketTick(0),
6212952Sgabeblack@google.com      currState(0),
6312952Sgabeblack@google.com      port(name() + ".port", *this),
6412952Sgabeblack@google.com      retryPkt(NULL),
6513135Sgabeblack@google.com      retryPktTick(0),
6613135Sgabeblack@google.com      updateEvent(this),
6713135Sgabeblack@google.com      drainManager(NULL)
6813135Sgabeblack@google.com{
6913135Sgabeblack@google.com}
7013135Sgabeblack@google.com
7113135Sgabeblack@google.comTrafficGen*
7213135Sgabeblack@google.comTrafficGenParams::create()
7312993Sgabeblack@google.com{
7412993Sgabeblack@google.com    return new TrafficGen(this);
7512952Sgabeblack@google.com}
7612952Sgabeblack@google.com
7712952Sgabeblack@google.comBaseMasterPort&
7812952Sgabeblack@google.comTrafficGen::getMasterPort(const string& if_name, PortID idx)
7912952Sgabeblack@google.com{
8013135Sgabeblack@google.com    if (if_name == "port") {
8113135Sgabeblack@google.com        return port;
8213135Sgabeblack@google.com    } else {
8313135Sgabeblack@google.com        return MemObject::getMasterPort(if_name, idx);
8413135Sgabeblack@google.com    }
8513135Sgabeblack@google.com}
8613135Sgabeblack@google.com
8713135Sgabeblack@google.comvoid
8812993Sgabeblack@google.comTrafficGen::init()
8913060Sgabeblack@google.com{
9012993Sgabeblack@google.com    if (!port.isConnected())
9112952Sgabeblack@google.com        fatal("The port of %s is not connected!\n", name());
9212952Sgabeblack@google.com
9313035Sgabeblack@google.com    // if the system is in timing mode active the request generator
9413035Sgabeblack@google.com    if (system->isTimingMode()) {
9512952Sgabeblack@google.com        DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
9612952Sgabeblack@google.com
9712837Sgabeblack@google.com        parseConfig();
9812837Sgabeblack@google.com
9912837Sgabeblack@google.com        // enter initial state
10013091Sgabeblack@google.com        enterState(currState);
10112951Sgabeblack@google.com    } else {
10212951Sgabeblack@google.com        DPRINTF(TrafficGen,
10312837Sgabeblack@google.com                "Traffic generator is only active in timing mode\n");
10413091Sgabeblack@google.com    }
10512951Sgabeblack@google.com}
10612951Sgabeblack@google.com
10712837Sgabeblack@google.comvoid
10813091Sgabeblack@google.comTrafficGen::initState()
10912837Sgabeblack@google.com{
11012982Sgabeblack@google.com    // when not restoring from a checkpoint, make sure we kick things off
11112837Sgabeblack@google.com    if (system->isTimingMode()) {
11213091Sgabeblack@google.com        // call nextPacketTick on the state to advance it
11312837Sgabeblack@google.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
11412837Sgabeblack@google.com        schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick));
11512837Sgabeblack@google.com    } else {
11612837Sgabeblack@google.com        DPRINTF(TrafficGen,
11712837Sgabeblack@google.com                "Traffic generator is only active in timing mode\n");
11812837Sgabeblack@google.com    }
11912837Sgabeblack@google.com}
12012837Sgabeblack@google.com
12112837Sgabeblack@google.comunsigned int
12212837Sgabeblack@google.comTrafficGen::drain(DrainManager *dm)
12312837Sgabeblack@google.com{
12412837Sgabeblack@google.com    if (!updateEvent.scheduled()) {
12512837Sgabeblack@google.com        // no event has been scheduled yet (e.g. switched from atomic mode)
12612837Sgabeblack@google.com        return 0;
12712837Sgabeblack@google.com    }
12812837Sgabeblack@google.com
12912837Sgabeblack@google.com    if (retryPkt == NULL) {
13012837Sgabeblack@google.com        // shut things down
13112837Sgabeblack@google.com        nextPacketTick = MaxTick;
13212837Sgabeblack@google.com        nextTransitionTick = MaxTick;
13312837Sgabeblack@google.com        deschedule(updateEvent);
13412837Sgabeblack@google.com        return 0;
13512837Sgabeblack@google.com    } else {
13612837Sgabeblack@google.com        drainManager = dm;
13712837Sgabeblack@google.com        return 1;
13812837Sgabeblack@google.com    }
13912837Sgabeblack@google.com}
14012837Sgabeblack@google.com
14112837Sgabeblack@google.comvoid
14212837Sgabeblack@google.comTrafficGen::serialize(ostream &os)
14312837Sgabeblack@google.com{
14412837Sgabeblack@google.com    DPRINTF(Checkpoint, "Serializing TrafficGen\n");
14512837Sgabeblack@google.com
14612837Sgabeblack@google.com    // save ticks of the graph event if it is scheduled
14712837Sgabeblack@google.com    Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0;
14812837Sgabeblack@google.com
14912837Sgabeblack@google.com    DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent);
15012837Sgabeblack@google.com
15112837Sgabeblack@google.com    SERIALIZE_SCALAR(nextEvent);
15212837Sgabeblack@google.com
15312837Sgabeblack@google.com    SERIALIZE_SCALAR(nextTransitionTick);
15412837Sgabeblack@google.com
15512837Sgabeblack@google.com    SERIALIZE_SCALAR(nextPacketTick);
15612837Sgabeblack@google.com
15712837Sgabeblack@google.com    SERIALIZE_SCALAR(currState);
15812837Sgabeblack@google.com}
15912837Sgabeblack@google.com
16012837Sgabeblack@google.comvoid
16112837Sgabeblack@google.comTrafficGen::unserialize(Checkpoint* cp, const string& section)
16212837Sgabeblack@google.com{
16312837Sgabeblack@google.com    // restore scheduled events
16412837Sgabeblack@google.com    Tick nextEvent;
16512837Sgabeblack@google.com    UNSERIALIZE_SCALAR(nextEvent);
16612837Sgabeblack@google.com    if (nextEvent != 0) {
16712837Sgabeblack@google.com        schedule(updateEvent, nextEvent);
16812837Sgabeblack@google.com    }
16912837Sgabeblack@google.com
17012837Sgabeblack@google.com    UNSERIALIZE_SCALAR(nextTransitionTick);
17112837Sgabeblack@google.com
17212837Sgabeblack@google.com    UNSERIALIZE_SCALAR(nextPacketTick);
17312837Sgabeblack@google.com
17412837Sgabeblack@google.com    // @todo In the case of a stateful generator state such as the
17512837Sgabeblack@google.com    // trace player we would also have to restore the position in the
17612837Sgabeblack@google.com    // trace playback and the tick offset
17712837Sgabeblack@google.com    UNSERIALIZE_SCALAR(currState);
17812837Sgabeblack@google.com}
17912837Sgabeblack@google.com
18013091Sgabeblack@google.comvoid
18113091Sgabeblack@google.comTrafficGen::update()
18213091Sgabeblack@google.com{
18313091Sgabeblack@google.com    // if we have reached the time for the next state transition, then
18413091Sgabeblack@google.com    // perform the transition
18513091Sgabeblack@google.com    if (curTick() >= nextTransitionTick) {
18613091Sgabeblack@google.com        transition();
18713091Sgabeblack@google.com    } else {
18813091Sgabeblack@google.com        assert(curTick() >= nextPacketTick);
18913091Sgabeblack@google.com        // get the next packet and try to send it
19013091Sgabeblack@google.com        PacketPtr pkt = states[currState]->getNextPacket();
19113091Sgabeblack@google.com
19213091Sgabeblack@google.com        // suppress packets that are not destined for a memory, such as
19313091Sgabeblack@google.com        // device accesses that could be part of a trace
19413091Sgabeblack@google.com        if (system->isMemAddr(pkt->getAddr())) {
19513091Sgabeblack@google.com            numPackets++;
19613091Sgabeblack@google.com            if (!port.sendTimingReq(pkt)) {
19713091Sgabeblack@google.com                retryPkt = pkt;
19813091Sgabeblack@google.com                retryPktTick = curTick();
19913091Sgabeblack@google.com            }
20013091Sgabeblack@google.com        } else {
20113091Sgabeblack@google.com            DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n",
20213091Sgabeblack@google.com                    pkt->cmdString(), pkt->getAddr());
20313091Sgabeblack@google.com        }
20412837Sgabeblack@google.com    }
20512837Sgabeblack@google.com
20612837Sgabeblack@google.com    // if we are waiting for a retry, do not schedule any further
20712837Sgabeblack@google.com    // events, in the case of a transition or a successful send, go
20812837Sgabeblack@google.com    // ahead and determine when the next update should take place
20912951Sgabeblack@google.com    if (retryPkt == NULL) {
21012837Sgabeblack@google.com        // schedule next update event based on either the next execute
21112837Sgabeblack@google.com        // tick or the next transition, which ever comes first
21212837Sgabeblack@google.com        nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0);
21312837Sgabeblack@google.com        Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
21412837Sgabeblack@google.com        DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick);
21512951Sgabeblack@google.com        schedule(updateEvent, nextEventTick);
21612837Sgabeblack@google.com    }
21712837Sgabeblack@google.com}
21812951Sgabeblack@google.com
21913079Sgabeblack@google.comvoid
22012951Sgabeblack@google.comTrafficGen::parseConfig()
22112951Sgabeblack@google.com{
22212837Sgabeblack@google.com    // keep track of the transitions parsed to create the matrix when
22312951Sgabeblack@google.com    // done
22412951Sgabeblack@google.com    vector<Transition> transitions;
22512951Sgabeblack@google.com
22612951Sgabeblack@google.com    // open input file
22712951Sgabeblack@google.com    ifstream infile;
22812928Sgabeblack@google.com    infile.open(configFile.c_str(), ifstream::in);
22912837Sgabeblack@google.com    if (!infile.is_open()) {
23012837Sgabeblack@google.com        fatal("Traffic generator %s config file not found at %s\n",
23112837Sgabeblack@google.com              name(), configFile);
23212837Sgabeblack@google.com    }
23312837Sgabeblack@google.com
23412837Sgabeblack@google.com    bool init_state_set = false;
23512837Sgabeblack@google.com
23612837Sgabeblack@google.com    // read line by line and determine the action based on the first
23712837Sgabeblack@google.com    // keyword
23812837Sgabeblack@google.com    string keyword;
23912837Sgabeblack@google.com    string line;
24012837Sgabeblack@google.com
24112837Sgabeblack@google.com    while (getline(infile, line).good()) {
24212837Sgabeblack@google.com        // see if this line is a comment line, and if so skip it
24312837Sgabeblack@google.com        if (line.find('#') != 1) {
24412837Sgabeblack@google.com            // create an input stream for the tokenization
24512837Sgabeblack@google.com            istringstream is(line);
24612837Sgabeblack@google.com
24712837Sgabeblack@google.com            // determine the keyword
24812837Sgabeblack@google.com            is >> keyword;
24912837Sgabeblack@google.com
25012837Sgabeblack@google.com            if (keyword == "STATE") {
25112837Sgabeblack@google.com                // parse the behaviour of this state
25212837Sgabeblack@google.com                uint32_t id;
25312837Sgabeblack@google.com                Tick duration;
25412837Sgabeblack@google.com                string mode;
25512837Sgabeblack@google.com
25612837Sgabeblack@google.com                is >> id >> duration >> mode;
25712837Sgabeblack@google.com
25812837Sgabeblack@google.com                if (mode == "TRACE") {
25912837Sgabeblack@google.com                    string traceFile;
26012837Sgabeblack@google.com                    Addr addrOffset;
26112837Sgabeblack@google.com
26212837Sgabeblack@google.com                    is >> traceFile >> addrOffset;
26312837Sgabeblack@google.com
26412837Sgabeblack@google.com                    states[id] = new TraceGen(name(), masterID, duration,
26512837Sgabeblack@google.com                                              traceFile, addrOffset);
26612837Sgabeblack@google.com                    DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
26712837Sgabeblack@google.com                } else if (mode == "IDLE") {
26812837Sgabeblack@google.com                    states[id] = new IdleGen(name(), masterID, duration);
26912837Sgabeblack@google.com                    DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
27012837Sgabeblack@google.com                } else if (mode == "LINEAR" || mode == "RANDOM" ||
27112837Sgabeblack@google.com                           mode == "DRAM"   || mode == "DRAM_ROTATE") {
27212837Sgabeblack@google.com                    uint32_t read_percent;
27312837Sgabeblack@google.com                    Addr start_addr;
27412837Sgabeblack@google.com                    Addr end_addr;
27512837Sgabeblack@google.com                    Addr blocksize;
27612837Sgabeblack@google.com                    Tick min_period;
27712837Sgabeblack@google.com                    Tick max_period;
27812837Sgabeblack@google.com                    Addr data_limit;
27912837Sgabeblack@google.com
28012837Sgabeblack@google.com                    is >> read_percent >> start_addr >> end_addr >>
28112837Sgabeblack@google.com                        blocksize >> min_period >> max_period >> data_limit;
28212953Sgabeblack@google.com
28312837Sgabeblack@google.com                    DPRINTF(TrafficGen, "%s, addr %x to %x, size %d,"
28412837Sgabeblack@google.com                            " period %d to %d, %d%% reads\n",
28512837Sgabeblack@google.com                            mode, start_addr, end_addr, blocksize, min_period,
28612953Sgabeblack@google.com                            max_period, read_percent);
28712837Sgabeblack@google.com
28812953Sgabeblack@google.com
28912837Sgabeblack@google.com                    if (blocksize > system->cacheLineSize())
29012837Sgabeblack@google.com                        fatal("TrafficGen %s block size (%d) is larger than "
29112837Sgabeblack@google.com                              "cache line size (%d)\n", name(),
29212951Sgabeblack@google.com                              blocksize, system->cacheLineSize());
29312951Sgabeblack@google.com
29412837Sgabeblack@google.com                    if (read_percent > 100)
29512951Sgabeblack@google.com                        fatal("%s cannot have more than 100% reads", name());
29612837Sgabeblack@google.com
29712951Sgabeblack@google.com                    if (min_period > max_period)
29812837Sgabeblack@google.com                        fatal("%s cannot have min_period > max_period", name());
29912837Sgabeblack@google.com
30012837Sgabeblack@google.com                    if (mode == "LINEAR") {
30112951Sgabeblack@google.com                        states[id] = new LinearGen(name(), masterID,
30212837Sgabeblack@google.com                                                   duration, start_addr,
30312951Sgabeblack@google.com                                                   end_addr, blocksize,
30412837Sgabeblack@google.com                                                   min_period, max_period,
30512837Sgabeblack@google.com                                                   read_percent, data_limit);
30612837Sgabeblack@google.com                        DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
30712951Sgabeblack@google.com                    } else if (mode == "RANDOM") {
30812837Sgabeblack@google.com                        states[id] = new RandomGen(name(), masterID,
30912951Sgabeblack@google.com                                                   duration, start_addr,
31012837Sgabeblack@google.com                                                   end_addr, blocksize,
31112837Sgabeblack@google.com                                                   min_period, max_period,
31212837Sgabeblack@google.com                                                   read_percent, data_limit);
31312951Sgabeblack@google.com                        DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
31412837Sgabeblack@google.com                    } else if (mode == "DRAM" || mode == "DRAM_ROTATE") {
31512951Sgabeblack@google.com                        // stride size (bytes) of the request for achieving
31612837Sgabeblack@google.com                        // required hit length
31712837Sgabeblack@google.com                        unsigned int stride_size;
31812837Sgabeblack@google.com                        unsigned int page_size;
31912951Sgabeblack@google.com                        unsigned int nbr_of_banks_DRAM;
32012837Sgabeblack@google.com                        unsigned int nbr_of_banks_util;
32112951Sgabeblack@google.com                        unsigned int addr_mapping;
32212837Sgabeblack@google.com                        unsigned int nbr_of_ranks;
32312837Sgabeblack@google.com
32412837Sgabeblack@google.com                        is >> stride_size >> page_size >> nbr_of_banks_DRAM >>
32512951Sgabeblack@google.com                            nbr_of_banks_util >> addr_mapping >>
32612837Sgabeblack@google.com                            nbr_of_ranks;
32712951Sgabeblack@google.com
32812837Sgabeblack@google.com                        if (stride_size > page_size)
32912837Sgabeblack@google.com                            warn("DRAM generator stride size (%d) is greater "
33012837Sgabeblack@google.com                                 "than page size (%d)  of the memory\n",
33112951Sgabeblack@google.com                                 blocksize, page_size);
33212837Sgabeblack@google.com
33312951Sgabeblack@google.com                        if (nbr_of_banks_util > nbr_of_banks_DRAM)
33412837Sgabeblack@google.com                            fatal("Attempting to use more banks (%) than "
33512837Sgabeblack@google.com                                  "what is available (%)\n",
33612837Sgabeblack@google.com                                  nbr_of_banks_util, nbr_of_banks_DRAM);
33712951Sgabeblack@google.com
33812837Sgabeblack@google.com                        if (nbr_of_banks_util > nbr_of_banks_DRAM)
33912951Sgabeblack@google.com                            fatal("Attempting to use more banks (%) than "
34012837Sgabeblack@google.com                                  "what is available (%)\n",
34112837Sgabeblack@google.com                                  nbr_of_banks_util, nbr_of_banks_DRAM);
34212837Sgabeblack@google.com
34312951Sgabeblack@google.com                        // count the number of sequential packets to
34412837Sgabeblack@google.com                        // generate
34512951Sgabeblack@google.com                        unsigned int num_seq_pkts = 1;
34612837Sgabeblack@google.com
34712837Sgabeblack@google.com                        if (stride_size > blocksize) {
34812837Sgabeblack@google.com                            num_seq_pkts = divCeil(stride_size, blocksize);
34912951Sgabeblack@google.com                            DPRINTF(TrafficGen, "stride size: %d "
35012837Sgabeblack@google.com                                    "block size: %d, num_seq_pkts: %d\n",
35112951Sgabeblack@google.com                                    stride_size, blocksize, num_seq_pkts);
35212837Sgabeblack@google.com                        }
35312837Sgabeblack@google.com
35412837Sgabeblack@google.com                        if (mode == "DRAM") {
35512951Sgabeblack@google.com                            states[id] = new DramGen(name(), masterID,
35612837Sgabeblack@google.com                                                     duration, start_addr,
35712951Sgabeblack@google.com                                                     end_addr, blocksize,
35812837Sgabeblack@google.com                                                     min_period, max_period,
35912837Sgabeblack@google.com                                                     read_percent, data_limit,
36012837Sgabeblack@google.com                                                     num_seq_pkts, page_size,
36112929Sgabeblack@google.com                                                     nbr_of_banks_DRAM,
36212929Sgabeblack@google.com                                                     nbr_of_banks_util,
36312929Sgabeblack@google.com                                                     addr_mapping,
36412929Sgabeblack@google.com                                                     nbr_of_ranks);
36512929Sgabeblack@google.com                            DPRINTF(TrafficGen, "State: %d DramGen\n", id);
36612929Sgabeblack@google.com                        } else {
36712929Sgabeblack@google.com                            // Will rotate to the next rank after rotating
36812929Sgabeblack@google.com                            // through all banks, for each command type.
36912837Sgabeblack@google.com                            // In the 50% read case, series will be issued
37012837Sgabeblack@google.com                            // for both RD & WR before the rank in incremented
37112837Sgabeblack@google.com                            unsigned int max_seq_count_per_rank =
37212951Sgabeblack@google.com                                (read_percent == 50) ? nbr_of_banks_util * 2
37312837Sgabeblack@google.com                                                     : nbr_of_banks_util;
37412837Sgabeblack@google.com
37512837Sgabeblack@google.com                            states[id] = new DramRotGen(name(), masterID,
37612951Sgabeblack@google.com                                                     duration, start_addr,
37712837Sgabeblack@google.com                                                     end_addr, blocksize,
37812951Sgabeblack@google.com                                                     min_period, max_period,
37912837Sgabeblack@google.com                                                     read_percent, data_limit,
38012837Sgabeblack@google.com                                                     num_seq_pkts, page_size,
38112837Sgabeblack@google.com                                                     nbr_of_banks_DRAM,
38212951Sgabeblack@google.com                                                     nbr_of_banks_util,
38312837Sgabeblack@google.com                                                     addr_mapping,
38412951Sgabeblack@google.com                                                     nbr_of_ranks,
38512837Sgabeblack@google.com                                                     max_seq_count_per_rank);
38612837Sgabeblack@google.com                            DPRINTF(TrafficGen, "State: %d DramRotGen\n", id);
38712837Sgabeblack@google.com                        }
38812951Sgabeblack@google.com                    }
38912837Sgabeblack@google.com                } else {
39012951Sgabeblack@google.com                    fatal("%s: Unknown traffic generator mode: %s",
39112837Sgabeblack@google.com                          name(), mode);
39212837Sgabeblack@google.com                }
39312837Sgabeblack@google.com            } else if (keyword == "TRANSITION") {
39412951Sgabeblack@google.com                Transition transition;
39512837Sgabeblack@google.com
39612951Sgabeblack@google.com                is >> transition.from >> transition.to >> transition.p;
39712837Sgabeblack@google.com
39812837Sgabeblack@google.com                transitions.push_back(transition);
39912837Sgabeblack@google.com
40012951Sgabeblack@google.com                DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from,
40112837Sgabeblack@google.com                        transition.to);
40212951Sgabeblack@google.com            } else if (keyword == "INIT") {
40312837Sgabeblack@google.com                // set the initial state as the active state
40412837Sgabeblack@google.com                is >> currState;
40512837Sgabeblack@google.com
40612951Sgabeblack@google.com                init_state_set = true;
40712837Sgabeblack@google.com
40812951Sgabeblack@google.com                DPRINTF(TrafficGen, "Initial state: %d\n", currState);
40912837Sgabeblack@google.com            }
41012837Sgabeblack@google.com        }
41112837Sgabeblack@google.com    }
41212951Sgabeblack@google.com
41312837Sgabeblack@google.com    if (!init_state_set)
41412951Sgabeblack@google.com        fatal("%s: initial state not specified (add 'INIT <id>' line "
41512837Sgabeblack@google.com              "to the config file)\n", name());
41612837Sgabeblack@google.com
41712837Sgabeblack@google.com    // resize and populate state transition matrix
41812951Sgabeblack@google.com    transitionMatrix.resize(states.size());
41912837Sgabeblack@google.com    for (size_t i = 0; i < states.size(); i++) {
42012951Sgabeblack@google.com        transitionMatrix[i].resize(states.size());
42112837Sgabeblack@google.com    }
42212837Sgabeblack@google.com
42312837Sgabeblack@google.com    for (vector<Transition>::iterator t = transitions.begin();
42412951Sgabeblack@google.com         t != transitions.end(); ++t) {
42512837Sgabeblack@google.com        transitionMatrix[t->from][t->to] = t->p;
42612951Sgabeblack@google.com    }
42712837Sgabeblack@google.com
42812837Sgabeblack@google.com    // ensure the egress edges do not have a probability larger than
42912837Sgabeblack@google.com    // one
43012951Sgabeblack@google.com    for (size_t i = 0; i < states.size(); i++) {
43112837Sgabeblack@google.com        double sum = 0;
43212951Sgabeblack@google.com        for (size_t j = 0; j < states.size(); j++) {
43312837Sgabeblack@google.com            sum += transitionMatrix[i][j];
43412837Sgabeblack@google.com        }
43512837Sgabeblack@google.com
43612951Sgabeblack@google.com        // avoid comparing floating point numbers
43712837Sgabeblack@google.com        if (abs(sum - 1.0) > 0.001)
43812951Sgabeblack@google.com            fatal("%s has transition probability != 1 for state %d\n",
43912837Sgabeblack@google.com                  name(), i);
44012837Sgabeblack@google.com    }
44112837Sgabeblack@google.com
44212951Sgabeblack@google.com    // close input file
44312837Sgabeblack@google.com    infile.close();
44412951Sgabeblack@google.com}
44512837Sgabeblack@google.com
44612837Sgabeblack@google.comvoid
44712837Sgabeblack@google.comTrafficGen::transition()
44812837Sgabeblack@google.com{
44912909Sgabeblack@google.com    // exit the current state
45012909Sgabeblack@google.com    states[currState]->exit();
45112951Sgabeblack@google.com
45212909Sgabeblack@google.com    // determine next state
45312909Sgabeblack@google.com    double p = random_mt.random<double>();
45412914Sgabeblack@google.com    assert(currState < transitionMatrix.size());
45512951Sgabeblack@google.com    double cumulative = 0.0;
45612914Sgabeblack@google.com    size_t i = 0;
45712951Sgabeblack@google.com    do {
45812914Sgabeblack@google.com        cumulative += transitionMatrix[currState][i];
45912914Sgabeblack@google.com        ++i;
46012914Sgabeblack@google.com    } while (cumulative < p && i < transitionMatrix[currState].size());
46112951Sgabeblack@google.com
46212914Sgabeblack@google.com    enterState(i - 1);
46312951Sgabeblack@google.com}
46412914Sgabeblack@google.com
46512914Sgabeblack@google.comvoid
46612914Sgabeblack@google.comTrafficGen::enterState(uint32_t newState)
46712951Sgabeblack@google.com{
46812914Sgabeblack@google.com    DPRINTF(TrafficGen, "Transition to state %d\n", newState);
46912951Sgabeblack@google.com
47012914Sgabeblack@google.com    currState = newState;
47112914Sgabeblack@google.com    // we could have been delayed and not transitioned on the exact
47212914Sgabeblack@google.com    // tick when we were supposed to (due to back pressure when
47312951Sgabeblack@google.com    // sending a packet)
47412914Sgabeblack@google.com    nextTransitionTick = curTick() + states[currState]->duration;
47512951Sgabeblack@google.com    states[currState]->enter();
47612914Sgabeblack@google.com}
47712914Sgabeblack@google.com
47812909Sgabeblack@google.comvoid
47912909Sgabeblack@google.comTrafficGen::recvRetry()
48012837Sgabeblack@google.com{
48112837Sgabeblack@google.com    assert(retryPkt != NULL);
48212958Sgabeblack@google.com
48312958Sgabeblack@google.com    DPRINTF(TrafficGen, "Received retry\n");
48412837Sgabeblack@google.com    numRetries++;
48512837Sgabeblack@google.com    // attempt to send the packet, and if we are successful start up
48612837Sgabeblack@google.com    // the machinery again
48712958Sgabeblack@google.com    if (port.sendTimingReq(retryPkt)) {
48812837Sgabeblack@google.com        retryPkt = NULL;
48912958Sgabeblack@google.com        // remember how much delay was incurred due to back-pressure
49012958Sgabeblack@google.com        // when sending the request, we also use this to derive
49112837Sgabeblack@google.com        // the tick for the next packet
49212837Sgabeblack@google.com        Tick delay = curTick() - retryPktTick;
49312837Sgabeblack@google.com        retryPktTick = 0;
49412958Sgabeblack@google.com        retryTicks += delay;
49512837Sgabeblack@google.com
49612958Sgabeblack@google.com        if (drainManager == NULL) {
49712958Sgabeblack@google.com            // packet is sent, so find out when the next one is due
49812837Sgabeblack@google.com            nextPacketTick = states[currState]->nextPacketTick(elasticReq,
49912837Sgabeblack@google.com                                                               delay);
50012837Sgabeblack@google.com            Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick);
50112958Sgabeblack@google.com            schedule(updateEvent, std::max(curTick(), nextEventTick));
50212837Sgabeblack@google.com        } else {
50312958Sgabeblack@google.com            // shut things down
50412958Sgabeblack@google.com            nextPacketTick = MaxTick;
50512837Sgabeblack@google.com            nextTransitionTick = MaxTick;
50612837Sgabeblack@google.com            drainManager->signalDrainDone();
50712837Sgabeblack@google.com            // Clear the drain event once we're done with it.
50812958Sgabeblack@google.com            drainManager = NULL;
50912837Sgabeblack@google.com        }
51012958Sgabeblack@google.com    }
51112958Sgabeblack@google.com}
51212837Sgabeblack@google.com
51312837Sgabeblack@google.comvoid
51412837Sgabeblack@google.comTrafficGen::regStats()
51512951Sgabeblack@google.com{
51612837Sgabeblack@google.com    // Initialise all the stats
51712951Sgabeblack@google.com    using namespace Stats;
51812837Sgabeblack@google.com
51912837Sgabeblack@google.com    numPackets
52012837Sgabeblack@google.com        .name(name() + ".numPackets")
52112958Sgabeblack@google.com        .desc("Number of packets generated");
52212837Sgabeblack@google.com
52312958Sgabeblack@google.com    numRetries
52412958Sgabeblack@google.com        .name(name() + ".numRetries")
52512837Sgabeblack@google.com        .desc("Number of retries");
52612837Sgabeblack@google.com
52712837Sgabeblack@google.com    retryTicks
52812951Sgabeblack@google.com        .name(name() + ".retryTicks")
52912837Sgabeblack@google.com        .desc("Time spent waiting due to back-pressure (ticks)");
53012951Sgabeblack@google.com}
53112837Sgabeblack@google.com
53212837Sgabeblack@google.combool
53312837Sgabeblack@google.comTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
53412958Sgabeblack@google.com{
53512837Sgabeblack@google.com    delete pkt->req;
53612958Sgabeblack@google.com    delete pkt;
53712958Sgabeblack@google.com
53812958Sgabeblack@google.com    return true;
53912837Sgabeblack@google.com}
54012837Sgabeblack@google.com