traffic_gen.cc revision 9717
1/* 2 * Copyright (c) 2012-2013 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions are 16 * met: redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer; 18 * redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution; 21 * neither the name of the copyright holders nor the names of its 22 * contributors may be used to endorse or promote products derived from 23 * this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36 * 37 * Authors: Thomas Grass 38 * Andreas Hansson 39 * Sascha Bischoff 40 */ 41 42#include <sstream> 43 44#include "base/random.hh" 45#include "cpu/testers/traffic_gen/traffic_gen.hh" 46#include "debug/Checkpoint.hh" 47#include "debug/TrafficGen.hh" 48#include "sim/stats.hh" 49#include "sim/system.hh" 50 51using namespace std; 52 53TrafficGen::TrafficGen(const TrafficGenParams* p) 54 : MemObject(p), 55 system(p->system), 56 masterID(system->getMasterId(name())), 57 nextTransitionTick(0), 58 port(name() + ".port", *this), 59 updateEvent(this) 60{ 61 parseConfig(p->config_file, masterID); 62} 63 64TrafficGen* 65TrafficGenParams::create() 66{ 67 return new TrafficGen(this); 68} 69 70BaseMasterPort& 71TrafficGen::getMasterPort(const string& if_name, PortID idx) 72{ 73 if (if_name == "port") { 74 return port; 75 } else { 76 return MemObject::getMasterPort(if_name, idx); 77 } 78} 79 80void 81TrafficGen::init() 82{ 83 if (!port.isConnected()) 84 fatal("The port of %s is not connected!\n", name()); 85 86 // if the system is in timing mode active the request generator 87 if (system->isTimingMode()) { 88 DPRINTF(TrafficGen, "Timing mode, activating request generator\n"); 89 90 // enter initial state 91 enterState(currState); 92 } else { 93 DPRINTF(TrafficGen, 94 "Traffic generator is only active in timing mode\n"); 95 } 96} 97 98void 99TrafficGen::initState() 100{ 101 // when not restoring from a checkpoint, make sure we kick things off 102 if (system->isTimingMode()) { 103 schedule(updateEvent, nextEventTick()); 104 } else { 105 DPRINTF(TrafficGen, 106 "Traffic generator is only active in timing mode\n"); 107 } 108} 109 110unsigned int 111TrafficGen::drain(DrainManager *dm) 112{ 113 // @todo we should also stop putting new requests in the queue and 114 // either interrupt the current state or wait for a transition 115 return port.drain(dm); 116} 117 118void 119TrafficGen::serialize(ostream &os) 120{ 121 DPRINTF(Checkpoint, "Serializing TrafficGen\n"); 122 123 // save ticks of the graph event if it is scheduled 124 Tick nextEvent = updateEvent.scheduled() ? 125 updateEvent.when() : 0; 126 127 DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", 128 nextEvent); 129 130 SERIALIZE_SCALAR(nextEvent); 131 132 SERIALIZE_SCALAR(nextTransitionTick); 133 134 // @todo: also serialise the current state, figure out the best 135 // way to drain and restore 136} 137 138void 139TrafficGen::unserialize(Checkpoint* cp, const string& section) 140{ 141 // restore scheduled events 142 Tick nextEvent; 143 UNSERIALIZE_SCALAR(nextEvent); 144 if (nextEvent != 0) { 145 schedule(updateEvent, nextEvent); 146 } 147 148 UNSERIALIZE_SCALAR(nextTransitionTick); 149} 150 151void 152TrafficGen::update() 153{ 154 // schedule next update event based on either the next execute 155 // tick or the next transition, which ever comes first 156 Tick nextEvent = nextEventTick(); 157 DPRINTF(TrafficGen, "Updating state graph, next event at %lld\n", 158 nextEvent); 159 schedule(updateEvent, nextEvent); 160 161 // perform the update associated with the current update event 162 163 // if we have reached the time for the next state transition, then 164 // perform the transition 165 if (curTick() >= nextTransitionTick) { 166 transition(); 167 } else { 168 // we are still in the current state and should execute it 169 states[currState]->execute(); 170 } 171} 172 173void 174TrafficGen::parseConfig(const string& file_name, MasterID master_id) 175{ 176 // keep track of the transitions parsed to create the matrix when 177 // done 178 vector<Transition> transitions; 179 180 // open input file 181 ifstream infile; 182 infile.open(file_name.c_str(), ifstream::in); 183 if (!infile.is_open()) { 184 fatal("Traffic generator %s config file not found at %s\n", 185 name(), file_name); 186 } 187 188 // read line by line and determine the action based on the first 189 // keyword 190 string keyword; 191 string line; 192 193 while (getline(infile, line).good()) { 194 // see if this line is a comment line, and if so skip it 195 if (line.find('#') != 1) { 196 // create an input stream for the tokenization 197 istringstream is(line); 198 199 // determine the keyword 200 is >> keyword; 201 202 if (keyword == "STATE") { 203 // parse the behaviour of this state 204 uint32_t id; 205 Tick duration; 206 string mode; 207 208 is >> id >> duration >> mode; 209 210 if (mode == "TRACE") { 211 string traceFile; 212 Addr addrOffset; 213 214 is >> traceFile >> addrOffset; 215 216 states[id] = new TraceGen(port, master_id, duration, 217 traceFile, addrOffset); 218 DPRINTF(TrafficGen, "State: %d TraceGen\n", id); 219 } else if (mode == "IDLE") { 220 states[id] = new IdleGen(port, master_id, duration); 221 DPRINTF(TrafficGen, "State: %d IdleGen\n", id); 222 } else if (mode == "LINEAR" || mode == "RANDOM") { 223 uint32_t read_percent; 224 Addr start_addr; 225 Addr end_addr; 226 Addr blocksize; 227 Tick min_period; 228 Tick max_period; 229 Addr data_limit; 230 231 is >> read_percent >> start_addr >> end_addr >> 232 blocksize >> min_period >> max_period >> data_limit; 233 234 DPRINTF(TrafficGen, "%s, addr %x to %x, size %d," 235 " period %d to %d, %d%% reads\n", 236 mode, start_addr, end_addr, blocksize, min_period, 237 max_period, read_percent); 238 239 if (read_percent > 100) 240 panic("%s cannot have more than 100% reads", name()); 241 242 if (mode == "LINEAR") { 243 states[id] = new LinearGen(port, master_id, 244 duration, start_addr, 245 end_addr, blocksize, 246 min_period, max_period, 247 read_percent, data_limit); 248 DPRINTF(TrafficGen, "State: %d LinearGen\n", id); 249 } else if (mode == "RANDOM") { 250 states[id] = new RandomGen(port, master_id, 251 duration, start_addr, 252 end_addr, blocksize, 253 min_period, max_period, 254 read_percent, data_limit); 255 DPRINTF(TrafficGen, "State: %d RandomGen\n", id); 256 } 257 } else { 258 fatal("%s: Unknown traffic generator mode: %s", 259 name(), mode); 260 } 261 } else if (keyword == "TRANSITION") { 262 Transition transition; 263 264 is >> transition.from >> transition.to >> transition.p; 265 266 transitions.push_back(transition); 267 268 DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from, 269 transition.to); 270 } else if (keyword == "INIT") { 271 // set the initial state as the active state 272 is >> currState; 273 274 DPRINTF(TrafficGen, "Initial state: %d\n", currState); 275 } 276 } 277 } 278 279 // resize and populate state transition matrix 280 transitionMatrix.resize(transitions.size()); 281 for (size_t i = 0; i < transitions.size(); i++) { 282 transitionMatrix[i].resize(transitions.size()); 283 } 284 285 for (vector<Transition>::iterator t = transitions.begin(); 286 t != transitions.end(); ++t) { 287 transitionMatrix[t->from][t->to] = t->p; 288 } 289 290 // ensure the egress edges do not have a probability larger than 291 // one 292 for (size_t i = 0; i < transitions.size(); i++) { 293 double sum = 0; 294 for (size_t j = 0; j < transitions.size(); j++) { 295 sum += transitionMatrix[i][j]; 296 } 297 298 // avoid comparing floating point numbers 299 if (abs(sum - 1.0) > 0.001) 300 fatal("%s has transition probability != 1 for state %d\n", 301 name(), i); 302 } 303 304 // close input file 305 infile.close(); 306} 307 308void 309TrafficGen::transition() 310{ 311 // exit the current state 312 states[currState]->exit(); 313 314 // determine next state 315 double p = random_mt.gen_real1(); 316 assert(currState < transitionMatrix.size()); 317 double cumulative = 0.0; 318 size_t i = 0; 319 do { 320 cumulative += transitionMatrix[currState][i]; 321 ++i; 322 } while (cumulative < p && i < transitionMatrix[currState].size()); 323 324 enterState(i - 1); 325} 326 327void 328TrafficGen::enterState(uint32_t newState) 329{ 330 DPRINTF(TrafficGen, "Transition to state %d\n", newState); 331 332 currState = newState; 333 nextTransitionTick += states[currState]->duration; 334 states[currState]->enter(); 335} 336 337bool 338TrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt) 339{ 340 delete pkt->req; 341 delete pkt; 342 343 return true; 344} 345