traffic_gen.cc revision 9342:6fec8f26e56d
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} 6813531Sjairo.balart@metempsy.com 6913531Sjairo.balart@metempsy.comBaseMasterPort& 7013531Sjairo.balart@metempsy.comTrafficGen::getMasterPort(const string& if_name, PortID 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{ 8213531Sjairo.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, 9513531Sjairo.balart@metempsy.com "Traffic generator is only active in timing mode\n"); 9613531Sjairo.balart@metempsy.com } 9713531Sjairo.balart@metempsy.com} 9813531Sjairo.balart@metempsy.com 9913580Sgabeblack@google.comvoid 10013531Sjairo.balart@metempsy.comTrafficGen::initState() 10113531Sjairo.balart@metempsy.com{ 10213580Sgabeblack@google.com // when not restoring from a checkpoint, make sure we kick things off 10313531Sjairo.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(DrainManager *dm) 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(dm); 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 12613531Sjairo.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); 14913531Sjairo.balart@metempsy.com } 15013531Sjairo.balart@metempsy.com 15113531Sjairo.balart@metempsy.com Tick nextTransitionTick; 15213531Sjairo.balart@metempsy.com UNSERIALIZE_SCALAR(nextTransitionTick); 15313531Sjairo.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{ 15913531Sjairo.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", 16313531Sjairo.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} 16913531Sjairo.balart@metempsy.com 17013531Sjairo.balart@metempsy.comvoid 17113531Sjairo.balart@metempsy.comTrafficGen::StateGraph::parseConfig(const string& file_name, 17213531Sjairo.balart@metempsy.com MasterID master_id) 17313531Sjairo.balart@metempsy.com{ 17413531Sjairo.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 17813531Sjairo.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 } 18513531Sjairo.balart@metempsy.com 18613531Sjairo.balart@metempsy.com // read line by line and determine the action based on the first 18713531Sjairo.balart@metempsy.com // keyword 18813531Sjairo.balart@metempsy.com string keyword; 18913531Sjairo.balart@metempsy.com string line; 19013531Sjairo.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 19313531Sjairo.balart@metempsy.com if (line.find('#') != 1) { 19413531Sjairo.balart@metempsy.com // create an input stream for the tokenization 19513531Sjairo.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; 20413531Sjairo.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; 21013531Sjairo.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") { 22113531Sjairo.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; 22713531Sjairo.balart@metempsy.com Addr data_limit; 22813531Sjairo.balart@metempsy.com 22913531Sjairo.balart@metempsy.com is >> read_percent >> start_addr >> end_addr >> 23013531Sjairo.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," 23313531Sjairo.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) 23813580Sgabeblack@google.com panic("%s cannot have more than 100% reads", name()); 23913531Sjairo.balart@metempsy.com 24013531Sjairo.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, 25113531Sjairo.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", 25713531Sjairo.balart@metempsy.com name(), mode); 25813531Sjairo.balart@metempsy.com } 25913531Sjairo.balart@metempsy.com } else if (keyword == "TRANSITION") { 26013531Sjairo.balart@metempsy.com Transition transition; 26113531Sjairo.balart@metempsy.com 26213531Sjairo.balart@metempsy.com is >> transition.from >> transition.to >> transition.p; 26313531Sjairo.balart@metempsy.com 26413531Sjairo.balart@metempsy.com transitions.push_back(transition); 26513531Sjairo.balart@metempsy.com 26613580Sgabeblack@google.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 27013531Sjairo.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()); 27913531Sjairo.balart@metempsy.com for (size_t i = 0; i < transitions.size(); i++) { 28013531Sjairo.balart@metempsy.com transitionMatrix[i].resize(transitions.size()); 28113531Sjairo.balart@metempsy.com } 28213531Sjairo.balart@metempsy.com 28313531Sjairo.balart@metempsy.com for (vector<Transition>::iterator t = transitions.begin(); 28413531Sjairo.balart@metempsy.com t != transitions.end(); ++t) { 28513531Sjairo.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++) { 29313531Sjairo.balart@metempsy.com sum += transitionMatrix[i][j]; 29413531Sjairo.balart@metempsy.com } 29513531Sjairo.balart@metempsy.com 29613531Sjairo.balart@metempsy.com // avoid comparing floating point numbers 29713531Sjairo.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 30313531Sjairo.balart@metempsy.com infile.close(); 30413531Sjairo.balart@metempsy.com} 30513531Sjairo.balart@metempsy.com 30613531Sjairo.balart@metempsy.comvoid 30713531Sjairo.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()) { 33113531Sjairo.balart@metempsy.com cumulative += transitionMatrix[currState][i]; 33213531Sjairo.balart@metempsy.com ++i; 33313531Sjairo.balart@metempsy.com } 33413531Sjairo.balart@metempsy.com enterState(i); 33513531Sjairo.balart@metempsy.com} 33613531Sjairo.balart@metempsy.com 33713531Sjairo.balart@metempsy.comvoid 33813531Sjairo.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 34213531Sjairo.balart@metempsy.com currState = newState; 34313580Sgabeblack@google.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) 35113531Sjairo.balart@metempsy.com{ 35213531Sjairo.balart@metempsy.com} 35313531Sjairo.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} 36813531Sjairo.balart@metempsy.com 36913531Sjairo.balart@metempsy.comvoid 37013531Sjairo.balart@metempsy.comTrafficGen::StateGraph::LinearGen::execute() 37113531Sjairo.balart@metempsy.com{ 37213531Sjairo.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) 37613531Sjairo.balart@metempsy.com assert(!isRead); 37713531Sjairo.balart@metempsy.com 37813531Sjairo.balart@metempsy.com DPRINTF(TrafficGen, "LinearGen::execute: %c to addr %x, size %d\n", 37913531Sjairo.balart@metempsy.com isRead ? 'r' : 'w', nextAddr, blocksize); 38013531Sjairo.balart@metempsy.com 38113531Sjairo.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); 38413531Sjairo.balart@metempsy.com 38513531Sjairo.balart@metempsy.com PacketPtr pkt = new Packet(req, isRead ? MemCmd::ReadReq : 38613531Sjairo.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()); 39313531Sjairo.balart@metempsy.com } 39413531Sjairo.balart@metempsy.com 39513531Sjairo.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 41713531Sjairo.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 { 42313580Sgabeblack@google.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 } 42613531Sjairo.balart@metempsy.com} 42713531Sjairo.balart@metempsy.com 42813531Sjairo.balart@metempsy.comvoid 42913531Sjairo.balart@metempsy.comTrafficGen::StateGraph::RandomGen::enter() 43013531Sjairo.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 43613531Sjairo.balart@metempsy.com if (port.deviceBlockSize() && blocksize > port.deviceBlockSize()) 43713531Sjairo.balart@metempsy.com fatal("TrafficGen %s block size (%d) is larger than port" 43813531Sjairo.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) 44813531Sjairo.balart@metempsy.com assert(!isRead); 44913531Sjairo.balart@metempsy.com 45013531Sjairo.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 } 47213531Sjairo.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 47613580Sgabeblack@google.com dataManipulated += blocksize; 47713531Sjairo.balart@metempsy.com} 47813531Sjairo.balart@metempsy.com 47913531Sjairo.balart@metempsy.comTick 48013531Sjairo.balart@metempsy.comTrafficGen::StateGraph::RandomGen::nextExecuteTick() 48113531Sjairo.balart@metempsy.com{ 48213531Sjairo.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. 48513531Sjairo.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 { 49113531Sjairo.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); 49313531Sjairo.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()){ 50313531Sjairo.balart@metempsy.com getline(trace, buffer); 50413531Sjairo.balart@metempsy.com DPRINTF(TrafficGen, "Input trace: %s\n", buffer); 50513531Sjairo.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. 50913580Sgabeblack@google.com return MaxTick; 51013531Sjairo.balart@metempsy.com } 51113531Sjairo.balart@metempsy.com 51213531Sjairo.balart@metempsy.com //Reset the nextElement to the default values 51313531Sjairo.balart@metempsy.com currElement = nextElement; 51413531Sjairo.balart@metempsy.com nextElement.clear(); 51513531Sjairo.balart@metempsy.com 51613580Sgabeblack@google.com // Check that we have something to process. This assume no EOF at 51713531Sjairo.balart@metempsy.com // the end of the line. 51813531Sjairo.balart@metempsy.com if (buffer.size() > 0 && !trace.eof()) { 51913531Sjairo.balart@metempsy.com istringstream iss(buffer); 52013531Sjairo.balart@metempsy.com 52113531Sjairo.balart@metempsy.com char rOrW, ch; 52213531Sjairo.balart@metempsy.com iss >> rOrW; 52313580Sgabeblack@google.com iss >> ch; assert(ch == ','); 52413531Sjairo.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; 52913531Sjairo.balart@metempsy.com 53013531Sjairo.balart@metempsy.com if (rOrW == 'r') { 53113531Sjairo.balart@metempsy.com nextElement.cmd = MemCmd::ReadReq; 53213531Sjairo.balart@metempsy.com } else if (rOrW == 'w') { 53313531Sjairo.balart@metempsy.com nextElement.cmd = MemCmd::WriteReq; 53413531Sjairo.balart@metempsy.com } else { 53513531Sjairo.balart@metempsy.com fatal("Incorrect trace file format!\n"); 53613531Sjairo.balart@metempsy.com } 53713531Sjairo.balart@metempsy.com } 53813531Sjairo.balart@metempsy.com 53913531Sjairo.balart@metempsy.com // Check that we have a valid request 54013531Sjairo.balart@metempsy.com if (!nextElement.isValid()) { 54113531Sjairo.balart@metempsy.com // If it is not valid, assume that we have reached the end of 54213531Sjairo.balart@metempsy.com // the trace. Even if this is not the case, we do not know 54313531Sjairo.balart@metempsy.com // what to do with the request as it makes no sense. 54413531Sjairo.balart@metempsy.com if (trace.good()) { 54513531Sjairo.balart@metempsy.com // Trace is good, therefore we are not at the end of the 54613531Sjairo.balart@metempsy.com // file. This means that the input trace cannot be read 54713531Sjairo.balart@metempsy.com // correctly or it contains data that makes no sense. 54813531Sjairo.balart@metempsy.com warn("Unable to read the trace file format\n"); 54913531Sjairo.balart@metempsy.com warn("%s", buffer); 55013531Sjairo.balart@metempsy.com } 55113531Sjairo.balart@metempsy.com 55213531Sjairo.balart@metempsy.com traceComplete = true; 55313531Sjairo.balart@metempsy.com return MaxTick; 55413531Sjairo.balart@metempsy.com } 55513531Sjairo.balart@metempsy.com 55613531Sjairo.balart@metempsy.com DPRINTF(TrafficGen, "currElement: %c addr %d size %d tick %d (%d)\n", 55713531Sjairo.balart@metempsy.com currElement.cmd.isRead() ? 'r' : 'w', 55813531Sjairo.balart@metempsy.com currElement.addr, 55913531Sjairo.balart@metempsy.com currElement.blocksize, 56013531Sjairo.balart@metempsy.com currElement.tick + tickOffset, 56113531Sjairo.balart@metempsy.com currElement.tick); 56213531Sjairo.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, 56613531Sjairo.balart@metempsy.com nextElement.blocksize, 56713531Sjairo.balart@metempsy.com nextElement.tick + tickOffset, 56813531Sjairo.balart@metempsy.com nextElement.tick); 56913531Sjairo.balart@metempsy.com 57013531Sjairo.balart@metempsy.com return tickOffset + nextElement.tick; 57113531Sjairo.balart@metempsy.com} 57213531Sjairo.balart@metempsy.com 57313531Sjairo.balart@metempsy.comvoid 57413531Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::enter() { 57513531Sjairo.balart@metempsy.com // update the trace offset to the time where the state was entered. 57613531Sjairo.balart@metempsy.com tickOffset = curTick(); 57713531Sjairo.balart@metempsy.com 57813531Sjairo.balart@metempsy.com // seek to the start of the input trace file 57913531Sjairo.balart@metempsy.com trace.seekg(0, ifstream::beg); 58013531Sjairo.balart@metempsy.com trace.clear(); 58113531Sjairo.balart@metempsy.com 58213531Sjairo.balart@metempsy.com // clear everything 58313531Sjairo.balart@metempsy.com nextElement.clear(); 58413531Sjairo.balart@metempsy.com currElement.clear(); 58513531Sjairo.balart@metempsy.com 58613531Sjairo.balart@metempsy.com traceComplete = false; 58713531Sjairo.balart@metempsy.com} 58813531Sjairo.balart@metempsy.com 58913531Sjairo.balart@metempsy.comvoid 59013531Sjairo.balart@metempsy.comTrafficGen::StateGraph::TraceGen::execute() { 59113580Sgabeblack@google.com // it is the responsibility of nextExecuteTick to prevent the 59213531Sjairo.balart@metempsy.com // state graph from executing the state if it should not 59313531Sjairo.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', 59713531Sjairo.balart@metempsy.com currElement.addr, 59813531Sjairo.balart@metempsy.com currElement.blocksize, 59913531Sjairo.balart@metempsy.com currElement.tick); 60013531Sjairo.balart@metempsy.com 60113531Sjairo.balart@metempsy.com Request::Flags flags; 60213531Sjairo.balart@metempsy.com Request *req = new Request(currElement.addr + addrOffset, 60313531Sjairo.balart@metempsy.com currElement.blocksize, flags, masterID); 60413531Sjairo.balart@metempsy.com 60513531Sjairo.balart@metempsy.com PacketPtr pkt = new Packet(req, currElement.cmd); 60613531Sjairo.balart@metempsy.com 60713531Sjairo.balart@metempsy.com uint8_t* pkt_data = new uint8_t[req->getSize()]; 60813531Sjairo.balart@metempsy.com pkt->dataDynamicArray(pkt_data); 60913531Sjairo.balart@metempsy.com 61013531Sjairo.balart@metempsy.com if (currElement.cmd.isWrite()) { 61113531Sjairo.balart@metempsy.com memset(pkt_data, 0xA, req->getSize()); 61213531Sjairo.balart@metempsy.com } 61313531Sjairo.balart@metempsy.com 61413531Sjairo.balart@metempsy.com port.schedTimingReq(pkt, curTick()); 61513580Sgabeblack@google.com} 61613531Sjairo.balart@metempsy.com 61713580Sgabeblack@google.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 62113531Sjairo.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 } 62613531Sjairo.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 63113531Sjairo.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; 63613531Sjairo.balart@metempsy.com 63713531Sjairo.balart@metempsy.com return true; 63813531Sjairo.balart@metempsy.com} 63913531Sjairo.balart@metempsy.com