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