traffic_gen.cc revision 9241:6cfb9a7acb1b
113531Sjairo.balart@metempsy.com/*
213531Sjairo.balart@metempsy.com * Copyright (c) 2012 ARM Limited
313531Sjairo.balart@metempsy.com * All rights reserved
413531Sjairo.balart@metempsy.com *
513531Sjairo.balart@metempsy.com * The license below extends only to copyright in the software and shall
613531Sjairo.balart@metempsy.com * not be construed as granting a license to any other intellectual
713531Sjairo.balart@metempsy.com * property including but not limited to intellectual property relating
813531Sjairo.balart@metempsy.com * to a hardware implementation of the functionality of the software
913531Sjairo.balart@metempsy.com * licensed hereunder.  You may use the software subject to the license
1013531Sjairo.balart@metempsy.com * terms below provided that you ensure that this notice is replicated
1113531Sjairo.balart@metempsy.com * unmodified and in its entirety in all distributions of the software,
1213531Sjairo.balart@metempsy.com * modified or unmodified, in source code or in binary form.
1313531Sjairo.balart@metempsy.com *
1413531Sjairo.balart@metempsy.com * Redistribution and use in source and binary forms, with or without
1513531Sjairo.balart@metempsy.com * modification, are permitted provided that the following conditions are
1613531Sjairo.balart@metempsy.com * met: redistributions of source code must retain the above copyright
1713531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer;
1813531Sjairo.balart@metempsy.com * redistributions in binary form must reproduce the above copyright
1913531Sjairo.balart@metempsy.com * notice, this list of conditions and the following disclaimer in the
2013531Sjairo.balart@metempsy.com * documentation and/or other materials provided with the distribution;
2113531Sjairo.balart@metempsy.com * neither the name of the copyright holders nor the names of its
2213531Sjairo.balart@metempsy.com * contributors may be used to endorse or promote products derived from
2313531Sjairo.balart@metempsy.com * this software without specific prior written permission.
2413531Sjairo.balart@metempsy.com *
2513531Sjairo.balart@metempsy.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2613531Sjairo.balart@metempsy.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2713531Sjairo.balart@metempsy.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
2813531Sjairo.balart@metempsy.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
2913531Sjairo.balart@metempsy.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3013531Sjairo.balart@metempsy.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3113531Sjairo.balart@metempsy.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3213531Sjairo.balart@metempsy.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3313531Sjairo.balart@metempsy.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3413531Sjairo.balart@metempsy.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3513531Sjairo.balart@metempsy.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3613531Sjairo.balart@metempsy.com *
3713531Sjairo.balart@metempsy.com * Authors: Thomas Grass
3813531Sjairo.balart@metempsy.com *          Andreas Hansson
3913531Sjairo.balart@metempsy.com *          Sascha Bischoff
4013531Sjairo.balart@metempsy.com */
4113531Sjairo.balart@metempsy.com
4213531Sjairo.balart@metempsy.com#include <sstream>
4313531Sjairo.balart@metempsy.com
4413531Sjairo.balart@metempsy.com#include "base/random.hh"
4513531Sjairo.balart@metempsy.com#include "cpu/testers/traffic_gen/traffic_gen.hh"
4613531Sjairo.balart@metempsy.com#include "debug/Checkpoint.hh"
4713531Sjairo.balart@metempsy.com#include "debug/TrafficGen.hh"
4813531Sjairo.balart@metempsy.com#include "sim/stats.hh"
4913531Sjairo.balart@metempsy.com#include "sim/system.hh"
5013531Sjairo.balart@metempsy.com
5113531Sjairo.balart@metempsy.comusing namespace std;
5213531Sjairo.balart@metempsy.com
5313531Sjairo.balart@metempsy.comTrafficGen::TrafficGen(const TrafficGenParams* p)
5413531Sjairo.balart@metempsy.com    : MemObject(p),
5513531Sjairo.balart@metempsy.com      system(p->system),
5613531Sjairo.balart@metempsy.com      masterID(system->getMasterId(name())),
5713531Sjairo.balart@metempsy.com      port(name() + ".port", *this),
5813531Sjairo.balart@metempsy.com      stateGraph(*this, port, p->config_file, masterID),
5913531Sjairo.balart@metempsy.com      updateStateGraphEvent(this)
6013531Sjairo.balart@metempsy.com{
6113531Sjairo.balart@metempsy.com}
6213531Sjairo.balart@metempsy.com
6313531Sjairo.balart@metempsy.comTrafficGen*
6413531Sjairo.balart@metempsy.comTrafficGenParams::create()
6513531Sjairo.balart@metempsy.com{
6613531Sjairo.balart@metempsy.com    return new TrafficGen(this);
6713531Sjairo.balart@metempsy.com}
6813760Sjairo.balart@metempsy.com
6913531Sjairo.balart@metempsy.comMasterPort&
7013531Sjairo.balart@metempsy.comTrafficGen::getMasterPort(const string& if_name, int idx)
7113531Sjairo.balart@metempsy.com{
7213531Sjairo.balart@metempsy.com    if (if_name == "port") {
7313531Sjairo.balart@metempsy.com        return port;
7413531Sjairo.balart@metempsy.com    } else {
7513531Sjairo.balart@metempsy.com        return MemObject::getMasterPort(if_name, idx);
7613531Sjairo.balart@metempsy.com    }
7713531Sjairo.balart@metempsy.com}
7813531Sjairo.balart@metempsy.com
7913531Sjairo.balart@metempsy.comvoid
8013531Sjairo.balart@metempsy.comTrafficGen::init()
8113531Sjairo.balart@metempsy.com{
8213760Sjairo.balart@metempsy.com    if (!port.isConnected())
8313531Sjairo.balart@metempsy.com        fatal("The port of %s is not connected!\n", name());
8413531Sjairo.balart@metempsy.com
8513531Sjairo.balart@metempsy.com    Enums::MemoryMode mode = system->getMemoryMode();
8613531Sjairo.balart@metempsy.com
8713531Sjairo.balart@metempsy.com    // if the system is in timing mode active the request generator
8813531Sjairo.balart@metempsy.com    if (mode == Enums::timing) {
8913531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen, "Timing mode, activating request generator\n");
9013531Sjairo.balart@metempsy.com
9113531Sjairo.balart@metempsy.com        // enter initial state
9213531Sjairo.balart@metempsy.com        stateGraph.enterState(stateGraph.currState);
9313531Sjairo.balart@metempsy.com    } else {
9413531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen,
9513580Sgabeblack@google.com                "Traffic generator is only active in timing mode\n");
9613531Sjairo.balart@metempsy.com    }
9713531Sjairo.balart@metempsy.com}
9813580Sgabeblack@google.com
9913531Sjairo.balart@metempsy.comvoid
10013531Sjairo.balart@metempsy.comTrafficGen::initState()
10113531Sjairo.balart@metempsy.com{
10213531Sjairo.balart@metempsy.com    // when not restoring from a checkpoint, make sure we kick things off
10313760Sjairo.balart@metempsy.com    if (system->getMemoryMode() == Enums::timing) {
10413531Sjairo.balart@metempsy.com        Tick nextStateGraphEvent = stateGraph.nextEventTick();
10513531Sjairo.balart@metempsy.com        schedule(updateStateGraphEvent, nextStateGraphEvent);
10613531Sjairo.balart@metempsy.com    } else {
10713531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen,
10813531Sjairo.balart@metempsy.com                "Traffic generator is only active in timing mode\n");
10913531Sjairo.balart@metempsy.com    }
11013531Sjairo.balart@metempsy.com}
11113531Sjairo.balart@metempsy.com
11213531Sjairo.balart@metempsy.comunsigned int
11313531Sjairo.balart@metempsy.comTrafficGen::drain(Event* drain_event)
11413531Sjairo.balart@metempsy.com{
11513531Sjairo.balart@metempsy.com    // @todo we should also stop putting new requests in the queue and
11613531Sjairo.balart@metempsy.com    // either interrupt the current state or wait for a transition
11713531Sjairo.balart@metempsy.com    return port.drain(drain_event);
11813531Sjairo.balart@metempsy.com}
11913531Sjairo.balart@metempsy.com
12013531Sjairo.balart@metempsy.comvoid
12113531Sjairo.balart@metempsy.comTrafficGen::serialize(ostream &os)
12213531Sjairo.balart@metempsy.com{
12313531Sjairo.balart@metempsy.com    DPRINTF(Checkpoint, "Serializing TrafficGen\n");
12413531Sjairo.balart@metempsy.com
12513531Sjairo.balart@metempsy.com    // save ticks of the graph event if it is scheduled
12613760Sjairo.balart@metempsy.com    Tick nextStateGraphEvent = updateStateGraphEvent.scheduled() ?
12713531Sjairo.balart@metempsy.com        updateStateGraphEvent.when() : 0;
12813531Sjairo.balart@metempsy.com
12913531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "Saving nextStateGraphEvent=%llu\n",
13013531Sjairo.balart@metempsy.com            nextStateGraphEvent);
13113531Sjairo.balart@metempsy.com
13213531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(nextStateGraphEvent);
13313531Sjairo.balart@metempsy.com
13413531Sjairo.balart@metempsy.com    Tick nextTransitionTick = stateGraph.nextTransitionTick;
13513531Sjairo.balart@metempsy.com    SERIALIZE_SCALAR(nextTransitionTick);
13613531Sjairo.balart@metempsy.com
13713531Sjairo.balart@metempsy.com    // @todo: also serialise the current state, figure out the best
13813531Sjairo.balart@metempsy.com    // way to drain and restore
13913531Sjairo.balart@metempsy.com}
14013531Sjairo.balart@metempsy.com
14113531Sjairo.balart@metempsy.comvoid
14213531Sjairo.balart@metempsy.comTrafficGen::unserialize(Checkpoint* cp, const string& section)
14313531Sjairo.balart@metempsy.com{
14413531Sjairo.balart@metempsy.com    // restore scheduled events
14513531Sjairo.balart@metempsy.com    Tick nextStateGraphEvent;
14613531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(nextStateGraphEvent);
14713531Sjairo.balart@metempsy.com    if (nextStateGraphEvent != 0) {
14813531Sjairo.balart@metempsy.com        schedule(updateStateGraphEvent, nextStateGraphEvent);
14913760Sjairo.balart@metempsy.com    }
15013531Sjairo.balart@metempsy.com
15113531Sjairo.balart@metempsy.com    Tick nextTransitionTick;
15213531Sjairo.balart@metempsy.com    UNSERIALIZE_SCALAR(nextTransitionTick);
15313760Sjairo.balart@metempsy.com    stateGraph.nextTransitionTick = nextTransitionTick;
15413531Sjairo.balart@metempsy.com}
15513531Sjairo.balart@metempsy.com
15613531Sjairo.balart@metempsy.comvoid
15713531Sjairo.balart@metempsy.comTrafficGen::updateStateGraph()
15813531Sjairo.balart@metempsy.com{
15913760Sjairo.balart@metempsy.com    // schedule next update event based on either the next execute
16013531Sjairo.balart@metempsy.com    // tick or the next transition, which ever comes first
16113531Sjairo.balart@metempsy.com    Tick nextStateGraphEvent = stateGraph.nextEventTick();
16213531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "Updating state graph, next event at %lld\n",
16313760Sjairo.balart@metempsy.com            nextStateGraphEvent);
16413531Sjairo.balart@metempsy.com    schedule(updateStateGraphEvent, nextStateGraphEvent);
16513531Sjairo.balart@metempsy.com
16613531Sjairo.balart@metempsy.com    // perform the update associated with the current update event
16713531Sjairo.balart@metempsy.com    stateGraph.update();
16813531Sjairo.balart@metempsy.com}
16913760Sjairo.balart@metempsy.com
17013760Sjairo.balart@metempsy.comvoid
17113760Sjairo.balart@metempsy.comTrafficGen::StateGraph::parseConfig(const string& file_name,
17213739Sgiacomo.travaglini@arm.com                                    MasterID master_id)
17313760Sjairo.balart@metempsy.com{
17413760Sjairo.balart@metempsy.com    // keep track of the transitions parsed to create the matrix when
17513531Sjairo.balart@metempsy.com    // done
17613531Sjairo.balart@metempsy.com    vector<Transition> transitions;
17713531Sjairo.balart@metempsy.com
17813760Sjairo.balart@metempsy.com    // open input file
17913531Sjairo.balart@metempsy.com    ifstream infile;
18013531Sjairo.balart@metempsy.com    infile.open(file_name.c_str(), ifstream::in);
18113531Sjairo.balart@metempsy.com    if (!infile.is_open()) {
18213531Sjairo.balart@metempsy.com        fatal("Traffic generator %s config file not found at %s\n",
18313531Sjairo.balart@metempsy.com              owner.name(), file_name);
18413531Sjairo.balart@metempsy.com    }
18513760Sjairo.balart@metempsy.com
18613760Sjairo.balart@metempsy.com    // read line by line and determine the action based on the first
18713760Sjairo.balart@metempsy.com    // keyword
18813531Sjairo.balart@metempsy.com    string keyword;
18913760Sjairo.balart@metempsy.com    string line;
19013760Sjairo.balart@metempsy.com
19113531Sjairo.balart@metempsy.com    while (getline(infile, line).good()) {
19213531Sjairo.balart@metempsy.com        // see if this line is a comment line, and if so skip it
19313760Sjairo.balart@metempsy.com        if (line.find('#') != 1) {
19413760Sjairo.balart@metempsy.com            // create an input stream for the tokenization
19513760Sjairo.balart@metempsy.com            istringstream is(line);
19613531Sjairo.balart@metempsy.com
19713531Sjairo.balart@metempsy.com            // determine the keyword
19813531Sjairo.balart@metempsy.com            is >> keyword;
19913531Sjairo.balart@metempsy.com
20013531Sjairo.balart@metempsy.com            if (keyword == "STATE") {
20113531Sjairo.balart@metempsy.com                // parse the behaviour of this state
20213531Sjairo.balart@metempsy.com                uint32_t id;
20313531Sjairo.balart@metempsy.com                Tick duration;
20413760Sjairo.balart@metempsy.com                string mode;
20513531Sjairo.balart@metempsy.com
20613531Sjairo.balart@metempsy.com                is >> id >> duration >> mode;
20713531Sjairo.balart@metempsy.com
20813531Sjairo.balart@metempsy.com                if (mode == "TRACE") {
20913531Sjairo.balart@metempsy.com                    string traceFile;
21013760Sjairo.balart@metempsy.com                    Addr addrOffset;
21113531Sjairo.balart@metempsy.com
21213531Sjairo.balart@metempsy.com                    is >> traceFile >> addrOffset;
21313531Sjairo.balart@metempsy.com
21413531Sjairo.balart@metempsy.com                    states[id] = new TraceGen(port, master_id, duration,
21513531Sjairo.balart@metempsy.com                                              traceFile, addrOffset);
21613531Sjairo.balart@metempsy.com                    DPRINTF(TrafficGen, "State: %d TraceGen\n", id);
21713531Sjairo.balart@metempsy.com                } else if (mode == "IDLE") {
21813531Sjairo.balart@metempsy.com                    states[id] = new IdleGen(port, master_id, duration);
21913531Sjairo.balart@metempsy.com                    DPRINTF(TrafficGen, "State: %d IdleGen\n", id);
22013531Sjairo.balart@metempsy.com                } else if (mode == "LINEAR" || mode == "RANDOM") {
22113760Sjairo.balart@metempsy.com                    uint32_t read_percent;
22213531Sjairo.balart@metempsy.com                    Addr start_addr;
22313531Sjairo.balart@metempsy.com                    Addr end_addr;
22413531Sjairo.balart@metempsy.com                    Addr blocksize;
22513531Sjairo.balart@metempsy.com                    Tick min_period;
22613531Sjairo.balart@metempsy.com                    Tick max_period;
22713760Sjairo.balart@metempsy.com                    Addr data_limit;
22813531Sjairo.balart@metempsy.com
22913531Sjairo.balart@metempsy.com                    is >> read_percent >> start_addr >> end_addr >>
23013760Sjairo.balart@metempsy.com                        blocksize >> min_period >> max_period >> data_limit;
23113531Sjairo.balart@metempsy.com
23213531Sjairo.balart@metempsy.com                    DPRINTF(TrafficGen, "%s, addr %x to %x, size %d,"
23313760Sjairo.balart@metempsy.com                            " period %d to %d, %d%% reads\n",
23413531Sjairo.balart@metempsy.com                            mode, start_addr, end_addr, blocksize, min_period,
23513531Sjairo.balart@metempsy.com                            max_period, read_percent);
23613531Sjairo.balart@metempsy.com
23713531Sjairo.balart@metempsy.com                    if (read_percent > 100)
23813531Sjairo.balart@metempsy.com                        panic("%s cannot have more than 100% reads", name());
23913531Sjairo.balart@metempsy.com
24013760Sjairo.balart@metempsy.com                    if (mode == "LINEAR") {
24113531Sjairo.balart@metempsy.com                        states[id] = new LinearGen(port, master_id,
24213531Sjairo.balart@metempsy.com                                                   duration, start_addr,
24313531Sjairo.balart@metempsy.com                                                   end_addr, blocksize,
24413531Sjairo.balart@metempsy.com                                                   min_period, max_period,
24513531Sjairo.balart@metempsy.com                                                   read_percent, data_limit);
24613531Sjairo.balart@metempsy.com                        DPRINTF(TrafficGen, "State: %d LinearGen\n", id);
24713531Sjairo.balart@metempsy.com                    } else if (mode == "RANDOM") {
24813531Sjairo.balart@metempsy.com                        states[id] = new RandomGen(port, master_id,
24913531Sjairo.balart@metempsy.com                                                   duration, start_addr,
25013531Sjairo.balart@metempsy.com                                                   end_addr, blocksize,
25113760Sjairo.balart@metempsy.com                                                   min_period, max_period,
25213531Sjairo.balart@metempsy.com                                                   read_percent, data_limit);
25313531Sjairo.balart@metempsy.com                        DPRINTF(TrafficGen, "State: %d RandomGen\n", id);
25413531Sjairo.balart@metempsy.com                    }
25513531Sjairo.balart@metempsy.com                } else {
25613531Sjairo.balart@metempsy.com                    fatal("%s: Unknown traffic generator mode: %s",
25713760Sjairo.balart@metempsy.com                          name(), mode);
25813531Sjairo.balart@metempsy.com                }
25913531Sjairo.balart@metempsy.com            } else if (keyword == "TRANSITION") {
26013760Sjairo.balart@metempsy.com                Transition transition;
26113531Sjairo.balart@metempsy.com
26213531Sjairo.balart@metempsy.com                is >> transition.from >> transition.to >> transition.p;
26313760Sjairo.balart@metempsy.com
26413531Sjairo.balart@metempsy.com                transitions.push_back(transition);
26513531Sjairo.balart@metempsy.com
26613531Sjairo.balart@metempsy.com                DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from,
26713531Sjairo.balart@metempsy.com                        transition.to);
26813531Sjairo.balart@metempsy.com            } else if (keyword == "INIT") {
26913531Sjairo.balart@metempsy.com                // set the initial state as the active state
27013760Sjairo.balart@metempsy.com                is >> currState;
27113531Sjairo.balart@metempsy.com
27213531Sjairo.balart@metempsy.com                DPRINTF(TrafficGen, "Initial state: %d\n", currState);
27313531Sjairo.balart@metempsy.com            }
27413531Sjairo.balart@metempsy.com        }
27513531Sjairo.balart@metempsy.com    }
27613531Sjairo.balart@metempsy.com
27713531Sjairo.balart@metempsy.com    // resize and populate state transition matrix
27813531Sjairo.balart@metempsy.com    transitionMatrix.resize(transitions.size());
27913760Sjairo.balart@metempsy.com    for (size_t i = 0; i < transitions.size(); i++) {
28013531Sjairo.balart@metempsy.com        transitionMatrix[i].resize(transitions.size());
28113760Sjairo.balart@metempsy.com    }
28213760Sjairo.balart@metempsy.com
28313760Sjairo.balart@metempsy.com    for (vector<Transition>::iterator t = transitions.begin();
28413760Sjairo.balart@metempsy.com         t != transitions.end(); ++t) {
28513760Sjairo.balart@metempsy.com        transitionMatrix[t->from][t->to] = t->p;
28613531Sjairo.balart@metempsy.com    }
28713531Sjairo.balart@metempsy.com
28813531Sjairo.balart@metempsy.com    // ensure the egress edges do not have a probability larger than
28913531Sjairo.balart@metempsy.com    // one
29013531Sjairo.balart@metempsy.com    for (size_t i = 0; i < transitions.size(); i++) {
29113531Sjairo.balart@metempsy.com        double sum = 0;
29213531Sjairo.balart@metempsy.com        for (size_t j = 0; j < transitions.size(); j++) {
29313760Sjairo.balart@metempsy.com            sum += transitionMatrix[i][j];
29413760Sjairo.balart@metempsy.com        }
29513760Sjairo.balart@metempsy.com
29613760Sjairo.balart@metempsy.com        // avoid comparing floating point numbers
29713760Sjairo.balart@metempsy.com        if (abs(sum - 1.0) > 0.001)
29813531Sjairo.balart@metempsy.com            fatal("%s has transition probability != 1 for state %d\n",
29913531Sjairo.balart@metempsy.com                  name(), i);
30013531Sjairo.balart@metempsy.com    }
30113531Sjairo.balart@metempsy.com
30213531Sjairo.balart@metempsy.com    // close input file
30313760Sjairo.balart@metempsy.com    infile.close();
30413760Sjairo.balart@metempsy.com}
30513760Sjairo.balart@metempsy.com
30613760Sjairo.balart@metempsy.comvoid
30713760Sjairo.balart@metempsy.comTrafficGen::StateGraph::update()
30813531Sjairo.balart@metempsy.com{
30913531Sjairo.balart@metempsy.com    // if we have reached the time for the next state transition, then
31013531Sjairo.balart@metempsy.com    // perform the transition
31113531Sjairo.balart@metempsy.com    if (curTick() >= nextTransitionTick) {
31213531Sjairo.balart@metempsy.com        transition();
31313531Sjairo.balart@metempsy.com    } else {
31413531Sjairo.balart@metempsy.com        // we are still in the current state and should execute it
31513531Sjairo.balart@metempsy.com        states[currState]->execute();
31613531Sjairo.balart@metempsy.com    }
31713531Sjairo.balart@metempsy.com}
31813531Sjairo.balart@metempsy.com
31913531Sjairo.balart@metempsy.comvoid
32013531Sjairo.balart@metempsy.comTrafficGen::StateGraph::transition()
32113531Sjairo.balart@metempsy.com{
32213531Sjairo.balart@metempsy.com    // exit the current state
32313531Sjairo.balart@metempsy.com    states[currState]->exit();
32413531Sjairo.balart@metempsy.com
32513531Sjairo.balart@metempsy.com    // determine next state
32613531Sjairo.balart@metempsy.com    double p = random_mt.gen_real1();
32713531Sjairo.balart@metempsy.com    assert(currState < transitionMatrix.size());
32813531Sjairo.balart@metempsy.com    double cumulative = transitionMatrix[currState][0];
32913531Sjairo.balart@metempsy.com    size_t i = 1;
33013531Sjairo.balart@metempsy.com    while (p < cumulative && i != transitionMatrix[currState].size()) {
33113760Sjairo.balart@metempsy.com        cumulative += transitionMatrix[currState][i];
33213760Sjairo.balart@metempsy.com        ++i;
33313760Sjairo.balart@metempsy.com    }
33413531Sjairo.balart@metempsy.com    enterState(i);
33513531Sjairo.balart@metempsy.com}
33613531Sjairo.balart@metempsy.com
33713531Sjairo.balart@metempsy.comvoid
33813760Sjairo.balart@metempsy.comTrafficGen::StateGraph::enterState(uint32_t newState)
33913531Sjairo.balart@metempsy.com{
34013531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "Transition to state %d\n", newState);
34113531Sjairo.balart@metempsy.com
34213760Sjairo.balart@metempsy.com    currState = newState;
34313760Sjairo.balart@metempsy.com    nextTransitionTick += states[currState]->duration;
34413531Sjairo.balart@metempsy.com    states[currState]->enter();
34513531Sjairo.balart@metempsy.com}
34613531Sjairo.balart@metempsy.com
34713531Sjairo.balart@metempsy.comTrafficGen::StateGraph::BaseGen::BaseGen(QueuedMasterPort& _port,
34813531Sjairo.balart@metempsy.com                                         MasterID master_id,
34913531Sjairo.balart@metempsy.com                                         Tick _duration)
35013531Sjairo.balart@metempsy.com    : port(_port), masterID(master_id), duration(_duration)
35113760Sjairo.balart@metempsy.com{
35213531Sjairo.balart@metempsy.com}
35313760Sjairo.balart@metempsy.com
35413531Sjairo.balart@metempsy.comvoid
35513531Sjairo.balart@metempsy.comTrafficGen::StateGraph::LinearGen::enter()
35613531Sjairo.balart@metempsy.com{
35713531Sjairo.balart@metempsy.com    // reset the address and the data counter
35813531Sjairo.balart@metempsy.com    nextAddr = startAddr;
35913531Sjairo.balart@metempsy.com    dataManipulated = 0;
36013531Sjairo.balart@metempsy.com
36113531Sjairo.balart@metempsy.com    // this test only needs to happen once, but cannot be performed
36213531Sjairo.balart@metempsy.com    // before init() is called and the ports are connected
36313531Sjairo.balart@metempsy.com    if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
36413531Sjairo.balart@metempsy.com        fatal("TrafficGen %s block size (%d) is larger than port"
36513531Sjairo.balart@metempsy.com              " block size (%d)\n", blocksize, port.deviceBlockSize());
36613531Sjairo.balart@metempsy.com
36713531Sjairo.balart@metempsy.com}
36813760Sjairo.balart@metempsy.com
36913531Sjairo.balart@metempsy.comvoid
37013760Sjairo.balart@metempsy.comTrafficGen::StateGraph::LinearGen::execute()
37113760Sjairo.balart@metempsy.com{
37213760Sjairo.balart@metempsy.com    // choose if we generate a read or a write here
37313531Sjairo.balart@metempsy.com    bool isRead = random_mt.random<uint8_t>(0, 100) < readPercent;
37413531Sjairo.balart@metempsy.com
37513531Sjairo.balart@metempsy.com    if (readPercent == 0)
37613760Sjairo.balart@metempsy.com        assert(!isRead);
37713760Sjairo.balart@metempsy.com
37813760Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n",
37913531Sjairo.balart@metempsy.com            isRead ? 'r' : 'w', nextAddr, blocksize);
38013760Sjairo.balart@metempsy.com
38113760Sjairo.balart@metempsy.com    // Create new request
38213531Sjairo.balart@metempsy.com    Request::Flags flags;
38313531Sjairo.balart@metempsy.com    Request *req = new Request(nextAddr, blocksize, flags, masterID);
38413760Sjairo.balart@metempsy.com
38513760Sjairo.balart@metempsy.com    PacketPtr pkt = new Packet(req, isRead ? MemCmd::ReadReq :
38613760Sjairo.balart@metempsy.com                               MemCmd::WriteReq);
38713531Sjairo.balart@metempsy.com
38813531Sjairo.balart@metempsy.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
38913531Sjairo.balart@metempsy.com    pkt->dataDynamicArray(pkt_data);
39013531Sjairo.balart@metempsy.com
39113531Sjairo.balart@metempsy.com    if (!isRead) {
39213531Sjairo.balart@metempsy.com        memset(pkt_data, 0xA, req->getSize());
39313760Sjairo.balart@metempsy.com    }
39413531Sjairo.balart@metempsy.com
39513760Sjairo.balart@metempsy.com    port.schedTimingReq(pkt, curTick());
39613531Sjairo.balart@metempsy.com
39713531Sjairo.balart@metempsy.com    // increment the address
39813531Sjairo.balart@metempsy.com    nextAddr += blocksize;
39913531Sjairo.balart@metempsy.com
40013531Sjairo.balart@metempsy.com    // Add the amount of data manipulated to the total
40113531Sjairo.balart@metempsy.com    dataManipulated += blocksize;
40213531Sjairo.balart@metempsy.com}
40313531Sjairo.balart@metempsy.com
40413531Sjairo.balart@metempsy.comTick
40513531Sjairo.balart@metempsy.comTrafficGen::StateGraph::LinearGen::nextExecuteTick()
40613531Sjairo.balart@metempsy.com{
40713531Sjairo.balart@metempsy.com    // If we have reached the end of the address space, reset the
40813531Sjairo.balart@metempsy.com    // address to the start of the range
40913531Sjairo.balart@metempsy.com    if (nextAddr + blocksize > endAddr) {
41013531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen, "Wrapping address to the start of "
41113531Sjairo.balart@metempsy.com                "the range\n");
41213531Sjairo.balart@metempsy.com        nextAddr = startAddr;
41313531Sjairo.balart@metempsy.com    }
41413531Sjairo.balart@metempsy.com
41513531Sjairo.balart@metempsy.com    // Check to see if we have reached the data limit. If dataLimit is
41613531Sjairo.balart@metempsy.com    // zero we do not have a data limit and therefore we will keep
41713760Sjairo.balart@metempsy.com    // generating requests for the entire residency in this state.
41813531Sjairo.balart@metempsy.com    if (dataLimit && dataManipulated >= dataLimit) {
41913531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen, "Data limit for LinearGen reached.\n");
42013531Sjairo.balart@metempsy.com        // there are no more requests, therefore return MaxTick
42113531Sjairo.balart@metempsy.com        return MaxTick;
42213531Sjairo.balart@metempsy.com    } else {
42313760Sjairo.balart@metempsy.com        // return the time when the next request should take place
42413531Sjairo.balart@metempsy.com        return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
42513531Sjairo.balart@metempsy.com    }
42613760Sjairo.balart@metempsy.com}
42713760Sjairo.balart@metempsy.com
42813531Sjairo.balart@metempsy.comvoid
42913531Sjairo.balart@metempsy.comTrafficGen::StateGraph::RandomGen::enter()
43013760Sjairo.balart@metempsy.com{
43113531Sjairo.balart@metempsy.com    // reset the counter to zero
43213531Sjairo.balart@metempsy.com    dataManipulated = 0;
43313531Sjairo.balart@metempsy.com
43413531Sjairo.balart@metempsy.com    // this test only needs to happen once, but cannot be performed
43513531Sjairo.balart@metempsy.com    // before init() is called and the ports are connected
43613760Sjairo.balart@metempsy.com    if (port.deviceBlockSize() && blocksize > port.deviceBlockSize())
43713531Sjairo.balart@metempsy.com        fatal("TrafficGen %s block size (%d) is larger than port"
43813760Sjairo.balart@metempsy.com              " block size (%d)\n", name(), blocksize, port.deviceBlockSize());
43913531Sjairo.balart@metempsy.com}
44013531Sjairo.balart@metempsy.com
44113531Sjairo.balart@metempsy.comvoid
44213531Sjairo.balart@metempsy.comTrafficGen::StateGraph::RandomGen::execute()
44313531Sjairo.balart@metempsy.com{
44413531Sjairo.balart@metempsy.com    // choose if we generate a read or a write here
44513531Sjairo.balart@metempsy.com    bool isRead = random_mt.random<uint8_t>(0, 100) < readPercent;
44613531Sjairo.balart@metempsy.com
44713531Sjairo.balart@metempsy.com    if (readPercent == 0)
44813760Sjairo.balart@metempsy.com        assert(!isRead);
44913531Sjairo.balart@metempsy.com
45013760Sjairo.balart@metempsy.com    // address of the request
45113531Sjairo.balart@metempsy.com    Addr addr = random_mt.random<Addr>(startAddr, endAddr - 1);
45213531Sjairo.balart@metempsy.com
45313531Sjairo.balart@metempsy.com    // round down to start address of block
45413531Sjairo.balart@metempsy.com    addr -= addr % blocksize;
45513531Sjairo.balart@metempsy.com
45613531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "RandomGen::execute: %c to addr %x, size %d\n",
45713531Sjairo.balart@metempsy.com            isRead ? 'r' : 'w', addr, blocksize);
45813531Sjairo.balart@metempsy.com
45913531Sjairo.balart@metempsy.com    // create new request packet
46013531Sjairo.balart@metempsy.com    Request::Flags flags;
46113531Sjairo.balart@metempsy.com    Request *req = new Request(addr, blocksize, flags, masterID);
46213531Sjairo.balart@metempsy.com
46313531Sjairo.balart@metempsy.com    PacketPtr pkt = new Packet(req, isRead ? MemCmd::ReadReq :
46413531Sjairo.balart@metempsy.com                               MemCmd::WriteReq);
46513531Sjairo.balart@metempsy.com
46613531Sjairo.balart@metempsy.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
46713531Sjairo.balart@metempsy.com    pkt->dataDynamicArray(pkt_data);
46813531Sjairo.balart@metempsy.com
46913531Sjairo.balart@metempsy.com    if (!isRead) {
47013531Sjairo.balart@metempsy.com        memset(pkt_data, 0xA, req->getSize());
47113531Sjairo.balart@metempsy.com    }
47213760Sjairo.balart@metempsy.com
47313531Sjairo.balart@metempsy.com    port.schedTimingReq(pkt, curTick());
47413531Sjairo.balart@metempsy.com
47513531Sjairo.balart@metempsy.com    // Add the amount of data manipulated to the total
47613531Sjairo.balart@metempsy.com    dataManipulated += blocksize;
47713531Sjairo.balart@metempsy.com}
47813760Sjairo.balart@metempsy.com
47913531Sjairo.balart@metempsy.comTick
48013531Sjairo.balart@metempsy.comTrafficGen::StateGraph::RandomGen::nextExecuteTick()
48113760Sjairo.balart@metempsy.com{
48213760Sjairo.balart@metempsy.com    // Check to see if we have reached the data limit. If dataLimit is
48313531Sjairo.balart@metempsy.com    // zero we do not have a data limit and therefore we will keep
48413531Sjairo.balart@metempsy.com    // generating requests for the entire residency in this state.
48513760Sjairo.balart@metempsy.com    if (dataLimit && dataManipulated >= dataLimit)
48613531Sjairo.balart@metempsy.com    {
48713531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen, "Data limit for RandomGen reached.\n");
48813531Sjairo.balart@metempsy.com        // No more requests. Return MaxTick.
48913531Sjairo.balart@metempsy.com        return MaxTick;
49013531Sjairo.balart@metempsy.com    } else {
49113760Sjairo.balart@metempsy.com        // Return the time when the next request should take place.
49213531Sjairo.balart@metempsy.com        return curTick() + random_mt.random<Tick>(minPeriod, maxPeriod);
49313760Sjairo.balart@metempsy.com    }
49413531Sjairo.balart@metempsy.com}
49513531Sjairo.balart@metempsy.com
49613531Sjairo.balart@metempsy.comTick
49713531Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::nextExecuteTick() {
49813531Sjairo.balart@metempsy.com    // We need to look at the next line to calculate the next time an
49913531Sjairo.balart@metempsy.com    // event occurs, or potentially return MaxTick to signal that
50013531Sjairo.balart@metempsy.com    // nothing has to be done.
50113531Sjairo.balart@metempsy.com    string buffer;
50213531Sjairo.balart@metempsy.com    if (!traceComplete && trace.good()){
50313760Sjairo.balart@metempsy.com        getline(trace, buffer);
50413531Sjairo.balart@metempsy.com        DPRINTF(TrafficGen, "Input trace: %s\n", buffer);
50513760Sjairo.balart@metempsy.com    } else {
50613531Sjairo.balart@metempsy.com        // We are at the end of the file, thus we have no more data in
50713531Sjairo.balart@metempsy.com        // the trace Return MaxTick to signal that there will be no
50813531Sjairo.balart@metempsy.com        // more transactions in this active period for the state.
50913531Sjairo.balart@metempsy.com        return MaxTick;
51013531Sjairo.balart@metempsy.com    }
51113760Sjairo.balart@metempsy.com
51213760Sjairo.balart@metempsy.com    //Reset the nextElement to the default values
51313760Sjairo.balart@metempsy.com    currElement = nextElement;
51413760Sjairo.balart@metempsy.com    nextElement.clear();
51513760Sjairo.balart@metempsy.com
51613760Sjairo.balart@metempsy.com    // Check that we have something to process. This assume no EOF at
51713760Sjairo.balart@metempsy.com    // the end of the line.
51813760Sjairo.balart@metempsy.com    if (buffer.size() > 0 && !trace.eof()) {
51913760Sjairo.balart@metempsy.com        istringstream iss(buffer);
52013760Sjairo.balart@metempsy.com
52113760Sjairo.balart@metempsy.com        char rOrW, ch;
52213531Sjairo.balart@metempsy.com        iss >> rOrW;
52313531Sjairo.balart@metempsy.com        iss >> ch; assert(ch == ',');
52413760Sjairo.balart@metempsy.com        iss >> nextElement.addr;
52513531Sjairo.balart@metempsy.com        iss >> ch; assert(ch == ',');
52613531Sjairo.balart@metempsy.com        iss >> nextElement.blocksize;
52713531Sjairo.balart@metempsy.com        iss >> ch; assert(ch == ',');
52813531Sjairo.balart@metempsy.com        iss >> nextElement.tick;
52913760Sjairo.balart@metempsy.com
53013760Sjairo.balart@metempsy.com        if (rOrW == 'r') {
53113760Sjairo.balart@metempsy.com            nextElement.cmd = MemCmd::ReadReq;
53213760Sjairo.balart@metempsy.com        } else if (rOrW == 'w') {
53313760Sjairo.balart@metempsy.com            nextElement.cmd = MemCmd::WriteReq;
53413760Sjairo.balart@metempsy.com        } else {
53513531Sjairo.balart@metempsy.com            fatal("Incorrect trace file format!\n");
53613760Sjairo.balart@metempsy.com        }
53713760Sjairo.balart@metempsy.com    }
53813760Sjairo.balart@metempsy.com
53913760Sjairo.balart@metempsy.com    // Check that we have a valid request
54013760Sjairo.balart@metempsy.com    if (!nextElement.isValid()) {
54113760Sjairo.balart@metempsy.com        // If it is not valid, assume that we have reached the end of
54213760Sjairo.balart@metempsy.com        // the trace.  Even if this is not the case, we do not know
54313760Sjairo.balart@metempsy.com        // what to do with the request as it makes no sense.
54413760Sjairo.balart@metempsy.com        if (trace.good()) {
54513760Sjairo.balart@metempsy.com            // Trace is good, therefore we are not at the end of the
54613760Sjairo.balart@metempsy.com            // file. This means that the input trace cannot be read
54713760Sjairo.balart@metempsy.com            // correctly or it contains data that makes no sense.
54813760Sjairo.balart@metempsy.com            warn("Unable to read the trace file format\n");
54913760Sjairo.balart@metempsy.com            warn("%s", buffer);
55013760Sjairo.balart@metempsy.com        }
55113760Sjairo.balart@metempsy.com
55213760Sjairo.balart@metempsy.com        traceComplete = true;
55313760Sjairo.balart@metempsy.com        return MaxTick;
55413760Sjairo.balart@metempsy.com    }
55513760Sjairo.balart@metempsy.com
55613760Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "currElement: %c addr %d size %d tick %d (%d)\n",
55713760Sjairo.balart@metempsy.com            currElement.cmd.isRead() ? 'r' : 'w',
55813760Sjairo.balart@metempsy.com            currElement.addr,
55913760Sjairo.balart@metempsy.com            currElement.blocksize,
56013531Sjairo.balart@metempsy.com            currElement.tick + tickOffset,
56113760Sjairo.balart@metempsy.com            currElement.tick);
56213760Sjairo.balart@metempsy.com
56313531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "nextElement: %c addr %d size %d tick %d (%d)\n",
56413531Sjairo.balart@metempsy.com            nextElement.cmd.isRead() ? 'r' : 'w',
56513531Sjairo.balart@metempsy.com            nextElement.addr,
56613760Sjairo.balart@metempsy.com            nextElement.blocksize,
56713760Sjairo.balart@metempsy.com            nextElement.tick + tickOffset,
56813760Sjairo.balart@metempsy.com            nextElement.tick);
56913760Sjairo.balart@metempsy.com
57013760Sjairo.balart@metempsy.com    return tickOffset + nextElement.tick;
57113760Sjairo.balart@metempsy.com}
57213531Sjairo.balart@metempsy.com
57313531Sjairo.balart@metempsy.comvoid
57413760Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::enter() {
57513760Sjairo.balart@metempsy.com    // update the trace offset to the time where the state was entered.
57613760Sjairo.balart@metempsy.com    tickOffset = curTick();
57713760Sjairo.balart@metempsy.com
57813760Sjairo.balart@metempsy.com    // seek to the start of the input trace file
57913760Sjairo.balart@metempsy.com    trace.seekg(0, ifstream::beg);
58013760Sjairo.balart@metempsy.com    trace.clear();
58113760Sjairo.balart@metempsy.com
58213531Sjairo.balart@metempsy.com    // clear everything
58313531Sjairo.balart@metempsy.com    nextElement.clear();
58413531Sjairo.balart@metempsy.com    currElement.clear();
58513760Sjairo.balart@metempsy.com
58613531Sjairo.balart@metempsy.com    traceComplete = false;
58713760Sjairo.balart@metempsy.com}
58813760Sjairo.balart@metempsy.com
58913760Sjairo.balart@metempsy.comvoid
59013760Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::execute() {
59113760Sjairo.balart@metempsy.com    // it is the responsibility of nextExecuteTick to prevent the
59213760Sjairo.balart@metempsy.com    // state graph from executing the state if it should not
59313760Sjairo.balart@metempsy.com    assert(currElement.isValid());
59413531Sjairo.balart@metempsy.com
59513531Sjairo.balart@metempsy.com    DPRINTF(TrafficGen, "TraceGen::execute: %c %d %d %d\n",
59613531Sjairo.balart@metempsy.com            currElement.cmd.isRead() ? 'r' : 'w',
59713760Sjairo.balart@metempsy.com            currElement.addr,
59813531Sjairo.balart@metempsy.com            currElement.blocksize,
59913531Sjairo.balart@metempsy.com            currElement.tick);
60013760Sjairo.balart@metempsy.com
60113760Sjairo.balart@metempsy.com    Request::Flags flags;
60213760Sjairo.balart@metempsy.com    Request *req = new Request(currElement.addr + addrOffset,
60313760Sjairo.balart@metempsy.com                               currElement.blocksize, flags, masterID);
60413760Sjairo.balart@metempsy.com
60513760Sjairo.balart@metempsy.com    PacketPtr pkt = new Packet(req, currElement.cmd);
60613760Sjairo.balart@metempsy.com
60713531Sjairo.balart@metempsy.com    uint8_t* pkt_data = new uint8_t[req->getSize()];
60813531Sjairo.balart@metempsy.com    pkt->dataDynamicArray(pkt_data);
60913760Sjairo.balart@metempsy.com
61013760Sjairo.balart@metempsy.com    if (currElement.cmd.isWrite()) {
61113760Sjairo.balart@metempsy.com        memset(pkt_data, 0xA, req->getSize());
61213760Sjairo.balart@metempsy.com    }
61313760Sjairo.balart@metempsy.com
61413760Sjairo.balart@metempsy.com    port.schedTimingReq(pkt, curTick());
61513760Sjairo.balart@metempsy.com}
61613760Sjairo.balart@metempsy.com
61713760Sjairo.balart@metempsy.comvoid
61813531Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::exit() {
61913531Sjairo.balart@metempsy.com    // Check if we reached the end of the trace file. If we did not
62013531Sjairo.balart@metempsy.com    // then we want to generate a warning stating that not the entire
62113760Sjairo.balart@metempsy.com    // trace was played.
62213531Sjairo.balart@metempsy.com    if (!trace.eof()) {
62313531Sjairo.balart@metempsy.com        warn("Trace player %s was unable to replay the entire trace!\n",
62413531Sjairo.balart@metempsy.com             name());
62513531Sjairo.balart@metempsy.com    }
62613760Sjairo.balart@metempsy.com
62713531Sjairo.balart@metempsy.com    // clear any previous error flags for the input trace file
62813531Sjairo.balart@metempsy.com    trace.clear();
62913531Sjairo.balart@metempsy.com}
63013531Sjairo.balart@metempsy.com
63113760Sjairo.balart@metempsy.combool
63213531Sjairo.balart@metempsy.comTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt)
63313531Sjairo.balart@metempsy.com{
63413531Sjairo.balart@metempsy.com    delete pkt->req;
63513531Sjairo.balart@metempsy.com    delete pkt;
63613760Sjairo.balart@metempsy.com
63713531Sjairo.balart@metempsy.com    return true;
63813760Sjairo.balart@metempsy.com}
63913760Sjairo.balart@metempsy.com