traffic_gen.cc revision 12085
19241Sandreas.hansson@arm.com/* 211491Sandreas.hansson@arm.com * Copyright (c) 2012-2013, 2016 ARM Limited 39241Sandreas.hansson@arm.com * All rights reserved 49241Sandreas.hansson@arm.com * 59241Sandreas.hansson@arm.com * The license below extends only to copyright in the software and shall 69241Sandreas.hansson@arm.com * not be construed as granting a license to any other intellectual 79241Sandreas.hansson@arm.com * property including but not limited to intellectual property relating 89241Sandreas.hansson@arm.com * to a hardware implementation of the functionality of the software 99241Sandreas.hansson@arm.com * licensed hereunder. You may use the software subject to the license 109241Sandreas.hansson@arm.com * terms below provided that you ensure that this notice is replicated 119241Sandreas.hansson@arm.com * unmodified and in its entirety in all distributions of the software, 129241Sandreas.hansson@arm.com * modified or unmodified, in source code or in binary form. 139241Sandreas.hansson@arm.com * 149241Sandreas.hansson@arm.com * Redistribution and use in source and binary forms, with or without 159241Sandreas.hansson@arm.com * modification, are permitted provided that the following conditions are 169241Sandreas.hansson@arm.com * met: redistributions of source code must retain the above copyright 179241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer; 189241Sandreas.hansson@arm.com * redistributions in binary form must reproduce the above copyright 199241Sandreas.hansson@arm.com * notice, this list of conditions and the following disclaimer in the 209241Sandreas.hansson@arm.com * documentation and/or other materials provided with the distribution; 219241Sandreas.hansson@arm.com * neither the name of the copyright holders nor the names of its 229241Sandreas.hansson@arm.com * contributors may be used to endorse or promote products derived from 239241Sandreas.hansson@arm.com * this software without specific prior written permission. 249241Sandreas.hansson@arm.com * 259241Sandreas.hansson@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 269241Sandreas.hansson@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 279241Sandreas.hansson@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 289241Sandreas.hansson@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 299241Sandreas.hansson@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 309241Sandreas.hansson@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 319241Sandreas.hansson@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 329241Sandreas.hansson@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 339241Sandreas.hansson@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 349241Sandreas.hansson@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 359241Sandreas.hansson@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 369241Sandreas.hansson@arm.com * 379241Sandreas.hansson@arm.com * Authors: Thomas Grass 389241Sandreas.hansson@arm.com * Andreas Hansson 399241Sandreas.hansson@arm.com * Sascha Bischoff 409241Sandreas.hansson@arm.com */ 4111540Sandreas.sandberg@arm.com#include "cpu/testers/traffic_gen/traffic_gen.hh" 4211540Sandreas.sandberg@arm.com 4311540Sandreas.sandberg@arm.com#include <libgen.h> 4411540Sandreas.sandberg@arm.com#include <unistd.h> 459241Sandreas.hansson@arm.com 469241Sandreas.hansson@arm.com#include <sstream> 479241Sandreas.hansson@arm.com 4810138Sneha.agarwal@arm.com#include "base/intmath.hh" 499241Sandreas.hansson@arm.com#include "base/random.hh" 509241Sandreas.hansson@arm.com#include "debug/Checkpoint.hh" 519241Sandreas.hansson@arm.com#include "debug/TrafficGen.hh" 529241Sandreas.hansson@arm.com#include "sim/stats.hh" 539241Sandreas.hansson@arm.com#include "sim/system.hh" 549241Sandreas.hansson@arm.com 559241Sandreas.hansson@arm.comusing namespace std; 569241Sandreas.hansson@arm.com 579241Sandreas.hansson@arm.comTrafficGen::TrafficGen(const TrafficGenParams* p) 589241Sandreas.hansson@arm.com : MemObject(p), 599241Sandreas.hansson@arm.com system(p->system), 609241Sandreas.hansson@arm.com masterID(system->getMasterId(name())), 619718Sandreas.hansson@arm.com configFile(p->config_file), 629720Sandreas.hansson@arm.com elasticReq(p->elastic_req), 6311491Sandreas.hansson@arm.com progressCheck(p->progress_check), 6412085Sspwilson2@wisc.edu noProgressEvent([this]{ noProgress(); }, name()), 659717Sandreas.hansson@arm.com nextTransitionTick(0), 669719Sandreas.hansson@arm.com nextPacketTick(0), 6710360Sandreas.hansson@arm.com currState(0), 689241Sandreas.hansson@arm.com port(name() + ".port", *this), 699719Sandreas.hansson@arm.com retryPkt(NULL), 709719Sandreas.hansson@arm.com retryPktTick(0), 7112085Sspwilson2@wisc.edu updateEvent([this]{ update(); }, name()), 7211393Sandreas.hansson@arm.com numSuppressed(0) 739241Sandreas.hansson@arm.com{ 749241Sandreas.hansson@arm.com} 759241Sandreas.hansson@arm.com 769241Sandreas.hansson@arm.comTrafficGen* 779241Sandreas.hansson@arm.comTrafficGenParams::create() 789241Sandreas.hansson@arm.com{ 799241Sandreas.hansson@arm.com return new TrafficGen(this); 809241Sandreas.hansson@arm.com} 819241Sandreas.hansson@arm.com 829294Sandreas.hansson@arm.comBaseMasterPort& 839294Sandreas.hansson@arm.comTrafficGen::getMasterPort(const string& if_name, PortID idx) 849241Sandreas.hansson@arm.com{ 859241Sandreas.hansson@arm.com if (if_name == "port") { 869241Sandreas.hansson@arm.com return port; 879241Sandreas.hansson@arm.com } else { 889241Sandreas.hansson@arm.com return MemObject::getMasterPort(if_name, idx); 899241Sandreas.hansson@arm.com } 909241Sandreas.hansson@arm.com} 919241Sandreas.hansson@arm.com 929241Sandreas.hansson@arm.comvoid 939241Sandreas.hansson@arm.comTrafficGen::init() 949241Sandreas.hansson@arm.com{ 959241Sandreas.hansson@arm.com if (!port.isConnected()) 969241Sandreas.hansson@arm.com fatal("The port of %s is not connected!\n", name()); 979241Sandreas.hansson@arm.com 989241Sandreas.hansson@arm.com // if the system is in timing mode active the request generator 999524SAndreas.Sandberg@ARM.com if (system->isTimingMode()) { 1009241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Timing mode, activating request generator\n"); 1019241Sandreas.hansson@arm.com 1029718Sandreas.hansson@arm.com parseConfig(); 1039718Sandreas.hansson@arm.com 1049241Sandreas.hansson@arm.com // enter initial state 1059717Sandreas.hansson@arm.com enterState(currState); 1069241Sandreas.hansson@arm.com } else { 1079241Sandreas.hansson@arm.com DPRINTF(TrafficGen, 1089241Sandreas.hansson@arm.com "Traffic generator is only active in timing mode\n"); 1099241Sandreas.hansson@arm.com } 1109241Sandreas.hansson@arm.com} 1119241Sandreas.hansson@arm.com 1129241Sandreas.hansson@arm.comvoid 1139241Sandreas.hansson@arm.comTrafficGen::initState() 1149241Sandreas.hansson@arm.com{ 1159241Sandreas.hansson@arm.com // when not restoring from a checkpoint, make sure we kick things off 1169524SAndreas.Sandberg@ARM.com if (system->isTimingMode()) { 1179719Sandreas.hansson@arm.com // call nextPacketTick on the state to advance it 1189720Sandreas.hansson@arm.com nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0); 1199719Sandreas.hansson@arm.com schedule(updateEvent, std::min(nextPacketTick, nextTransitionTick)); 1209241Sandreas.hansson@arm.com } else { 1219241Sandreas.hansson@arm.com DPRINTF(TrafficGen, 1229241Sandreas.hansson@arm.com "Traffic generator is only active in timing mode\n"); 1239241Sandreas.hansson@arm.com } 1249241Sandreas.hansson@arm.com} 1259241Sandreas.hansson@arm.com 12610913Sandreas.sandberg@arm.comDrainState 12710913Sandreas.sandberg@arm.comTrafficGen::drain() 1289241Sandreas.hansson@arm.com{ 12910051Srioshering@gmail.com if (!updateEvent.scheduled()) { 13010051Srioshering@gmail.com // no event has been scheduled yet (e.g. switched from atomic mode) 13110913Sandreas.sandberg@arm.com return DrainState::Drained; 13210051Srioshering@gmail.com } 13310051Srioshering@gmail.com 1349719Sandreas.hansson@arm.com if (retryPkt == NULL) { 1359719Sandreas.hansson@arm.com // shut things down 1369719Sandreas.hansson@arm.com nextPacketTick = MaxTick; 1379719Sandreas.hansson@arm.com nextTransitionTick = MaxTick; 1389719Sandreas.hansson@arm.com deschedule(updateEvent); 13910913Sandreas.sandberg@arm.com return DrainState::Drained; 1409719Sandreas.hansson@arm.com } else { 14110913Sandreas.sandberg@arm.com return DrainState::Draining; 1429719Sandreas.hansson@arm.com } 1439241Sandreas.hansson@arm.com} 1449241Sandreas.hansson@arm.com 1459241Sandreas.hansson@arm.comvoid 14610905Sandreas.sandberg@arm.comTrafficGen::serialize(CheckpointOut &cp) const 1479241Sandreas.hansson@arm.com{ 1489241Sandreas.hansson@arm.com DPRINTF(Checkpoint, "Serializing TrafficGen\n"); 1499241Sandreas.hansson@arm.com 1509241Sandreas.hansson@arm.com // save ticks of the graph event if it is scheduled 1519719Sandreas.hansson@arm.com Tick nextEvent = updateEvent.scheduled() ? updateEvent.when() : 0; 1529241Sandreas.hansson@arm.com 1539719Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Saving nextEvent=%llu\n", nextEvent); 1549241Sandreas.hansson@arm.com 1559717Sandreas.hansson@arm.com SERIALIZE_SCALAR(nextEvent); 1569241Sandreas.hansson@arm.com 1579241Sandreas.hansson@arm.com SERIALIZE_SCALAR(nextTransitionTick); 1589241Sandreas.hansson@arm.com 1599719Sandreas.hansson@arm.com SERIALIZE_SCALAR(nextPacketTick); 1609719Sandreas.hansson@arm.com 1619719Sandreas.hansson@arm.com SERIALIZE_SCALAR(currState); 1629241Sandreas.hansson@arm.com} 1639241Sandreas.hansson@arm.com 1649241Sandreas.hansson@arm.comvoid 16510905Sandreas.sandberg@arm.comTrafficGen::unserialize(CheckpointIn &cp) 1669241Sandreas.hansson@arm.com{ 1679241Sandreas.hansson@arm.com // restore scheduled events 1689717Sandreas.hansson@arm.com Tick nextEvent; 1699717Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nextEvent); 1709717Sandreas.hansson@arm.com if (nextEvent != 0) { 1719717Sandreas.hansson@arm.com schedule(updateEvent, nextEvent); 1729241Sandreas.hansson@arm.com } 1739241Sandreas.hansson@arm.com 1749241Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nextTransitionTick); 1759719Sandreas.hansson@arm.com 1769719Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(nextPacketTick); 1779719Sandreas.hansson@arm.com 1789719Sandreas.hansson@arm.com // @todo In the case of a stateful generator state such as the 1799719Sandreas.hansson@arm.com // trace player we would also have to restore the position in the 1809720Sandreas.hansson@arm.com // trace playback and the tick offset 1819719Sandreas.hansson@arm.com UNSERIALIZE_SCALAR(currState); 1829241Sandreas.hansson@arm.com} 1839241Sandreas.hansson@arm.com 1849241Sandreas.hansson@arm.comvoid 1859717Sandreas.hansson@arm.comTrafficGen::update() 1869241Sandreas.hansson@arm.com{ 18711491Sandreas.hansson@arm.com // shift our progress-tracking event forward 18811491Sandreas.hansson@arm.com reschedule(noProgressEvent, curTick() + progressCheck, true); 18911491Sandreas.hansson@arm.com 1909717Sandreas.hansson@arm.com // if we have reached the time for the next state transition, then 1919717Sandreas.hansson@arm.com // perform the transition 1929717Sandreas.hansson@arm.com if (curTick() >= nextTransitionTick) { 1939717Sandreas.hansson@arm.com transition(); 1949717Sandreas.hansson@arm.com } else { 1959719Sandreas.hansson@arm.com assert(curTick() >= nextPacketTick); 1969719Sandreas.hansson@arm.com // get the next packet and try to send it 1979718Sandreas.hansson@arm.com PacketPtr pkt = states[currState]->getNextPacket(); 19810266Sandreas.hansson@arm.com 19910266Sandreas.hansson@arm.com // suppress packets that are not destined for a memory, such as 20010266Sandreas.hansson@arm.com // device accesses that could be part of a trace 20110266Sandreas.hansson@arm.com if (system->isMemAddr(pkt->getAddr())) { 20210266Sandreas.hansson@arm.com numPackets++; 20310266Sandreas.hansson@arm.com if (!port.sendTimingReq(pkt)) { 20410266Sandreas.hansson@arm.com retryPkt = pkt; 20510266Sandreas.hansson@arm.com retryPktTick = curTick(); 20610266Sandreas.hansson@arm.com } 20710266Sandreas.hansson@arm.com } else { 20810266Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Suppressed packet %s 0x%x\n", 20910266Sandreas.hansson@arm.com pkt->cmdString(), pkt->getAddr()); 21011393Sandreas.hansson@arm.com 21111393Sandreas.hansson@arm.com ++numSuppressed; 21211393Sandreas.hansson@arm.com if (numSuppressed % 10000) 21311393Sandreas.hansson@arm.com warn("%s suppressed %d packets with non-memory addresses\n", 21411393Sandreas.hansson@arm.com name(), numSuppressed); 21511393Sandreas.hansson@arm.com 21611222Sandreas.hansson@arm.com delete pkt->req; 21711222Sandreas.hansson@arm.com delete pkt; 21811222Sandreas.hansson@arm.com pkt = nullptr; 2199719Sandreas.hansson@arm.com } 2209719Sandreas.hansson@arm.com } 2219719Sandreas.hansson@arm.com 2229719Sandreas.hansson@arm.com // if we are waiting for a retry, do not schedule any further 2239719Sandreas.hansson@arm.com // events, in the case of a transition or a successful send, go 2249719Sandreas.hansson@arm.com // ahead and determine when the next update should take place 2259719Sandreas.hansson@arm.com if (retryPkt == NULL) { 2269719Sandreas.hansson@arm.com // schedule next update event based on either the next execute 2279719Sandreas.hansson@arm.com // tick or the next transition, which ever comes first 2289720Sandreas.hansson@arm.com nextPacketTick = states[currState]->nextPacketTick(elasticReq, 0); 2299719Sandreas.hansson@arm.com Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick); 2309719Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Next event scheduled at %lld\n", nextEventTick); 2319719Sandreas.hansson@arm.com schedule(updateEvent, nextEventTick); 2329717Sandreas.hansson@arm.com } 2339241Sandreas.hansson@arm.com} 2349241Sandreas.hansson@arm.com 23511540Sandreas.sandberg@arm.comstd::string 23611540Sandreas.sandberg@arm.comTrafficGen::resolveFile(const std::string &name) 23711540Sandreas.sandberg@arm.com{ 23811540Sandreas.sandberg@arm.com // Do nothing for empty and absolute file names 23911540Sandreas.sandberg@arm.com if (name.empty() || name[0] == '/') 24011540Sandreas.sandberg@arm.com return name; 24111540Sandreas.sandberg@arm.com 24211540Sandreas.sandberg@arm.com char *config_path = strdup(configFile.c_str()); 24311540Sandreas.sandberg@arm.com char *config_dir = dirname(config_path); 24411540Sandreas.sandberg@arm.com const std::string config_rel = csprintf("%s/%s", config_dir, name); 24511540Sandreas.sandberg@arm.com free(config_path); 24611540Sandreas.sandberg@arm.com 24711540Sandreas.sandberg@arm.com // Check the path relative to the config file first 24811540Sandreas.sandberg@arm.com if (access(config_rel.c_str(), R_OK) == 0) 24911540Sandreas.sandberg@arm.com return config_rel; 25011540Sandreas.sandberg@arm.com 25111540Sandreas.sandberg@arm.com // Fall back to the old behavior and search relative to the 25211540Sandreas.sandberg@arm.com // current working directory. 25311540Sandreas.sandberg@arm.com return name; 25411540Sandreas.sandberg@arm.com} 25511540Sandreas.sandberg@arm.com 2569241Sandreas.hansson@arm.comvoid 2579718Sandreas.hansson@arm.comTrafficGen::parseConfig() 2589241Sandreas.hansson@arm.com{ 2599241Sandreas.hansson@arm.com // keep track of the transitions parsed to create the matrix when 2609241Sandreas.hansson@arm.com // done 2619241Sandreas.hansson@arm.com vector<Transition> transitions; 2629241Sandreas.hansson@arm.com 2639241Sandreas.hansson@arm.com // open input file 2649241Sandreas.hansson@arm.com ifstream infile; 2659718Sandreas.hansson@arm.com infile.open(configFile.c_str(), ifstream::in); 2669241Sandreas.hansson@arm.com if (!infile.is_open()) { 2679241Sandreas.hansson@arm.com fatal("Traffic generator %s config file not found at %s\n", 2689718Sandreas.hansson@arm.com name(), configFile); 2699241Sandreas.hansson@arm.com } 2709241Sandreas.hansson@arm.com 27110128Sstan.czerniawski@arm.com bool init_state_set = false; 27210128Sstan.czerniawski@arm.com 2739241Sandreas.hansson@arm.com // read line by line and determine the action based on the first 2749241Sandreas.hansson@arm.com // keyword 2759241Sandreas.hansson@arm.com string keyword; 2769241Sandreas.hansson@arm.com string line; 2779241Sandreas.hansson@arm.com 2789241Sandreas.hansson@arm.com while (getline(infile, line).good()) { 2799241Sandreas.hansson@arm.com // see if this line is a comment line, and if so skip it 2809241Sandreas.hansson@arm.com if (line.find('#') != 1) { 2819241Sandreas.hansson@arm.com // create an input stream for the tokenization 2829241Sandreas.hansson@arm.com istringstream is(line); 2839241Sandreas.hansson@arm.com 2849241Sandreas.hansson@arm.com // determine the keyword 2859241Sandreas.hansson@arm.com is >> keyword; 2869241Sandreas.hansson@arm.com 2879241Sandreas.hansson@arm.com if (keyword == "STATE") { 2889241Sandreas.hansson@arm.com // parse the behaviour of this state 2899241Sandreas.hansson@arm.com uint32_t id; 2909241Sandreas.hansson@arm.com Tick duration; 2919241Sandreas.hansson@arm.com string mode; 2929241Sandreas.hansson@arm.com 2939241Sandreas.hansson@arm.com is >> id >> duration >> mode; 2949241Sandreas.hansson@arm.com 2959241Sandreas.hansson@arm.com if (mode == "TRACE") { 2969241Sandreas.hansson@arm.com string traceFile; 2979241Sandreas.hansson@arm.com Addr addrOffset; 2989241Sandreas.hansson@arm.com 2999241Sandreas.hansson@arm.com is >> traceFile >> addrOffset; 30011540Sandreas.sandberg@arm.com traceFile = resolveFile(traceFile); 3019241Sandreas.hansson@arm.com 3029718Sandreas.hansson@arm.com states[id] = new TraceGen(name(), masterID, duration, 3039241Sandreas.hansson@arm.com traceFile, addrOffset); 3049241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "State: %d TraceGen\n", id); 3059241Sandreas.hansson@arm.com } else if (mode == "IDLE") { 3069718Sandreas.hansson@arm.com states[id] = new IdleGen(name(), masterID, duration); 3079241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "State: %d IdleGen\n", id); 30810138Sneha.agarwal@arm.com } else if (mode == "LINEAR" || mode == "RANDOM" || 30910392Swendy.elsasser@arm.com mode == "DRAM" || mode == "DRAM_ROTATE") { 3109241Sandreas.hansson@arm.com uint32_t read_percent; 3119241Sandreas.hansson@arm.com Addr start_addr; 3129241Sandreas.hansson@arm.com Addr end_addr; 3139241Sandreas.hansson@arm.com Addr blocksize; 3149241Sandreas.hansson@arm.com Tick min_period; 3159241Sandreas.hansson@arm.com Tick max_period; 3169241Sandreas.hansson@arm.com Addr data_limit; 3179241Sandreas.hansson@arm.com 3189241Sandreas.hansson@arm.com is >> read_percent >> start_addr >> end_addr >> 3199241Sandreas.hansson@arm.com blocksize >> min_period >> max_period >> data_limit; 3209241Sandreas.hansson@arm.com 3219241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "%s, addr %x to %x, size %d," 3229241Sandreas.hansson@arm.com " period %d to %d, %d%% reads\n", 3239241Sandreas.hansson@arm.com mode, start_addr, end_addr, blocksize, min_period, 3249241Sandreas.hansson@arm.com max_period, read_percent); 3259241Sandreas.hansson@arm.com 3269718Sandreas.hansson@arm.com 3279814Sandreas.hansson@arm.com if (blocksize > system->cacheLineSize()) 3289718Sandreas.hansson@arm.com fatal("TrafficGen %s block size (%d) is larger than " 32910138Sneha.agarwal@arm.com "cache line size (%d)\n", name(), 3309814Sandreas.hansson@arm.com blocksize, system->cacheLineSize()); 3319718Sandreas.hansson@arm.com 3329241Sandreas.hansson@arm.com if (read_percent > 100) 3339718Sandreas.hansson@arm.com fatal("%s cannot have more than 100% reads", name()); 3349241Sandreas.hansson@arm.com 3359722Ssascha.bischoff@arm.com if (min_period > max_period) 3369722Ssascha.bischoff@arm.com fatal("%s cannot have min_period > max_period", name()); 3379722Ssascha.bischoff@arm.com 3389241Sandreas.hansson@arm.com if (mode == "LINEAR") { 3399718Sandreas.hansson@arm.com states[id] = new LinearGen(name(), masterID, 3409241Sandreas.hansson@arm.com duration, start_addr, 3419241Sandreas.hansson@arm.com end_addr, blocksize, 3429241Sandreas.hansson@arm.com min_period, max_period, 3439241Sandreas.hansson@arm.com read_percent, data_limit); 3449241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "State: %d LinearGen\n", id); 3459241Sandreas.hansson@arm.com } else if (mode == "RANDOM") { 3469718Sandreas.hansson@arm.com states[id] = new RandomGen(name(), masterID, 3479241Sandreas.hansson@arm.com duration, start_addr, 3489241Sandreas.hansson@arm.com end_addr, blocksize, 3499241Sandreas.hansson@arm.com min_period, max_period, 3509241Sandreas.hansson@arm.com read_percent, data_limit); 3519241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "State: %d RandomGen\n", id); 35210392Swendy.elsasser@arm.com } else if (mode == "DRAM" || mode == "DRAM_ROTATE") { 35310138Sneha.agarwal@arm.com // stride size (bytes) of the request for achieving 35410138Sneha.agarwal@arm.com // required hit length 35510138Sneha.agarwal@arm.com unsigned int stride_size; 35610138Sneha.agarwal@arm.com unsigned int page_size; 35710138Sneha.agarwal@arm.com unsigned int nbr_of_banks_DRAM; 35810138Sneha.agarwal@arm.com unsigned int nbr_of_banks_util; 35910138Sneha.agarwal@arm.com unsigned int addr_mapping; 36010392Swendy.elsasser@arm.com unsigned int nbr_of_ranks; 36110138Sneha.agarwal@arm.com 36210138Sneha.agarwal@arm.com is >> stride_size >> page_size >> nbr_of_banks_DRAM >> 36310392Swendy.elsasser@arm.com nbr_of_banks_util >> addr_mapping >> 36410392Swendy.elsasser@arm.com nbr_of_ranks; 36510138Sneha.agarwal@arm.com 36610138Sneha.agarwal@arm.com if (stride_size > page_size) 36710138Sneha.agarwal@arm.com warn("DRAM generator stride size (%d) is greater " 36810138Sneha.agarwal@arm.com "than page size (%d) of the memory\n", 36910138Sneha.agarwal@arm.com blocksize, page_size); 37010138Sneha.agarwal@arm.com 37110138Sneha.agarwal@arm.com if (nbr_of_banks_util > nbr_of_banks_DRAM) 37210746Swendy.elsasser@arm.com fatal("Attempting to use more banks (%d) than " 37310746Swendy.elsasser@arm.com "what is available (%d)\n", 37410138Sneha.agarwal@arm.com nbr_of_banks_util, nbr_of_banks_DRAM); 37510138Sneha.agarwal@arm.com 37610138Sneha.agarwal@arm.com // count the number of sequential packets to 37710138Sneha.agarwal@arm.com // generate 37810138Sneha.agarwal@arm.com unsigned int num_seq_pkts = 1; 37910138Sneha.agarwal@arm.com 38010138Sneha.agarwal@arm.com if (stride_size > blocksize) { 38110138Sneha.agarwal@arm.com num_seq_pkts = divCeil(stride_size, blocksize); 38210138Sneha.agarwal@arm.com DPRINTF(TrafficGen, "stride size: %d " 38310138Sneha.agarwal@arm.com "block size: %d, num_seq_pkts: %d\n", 38410138Sneha.agarwal@arm.com stride_size, blocksize, num_seq_pkts); 38510138Sneha.agarwal@arm.com } 38610138Sneha.agarwal@arm.com 38710392Swendy.elsasser@arm.com if (mode == "DRAM") { 38810392Swendy.elsasser@arm.com states[id] = new DramGen(name(), masterID, 38910392Swendy.elsasser@arm.com duration, start_addr, 39010392Swendy.elsasser@arm.com end_addr, blocksize, 39110392Swendy.elsasser@arm.com min_period, max_period, 39210392Swendy.elsasser@arm.com read_percent, data_limit, 39310392Swendy.elsasser@arm.com num_seq_pkts, page_size, 39410392Swendy.elsasser@arm.com nbr_of_banks_DRAM, 39510392Swendy.elsasser@arm.com nbr_of_banks_util, 39610392Swendy.elsasser@arm.com addr_mapping, 39710392Swendy.elsasser@arm.com nbr_of_ranks); 39810392Swendy.elsasser@arm.com DPRINTF(TrafficGen, "State: %d DramGen\n", id); 39910392Swendy.elsasser@arm.com } else { 40010392Swendy.elsasser@arm.com // Will rotate to the next rank after rotating 40110392Swendy.elsasser@arm.com // through all banks, for each command type. 40210392Swendy.elsasser@arm.com // In the 50% read case, series will be issued 40310392Swendy.elsasser@arm.com // for both RD & WR before the rank in incremented 40410392Swendy.elsasser@arm.com unsigned int max_seq_count_per_rank = 40510392Swendy.elsasser@arm.com (read_percent == 50) ? nbr_of_banks_util * 2 40610392Swendy.elsasser@arm.com : nbr_of_banks_util; 40710392Swendy.elsasser@arm.com 40810392Swendy.elsasser@arm.com states[id] = new DramRotGen(name(), masterID, 40910392Swendy.elsasser@arm.com duration, start_addr, 41010392Swendy.elsasser@arm.com end_addr, blocksize, 41110392Swendy.elsasser@arm.com min_period, max_period, 41210392Swendy.elsasser@arm.com read_percent, data_limit, 41310392Swendy.elsasser@arm.com num_seq_pkts, page_size, 41410392Swendy.elsasser@arm.com nbr_of_banks_DRAM, 41510392Swendy.elsasser@arm.com nbr_of_banks_util, 41610392Swendy.elsasser@arm.com addr_mapping, 41710392Swendy.elsasser@arm.com nbr_of_ranks, 41810392Swendy.elsasser@arm.com max_seq_count_per_rank); 41910392Swendy.elsasser@arm.com DPRINTF(TrafficGen, "State: %d DramRotGen\n", id); 42010392Swendy.elsasser@arm.com } 4219241Sandreas.hansson@arm.com } 4229241Sandreas.hansson@arm.com } else { 4239241Sandreas.hansson@arm.com fatal("%s: Unknown traffic generator mode: %s", 4249241Sandreas.hansson@arm.com name(), mode); 4259241Sandreas.hansson@arm.com } 4269241Sandreas.hansson@arm.com } else if (keyword == "TRANSITION") { 4279241Sandreas.hansson@arm.com Transition transition; 4289241Sandreas.hansson@arm.com 4299241Sandreas.hansson@arm.com is >> transition.from >> transition.to >> transition.p; 4309241Sandreas.hansson@arm.com 4319241Sandreas.hansson@arm.com transitions.push_back(transition); 4329241Sandreas.hansson@arm.com 4339241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Transition: %d -> %d\n", transition.from, 4349241Sandreas.hansson@arm.com transition.to); 4359241Sandreas.hansson@arm.com } else if (keyword == "INIT") { 4369241Sandreas.hansson@arm.com // set the initial state as the active state 4379241Sandreas.hansson@arm.com is >> currState; 4389241Sandreas.hansson@arm.com 43910128Sstan.czerniawski@arm.com init_state_set = true; 44010128Sstan.czerniawski@arm.com 4419241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Initial state: %d\n", currState); 4429241Sandreas.hansson@arm.com } 4439241Sandreas.hansson@arm.com } 4449241Sandreas.hansson@arm.com } 4459241Sandreas.hansson@arm.com 44610128Sstan.czerniawski@arm.com if (!init_state_set) 44710128Sstan.czerniawski@arm.com fatal("%s: initial state not specified (add 'INIT <id>' line " 44810128Sstan.czerniawski@arm.com "to the config file)\n", name()); 44910128Sstan.czerniawski@arm.com 4509241Sandreas.hansson@arm.com // resize and populate state transition matrix 4519721Ssascha.bischoff@arm.com transitionMatrix.resize(states.size()); 4529721Ssascha.bischoff@arm.com for (size_t i = 0; i < states.size(); i++) { 4539721Ssascha.bischoff@arm.com transitionMatrix[i].resize(states.size()); 4549241Sandreas.hansson@arm.com } 4559241Sandreas.hansson@arm.com 4569241Sandreas.hansson@arm.com for (vector<Transition>::iterator t = transitions.begin(); 4579241Sandreas.hansson@arm.com t != transitions.end(); ++t) { 4589241Sandreas.hansson@arm.com transitionMatrix[t->from][t->to] = t->p; 4599241Sandreas.hansson@arm.com } 4609241Sandreas.hansson@arm.com 4619241Sandreas.hansson@arm.com // ensure the egress edges do not have a probability larger than 4629241Sandreas.hansson@arm.com // one 4639721Ssascha.bischoff@arm.com for (size_t i = 0; i < states.size(); i++) { 4649241Sandreas.hansson@arm.com double sum = 0; 4659721Ssascha.bischoff@arm.com for (size_t j = 0; j < states.size(); j++) { 4669241Sandreas.hansson@arm.com sum += transitionMatrix[i][j]; 4679241Sandreas.hansson@arm.com } 4689241Sandreas.hansson@arm.com 4699241Sandreas.hansson@arm.com // avoid comparing floating point numbers 4709241Sandreas.hansson@arm.com if (abs(sum - 1.0) > 0.001) 4719241Sandreas.hansson@arm.com fatal("%s has transition probability != 1 for state %d\n", 4729241Sandreas.hansson@arm.com name(), i); 4739241Sandreas.hansson@arm.com } 4749241Sandreas.hansson@arm.com 4759241Sandreas.hansson@arm.com // close input file 4769241Sandreas.hansson@arm.com infile.close(); 4779241Sandreas.hansson@arm.com} 4789241Sandreas.hansson@arm.com 4799241Sandreas.hansson@arm.comvoid 4809717Sandreas.hansson@arm.comTrafficGen::transition() 4819241Sandreas.hansson@arm.com{ 4829241Sandreas.hansson@arm.com // exit the current state 4839241Sandreas.hansson@arm.com states[currState]->exit(); 4849241Sandreas.hansson@arm.com 4859241Sandreas.hansson@arm.com // determine next state 48610348Sandreas.hansson@arm.com double p = random_mt.random<double>(); 4879241Sandreas.hansson@arm.com assert(currState < transitionMatrix.size()); 4889584Sandreas@sandberg.pp.se double cumulative = 0.0; 4899584Sandreas@sandberg.pp.se size_t i = 0; 4909584Sandreas@sandberg.pp.se do { 4919241Sandreas.hansson@arm.com cumulative += transitionMatrix[currState][i]; 4929241Sandreas.hansson@arm.com ++i; 4939584Sandreas@sandberg.pp.se } while (cumulative < p && i < transitionMatrix[currState].size()); 4949584Sandreas@sandberg.pp.se 4959584Sandreas@sandberg.pp.se enterState(i - 1); 4969241Sandreas.hansson@arm.com} 4979241Sandreas.hansson@arm.com 4989241Sandreas.hansson@arm.comvoid 4999717Sandreas.hansson@arm.comTrafficGen::enterState(uint32_t newState) 5009241Sandreas.hansson@arm.com{ 5019241Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Transition to state %d\n", newState); 5029241Sandreas.hansson@arm.com 5039241Sandreas.hansson@arm.com currState = newState; 5049719Sandreas.hansson@arm.com // we could have been delayed and not transitioned on the exact 5059719Sandreas.hansson@arm.com // tick when we were supposed to (due to back pressure when 5069719Sandreas.hansson@arm.com // sending a packet) 5079719Sandreas.hansson@arm.com nextTransitionTick = curTick() + states[currState]->duration; 5089241Sandreas.hansson@arm.com states[currState]->enter(); 5099241Sandreas.hansson@arm.com} 5109241Sandreas.hansson@arm.com 5119719Sandreas.hansson@arm.comvoid 51210713Sandreas.hansson@arm.comTrafficGen::recvReqRetry() 5139719Sandreas.hansson@arm.com{ 5149719Sandreas.hansson@arm.com assert(retryPkt != NULL); 5159719Sandreas.hansson@arm.com 5169719Sandreas.hansson@arm.com DPRINTF(TrafficGen, "Received retry\n"); 5179719Sandreas.hansson@arm.com numRetries++; 5189719Sandreas.hansson@arm.com // attempt to send the packet, and if we are successful start up 5199719Sandreas.hansson@arm.com // the machinery again 5209719Sandreas.hansson@arm.com if (port.sendTimingReq(retryPkt)) { 5219719Sandreas.hansson@arm.com retryPkt = NULL; 5229719Sandreas.hansson@arm.com // remember how much delay was incurred due to back-pressure 5239720Sandreas.hansson@arm.com // when sending the request, we also use this to derive 5249720Sandreas.hansson@arm.com // the tick for the next packet 5259719Sandreas.hansson@arm.com Tick delay = curTick() - retryPktTick; 5269719Sandreas.hansson@arm.com retryPktTick = 0; 5279719Sandreas.hansson@arm.com retryTicks += delay; 5289719Sandreas.hansson@arm.com 52910913Sandreas.sandberg@arm.com if (drainState() != DrainState::Draining) { 5309719Sandreas.hansson@arm.com // packet is sent, so find out when the next one is due 5319720Sandreas.hansson@arm.com nextPacketTick = states[currState]->nextPacketTick(elasticReq, 5329720Sandreas.hansson@arm.com delay); 5339719Sandreas.hansson@arm.com Tick nextEventTick = std::min(nextPacketTick, nextTransitionTick); 5349719Sandreas.hansson@arm.com schedule(updateEvent, std::max(curTick(), nextEventTick)); 5359719Sandreas.hansson@arm.com } else { 5369719Sandreas.hansson@arm.com // shut things down 5379719Sandreas.hansson@arm.com nextPacketTick = MaxTick; 5389719Sandreas.hansson@arm.com nextTransitionTick = MaxTick; 53910913Sandreas.sandberg@arm.com signalDrainDone(); 5409719Sandreas.hansson@arm.com } 5419719Sandreas.hansson@arm.com } 5429719Sandreas.hansson@arm.com} 5439719Sandreas.hansson@arm.com 5449719Sandreas.hansson@arm.comvoid 54511491Sandreas.hansson@arm.comTrafficGen::noProgress() 54611491Sandreas.hansson@arm.com{ 54711491Sandreas.hansson@arm.com fatal("TrafficGen %s spent %llu ticks without making progress", 54811491Sandreas.hansson@arm.com name(), progressCheck); 54911491Sandreas.hansson@arm.com} 55011491Sandreas.hansson@arm.com 55111491Sandreas.hansson@arm.comvoid 5529719Sandreas.hansson@arm.comTrafficGen::regStats() 5539719Sandreas.hansson@arm.com{ 55411522Sstephan.diestelhorst@arm.com ClockedObject::regStats(); 55511522Sstephan.diestelhorst@arm.com 5569719Sandreas.hansson@arm.com // Initialise all the stats 5579719Sandreas.hansson@arm.com using namespace Stats; 5589719Sandreas.hansson@arm.com 5599719Sandreas.hansson@arm.com numPackets 5609719Sandreas.hansson@arm.com .name(name() + ".numPackets") 5619719Sandreas.hansson@arm.com .desc("Number of packets generated"); 5629719Sandreas.hansson@arm.com 5639719Sandreas.hansson@arm.com numRetries 5649719Sandreas.hansson@arm.com .name(name() + ".numRetries") 5659719Sandreas.hansson@arm.com .desc("Number of retries"); 5669719Sandreas.hansson@arm.com 5679719Sandreas.hansson@arm.com retryTicks 5689719Sandreas.hansson@arm.com .name(name() + ".retryTicks") 5699719Sandreas.hansson@arm.com .desc("Time spent waiting due to back-pressure (ticks)"); 5709719Sandreas.hansson@arm.com} 5719719Sandreas.hansson@arm.com 5729241Sandreas.hansson@arm.combool 5739241Sandreas.hansson@arm.comTrafficGen::TrafficGenPort::recvTimingResp(PacketPtr pkt) 5749241Sandreas.hansson@arm.com{ 5759241Sandreas.hansson@arm.com delete pkt->req; 5769241Sandreas.hansson@arm.com delete pkt; 5779241Sandreas.hansson@arm.com 5789241Sandreas.hansson@arm.com return true; 5799241Sandreas.hansson@arm.com} 580