trace_cpu.cc revision 12680
111249Sradhika.jagtap@ARM.com/* 211631Sradhika.jagtap@arm.com * Copyright (c) 2013 - 2016 ARM Limited 311249Sradhika.jagtap@ARM.com * All rights reserved 411249Sradhika.jagtap@ARM.com * 511249Sradhika.jagtap@ARM.com * The license below extends only to copyright in the software and shall 611249Sradhika.jagtap@ARM.com * not be construed as granting a license to any other intellectual 711249Sradhika.jagtap@ARM.com * property including but not limited to intellectual property relating 811249Sradhika.jagtap@ARM.com * to a hardware implementation of the functionality of the software 911249Sradhika.jagtap@ARM.com * licensed hereunder. You may use the software subject to the license 1011249Sradhika.jagtap@ARM.com * terms below provided that you ensure that this notice is replicated 1111249Sradhika.jagtap@ARM.com * unmodified and in its entirety in all distributions of the software, 1211249Sradhika.jagtap@ARM.com * modified or unmodified, in source code or in binary form. 1311249Sradhika.jagtap@ARM.com * 1411249Sradhika.jagtap@ARM.com * Redistribution and use in source and binary forms, with or without 1511249Sradhika.jagtap@ARM.com * modification, are permitted provided that the following conditions are 1611249Sradhika.jagtap@ARM.com * met: redistributions of source code must retain the above copyright 1711249Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer; 1811249Sradhika.jagtap@ARM.com * redistributions in binary form must reproduce the above copyright 1911249Sradhika.jagtap@ARM.com * notice, this list of conditions and the following disclaimer in the 2011249Sradhika.jagtap@ARM.com * documentation and/or other materials provided with the distribution; 2111249Sradhika.jagtap@ARM.com * neither the name of the copyright holders nor the names of its 2211249Sradhika.jagtap@ARM.com * contributors may be used to endorse or promote products derived from 2311249Sradhika.jagtap@ARM.com * this software without specific prior written permission. 2411249Sradhika.jagtap@ARM.com * 2511249Sradhika.jagtap@ARM.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2611249Sradhika.jagtap@ARM.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2711249Sradhika.jagtap@ARM.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2811249Sradhika.jagtap@ARM.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2911249Sradhika.jagtap@ARM.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 3011249Sradhika.jagtap@ARM.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 3111249Sradhika.jagtap@ARM.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 3211249Sradhika.jagtap@ARM.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 3311249Sradhika.jagtap@ARM.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 3411249Sradhika.jagtap@ARM.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 3511249Sradhika.jagtap@ARM.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3611249Sradhika.jagtap@ARM.com * 3711249Sradhika.jagtap@ARM.com * Authors: Radhika Jagtap 3811249Sradhika.jagtap@ARM.com * Andreas Hansson 3911249Sradhika.jagtap@ARM.com * Thomas Grass 4011249Sradhika.jagtap@ARM.com */ 4111249Sradhika.jagtap@ARM.com 4211249Sradhika.jagtap@ARM.com#include "cpu/trace/trace_cpu.hh" 4311249Sradhika.jagtap@ARM.com 4411249Sradhika.jagtap@ARM.com#include "sim/sim_exit.hh" 4511249Sradhika.jagtap@ARM.com 4611249Sradhika.jagtap@ARM.com// Declare and initialize the static counter for number of trace CPUs. 4711249Sradhika.jagtap@ARM.comint TraceCPU::numTraceCPUs = 0; 4811249Sradhika.jagtap@ARM.com 4911249Sradhika.jagtap@ARM.comTraceCPU::TraceCPU(TraceCPUParams *params) 5011249Sradhika.jagtap@ARM.com : BaseCPU(params), 5111249Sradhika.jagtap@ARM.com icachePort(this), 5211249Sradhika.jagtap@ARM.com dcachePort(this), 5312680Sgiacomo.travaglini@arm.com instMasterID(params->system->getMasterId(this, "inst")), 5412680Sgiacomo.travaglini@arm.com dataMasterID(params->system->getMasterId(this, "data")), 5511249Sradhika.jagtap@ARM.com instTraceFile(params->instTraceFile), 5611249Sradhika.jagtap@ARM.com dataTraceFile(params->dataTraceFile), 5711249Sradhika.jagtap@ARM.com icacheGen(*this, ".iside", icachePort, instMasterID, instTraceFile), 5811249Sradhika.jagtap@ARM.com dcacheGen(*this, ".dside", dcachePort, dataMasterID, dataTraceFile, 5911631Sradhika.jagtap@arm.com params), 6012085Sspwilson2@wisc.edu icacheNextEvent([this]{ schedIcacheNext(); }, name()), 6112085Sspwilson2@wisc.edu dcacheNextEvent([this]{ schedDcacheNext(); }, name()), 6211249Sradhika.jagtap@ARM.com oneTraceComplete(false), 6311632Sradhika.jagtap@arm.com traceOffset(0), 6411633Sradhika.jagtap@arm.com execCompleteEvent(nullptr), 6511918Sradhika.jagtap@arm.com enableEarlyExit(params->enableEarlyExit), 6611918Sradhika.jagtap@arm.com progressMsgInterval(params->progressMsgInterval), 6711918Sradhika.jagtap@arm.com progressMsgThreshold(params->progressMsgInterval) 6811249Sradhika.jagtap@ARM.com{ 6911249Sradhika.jagtap@ARM.com // Increment static counter for number of Trace CPUs. 7011249Sradhika.jagtap@ARM.com ++TraceCPU::numTraceCPUs; 7111249Sradhika.jagtap@ARM.com 7211918Sradhika.jagtap@arm.com // Check that the python parameters for sizes of ROB, store buffer and 7311918Sradhika.jagtap@arm.com // load buffer do not overflow the corresponding C++ variables. 7411249Sradhika.jagtap@ARM.com fatal_if(params->sizeROB > UINT16_MAX, "ROB size set to %d exceeds the " 7511249Sradhika.jagtap@ARM.com "max. value of %d.\n", params->sizeROB, UINT16_MAX); 7611249Sradhika.jagtap@ARM.com fatal_if(params->sizeStoreBuffer > UINT16_MAX, "ROB size set to %d " 7711249Sradhika.jagtap@ARM.com "exceeds the max. value of %d.\n", params->sizeROB, 7811249Sradhika.jagtap@ARM.com UINT16_MAX); 7911249Sradhika.jagtap@ARM.com fatal_if(params->sizeLoadBuffer > UINT16_MAX, "Load buffer size set to" 8011249Sradhika.jagtap@ARM.com " %d exceeds the max. value of %d.\n", 8111249Sradhika.jagtap@ARM.com params->sizeLoadBuffer, UINT16_MAX); 8211249Sradhika.jagtap@ARM.com} 8311249Sradhika.jagtap@ARM.com 8411249Sradhika.jagtap@ARM.comTraceCPU::~TraceCPU() 8511249Sradhika.jagtap@ARM.com{ 8611249Sradhika.jagtap@ARM.com 8711249Sradhika.jagtap@ARM.com} 8811249Sradhika.jagtap@ARM.com 8911249Sradhika.jagtap@ARM.comTraceCPU* 9011249Sradhika.jagtap@ARM.comTraceCPUParams::create() 9111249Sradhika.jagtap@ARM.com{ 9211249Sradhika.jagtap@ARM.com return new TraceCPU(this); 9311249Sradhika.jagtap@ARM.com} 9411249Sradhika.jagtap@ARM.com 9511249Sradhika.jagtap@ARM.comvoid 9611918Sradhika.jagtap@arm.comTraceCPU::updateNumOps(uint64_t rob_num) 9711918Sradhika.jagtap@arm.com{ 9811918Sradhika.jagtap@arm.com numOps = rob_num; 9911918Sradhika.jagtap@arm.com if (progressMsgInterval != 0 && numOps.value() >= progressMsgThreshold) { 10011918Sradhika.jagtap@arm.com inform("%s: %i insts committed\n", name(), progressMsgThreshold); 10111918Sradhika.jagtap@arm.com progressMsgThreshold += progressMsgInterval; 10211918Sradhika.jagtap@arm.com } 10311918Sradhika.jagtap@arm.com} 10411918Sradhika.jagtap@arm.com 10511918Sradhika.jagtap@arm.comvoid 10611249Sradhika.jagtap@ARM.comTraceCPU::takeOverFrom(BaseCPU *oldCPU) 10711249Sradhika.jagtap@ARM.com{ 10811249Sradhika.jagtap@ARM.com // Unbind the ports of the old CPU and bind the ports of the TraceCPU. 10911249Sradhika.jagtap@ARM.com assert(!getInstPort().isConnected()); 11011249Sradhika.jagtap@ARM.com assert(oldCPU->getInstPort().isConnected()); 11111249Sradhika.jagtap@ARM.com BaseSlavePort &inst_peer_port = oldCPU->getInstPort().getSlavePort(); 11211249Sradhika.jagtap@ARM.com oldCPU->getInstPort().unbind(); 11311249Sradhika.jagtap@ARM.com getInstPort().bind(inst_peer_port); 11411249Sradhika.jagtap@ARM.com 11511249Sradhika.jagtap@ARM.com assert(!getDataPort().isConnected()); 11611249Sradhika.jagtap@ARM.com assert(oldCPU->getDataPort().isConnected()); 11711249Sradhika.jagtap@ARM.com BaseSlavePort &data_peer_port = oldCPU->getDataPort().getSlavePort(); 11811249Sradhika.jagtap@ARM.com oldCPU->getDataPort().unbind(); 11911249Sradhika.jagtap@ARM.com getDataPort().bind(data_peer_port); 12011249Sradhika.jagtap@ARM.com} 12111249Sradhika.jagtap@ARM.com 12211249Sradhika.jagtap@ARM.comvoid 12311249Sradhika.jagtap@ARM.comTraceCPU::init() 12411249Sradhika.jagtap@ARM.com{ 12511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Instruction fetch request trace file is \"%s\"." 12611249Sradhika.jagtap@ARM.com "\n", instTraceFile); 12711249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Data memory request trace file is \"%s\".\n", 12811249Sradhika.jagtap@ARM.com dataTraceFile); 12911249Sradhika.jagtap@ARM.com 13011249Sradhika.jagtap@ARM.com BaseCPU::init(); 13111249Sradhika.jagtap@ARM.com 13211632Sradhika.jagtap@arm.com // Get the send tick of the first instruction read request 13311249Sradhika.jagtap@ARM.com Tick first_icache_tick = icacheGen.init(); 13411249Sradhika.jagtap@ARM.com 13511632Sradhika.jagtap@arm.com // Get the send tick of the first data read/write request 13611249Sradhika.jagtap@ARM.com Tick first_dcache_tick = dcacheGen.init(); 13711632Sradhika.jagtap@arm.com 13811632Sradhika.jagtap@arm.com // Set the trace offset as the minimum of that in both traces 13911632Sradhika.jagtap@arm.com traceOffset = std::min(first_icache_tick, first_dcache_tick); 14011632Sradhika.jagtap@arm.com inform("%s: Time offset (tick) found as min of both traces is %lli.\n", 14111632Sradhika.jagtap@arm.com name(), traceOffset); 14211632Sradhika.jagtap@arm.com 14311632Sradhika.jagtap@arm.com // Schedule next icache and dcache event by subtracting the offset 14411632Sradhika.jagtap@arm.com schedule(icacheNextEvent, first_icache_tick - traceOffset); 14511632Sradhika.jagtap@arm.com schedule(dcacheNextEvent, first_dcache_tick - traceOffset); 14611632Sradhika.jagtap@arm.com 14711632Sradhika.jagtap@arm.com // Adjust the trace offset for the dcache generator's ready nodes 14811632Sradhika.jagtap@arm.com // We don't need to do this for the icache generator as it will 14911632Sradhika.jagtap@arm.com // send its first request at the first event and schedule subsequent 15011632Sradhika.jagtap@arm.com // events using a relative tick delta 15111632Sradhika.jagtap@arm.com dcacheGen.adjustInitTraceOffset(traceOffset); 15211249Sradhika.jagtap@ARM.com 15311633Sradhika.jagtap@arm.com // If the Trace CPU simulation is configured to exit on any one trace 15411633Sradhika.jagtap@arm.com // completion then we don't need a counted event to count down all Trace 15511633Sradhika.jagtap@arm.com // CPUs in the system. If not then instantiate a counted event. 15611633Sradhika.jagtap@arm.com if (!enableEarlyExit) { 15711633Sradhika.jagtap@arm.com // The static counter for number of Trace CPUs is correctly set at 15811633Sradhika.jagtap@arm.com // this point so create an event and pass it. 15911633Sradhika.jagtap@arm.com execCompleteEvent = new CountedExitEvent("end of all traces reached.", 16011633Sradhika.jagtap@arm.com numTraceCPUs); 16111633Sradhika.jagtap@arm.com } 16211633Sradhika.jagtap@arm.com 16311249Sradhika.jagtap@ARM.com} 16411249Sradhika.jagtap@ARM.com 16511249Sradhika.jagtap@ARM.comvoid 16611249Sradhika.jagtap@ARM.comTraceCPU::schedIcacheNext() 16711249Sradhika.jagtap@ARM.com{ 16811249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "IcacheGen event.\n"); 16911249Sradhika.jagtap@ARM.com 17011249Sradhika.jagtap@ARM.com // Try to send the current packet or a retry packet if there is one 17111249Sradhika.jagtap@ARM.com bool sched_next = icacheGen.tryNext(); 17211249Sradhika.jagtap@ARM.com // If packet sent successfully, schedule next event 17311249Sradhika.jagtap@ARM.com if (sched_next) { 17411249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Scheduling next icacheGen event " 17511249Sradhika.jagtap@ARM.com "at %d.\n", curTick() + icacheGen.tickDelta()); 17611249Sradhika.jagtap@ARM.com schedule(icacheNextEvent, curTick() + icacheGen.tickDelta()); 17711249Sradhika.jagtap@ARM.com ++numSchedIcacheEvent; 17811249Sradhika.jagtap@ARM.com } else { 17911249Sradhika.jagtap@ARM.com // check if traceComplete. If not, do nothing because sending failed 18011249Sradhika.jagtap@ARM.com // and next event will be scheduled via RecvRetry() 18111249Sradhika.jagtap@ARM.com if (icacheGen.isTraceComplete()) { 18211249Sradhika.jagtap@ARM.com // If this is the first trace to complete, set the variable. If it 18311249Sradhika.jagtap@ARM.com // is already set then both traces are complete to exit sim. 18411249Sradhika.jagtap@ARM.com checkAndSchedExitEvent(); 18511249Sradhika.jagtap@ARM.com } 18611249Sradhika.jagtap@ARM.com } 18711249Sradhika.jagtap@ARM.com return; 18811249Sradhika.jagtap@ARM.com} 18911249Sradhika.jagtap@ARM.com 19011249Sradhika.jagtap@ARM.comvoid 19111249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNext() 19211249Sradhika.jagtap@ARM.com{ 19311249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "DcacheGen event.\n"); 19411249Sradhika.jagtap@ARM.com 19511632Sradhika.jagtap@arm.com // Update stat for numCycles 19611632Sradhika.jagtap@arm.com numCycles = clockEdge() / clockPeriod(); 19711632Sradhika.jagtap@arm.com 19811249Sradhika.jagtap@ARM.com dcacheGen.execute(); 19911249Sradhika.jagtap@ARM.com if (dcacheGen.isExecComplete()) { 20011249Sradhika.jagtap@ARM.com checkAndSchedExitEvent(); 20111249Sradhika.jagtap@ARM.com } 20211249Sradhika.jagtap@ARM.com} 20311249Sradhika.jagtap@ARM.com 20411249Sradhika.jagtap@ARM.comvoid 20511249Sradhika.jagtap@ARM.comTraceCPU::checkAndSchedExitEvent() 20611249Sradhika.jagtap@ARM.com{ 20711249Sradhika.jagtap@ARM.com if (!oneTraceComplete) { 20811249Sradhika.jagtap@ARM.com oneTraceComplete = true; 20911249Sradhika.jagtap@ARM.com } else { 21011249Sradhika.jagtap@ARM.com // Schedule event to indicate execution is complete as both 21111249Sradhika.jagtap@ARM.com // instruction and data access traces have been played back. 21211249Sradhika.jagtap@ARM.com inform("%s: Execution complete.\n", name()); 21311633Sradhika.jagtap@arm.com // If the replay is configured to exit early, that is when any one 21411633Sradhika.jagtap@arm.com // execution is complete then exit immediately and return. Otherwise, 21511633Sradhika.jagtap@arm.com // schedule the counted exit that counts down completion of each Trace 21611633Sradhika.jagtap@arm.com // CPU. 21711633Sradhika.jagtap@arm.com if (enableEarlyExit) { 21811633Sradhika.jagtap@arm.com exitSimLoop("End of trace reached"); 21911633Sradhika.jagtap@arm.com } else { 22011633Sradhika.jagtap@arm.com schedule(*execCompleteEvent, curTick()); 22111633Sradhika.jagtap@arm.com } 22211249Sradhika.jagtap@ARM.com } 22311249Sradhika.jagtap@ARM.com} 22411249Sradhika.jagtap@ARM.com 22511249Sradhika.jagtap@ARM.comvoid 22611249Sradhika.jagtap@ARM.comTraceCPU::regStats() 22711249Sradhika.jagtap@ARM.com{ 22811249Sradhika.jagtap@ARM.com 22911249Sradhika.jagtap@ARM.com BaseCPU::regStats(); 23011249Sradhika.jagtap@ARM.com 23111249Sradhika.jagtap@ARM.com numSchedDcacheEvent 23211249Sradhika.jagtap@ARM.com .name(name() + ".numSchedDcacheEvent") 23311249Sradhika.jagtap@ARM.com .desc("Number of events scheduled to trigger data request generator") 23411249Sradhika.jagtap@ARM.com ; 23511249Sradhika.jagtap@ARM.com 23611249Sradhika.jagtap@ARM.com numSchedIcacheEvent 23711249Sradhika.jagtap@ARM.com .name(name() + ".numSchedIcacheEvent") 23811249Sradhika.jagtap@ARM.com .desc("Number of events scheduled to trigger instruction request generator") 23911249Sradhika.jagtap@ARM.com ; 24011249Sradhika.jagtap@ARM.com 24111249Sradhika.jagtap@ARM.com numOps 24211249Sradhika.jagtap@ARM.com .name(name() + ".numOps") 24311249Sradhika.jagtap@ARM.com .desc("Number of micro-ops simulated by the Trace CPU") 24411249Sradhika.jagtap@ARM.com ; 24511249Sradhika.jagtap@ARM.com 24611249Sradhika.jagtap@ARM.com cpi 24711249Sradhika.jagtap@ARM.com .name(name() + ".cpi") 24811249Sradhika.jagtap@ARM.com .desc("Cycles per micro-op used as a proxy for CPI") 24911249Sradhika.jagtap@ARM.com .precision(6) 25011249Sradhika.jagtap@ARM.com ; 25111249Sradhika.jagtap@ARM.com cpi = numCycles/numOps; 25211249Sradhika.jagtap@ARM.com 25311249Sradhika.jagtap@ARM.com icacheGen.regStats(); 25411249Sradhika.jagtap@ARM.com dcacheGen.regStats(); 25511249Sradhika.jagtap@ARM.com} 25611249Sradhika.jagtap@ARM.com 25711249Sradhika.jagtap@ARM.comvoid 25811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::regStats() 25911249Sradhika.jagtap@ARM.com{ 26011249Sradhika.jagtap@ARM.com using namespace Stats; 26111249Sradhika.jagtap@ARM.com 26211249Sradhika.jagtap@ARM.com maxDependents 26311249Sradhika.jagtap@ARM.com .name(name() + ".maxDependents") 26411249Sradhika.jagtap@ARM.com .desc("Max number of dependents observed on a node") 26511249Sradhika.jagtap@ARM.com ; 26611249Sradhika.jagtap@ARM.com 26711249Sradhika.jagtap@ARM.com maxReadyListSize 26811249Sradhika.jagtap@ARM.com .name(name() + ".maxReadyListSize") 26911249Sradhika.jagtap@ARM.com .desc("Max size of the ready list observed") 27011249Sradhika.jagtap@ARM.com ; 27111249Sradhika.jagtap@ARM.com 27211249Sradhika.jagtap@ARM.com numSendAttempted 27311249Sradhika.jagtap@ARM.com .name(name() + ".numSendAttempted") 27411249Sradhika.jagtap@ARM.com .desc("Number of first attempts to send a request") 27511249Sradhika.jagtap@ARM.com ; 27611249Sradhika.jagtap@ARM.com 27711249Sradhika.jagtap@ARM.com numSendSucceeded 27811249Sradhika.jagtap@ARM.com .name(name() + ".numSendSucceeded") 27911249Sradhika.jagtap@ARM.com .desc("Number of successful first attempts") 28011249Sradhika.jagtap@ARM.com ; 28111249Sradhika.jagtap@ARM.com 28211249Sradhika.jagtap@ARM.com numSendFailed 28311249Sradhika.jagtap@ARM.com .name(name() + ".numSendFailed") 28411249Sradhika.jagtap@ARM.com .desc("Number of failed first attempts") 28511249Sradhika.jagtap@ARM.com ; 28611249Sradhika.jagtap@ARM.com 28711249Sradhika.jagtap@ARM.com numRetrySucceeded 28811249Sradhika.jagtap@ARM.com .name(name() + ".numRetrySucceeded") 28911249Sradhika.jagtap@ARM.com .desc("Number of successful retries") 29011249Sradhika.jagtap@ARM.com ; 29111249Sradhika.jagtap@ARM.com 29211249Sradhika.jagtap@ARM.com numSplitReqs 29311249Sradhika.jagtap@ARM.com .name(name() + ".numSplitReqs") 29411249Sradhika.jagtap@ARM.com .desc("Number of split requests") 29511249Sradhika.jagtap@ARM.com ; 29611249Sradhika.jagtap@ARM.com 29711249Sradhika.jagtap@ARM.com numSOLoads 29811249Sradhika.jagtap@ARM.com .name(name() + ".numSOLoads") 29911249Sradhika.jagtap@ARM.com .desc("Number of strictly ordered loads") 30011249Sradhika.jagtap@ARM.com ; 30111249Sradhika.jagtap@ARM.com 30211249Sradhika.jagtap@ARM.com numSOStores 30311249Sradhika.jagtap@ARM.com .name(name() + ".numSOStores") 30411249Sradhika.jagtap@ARM.com .desc("Number of strictly ordered stores") 30511249Sradhika.jagtap@ARM.com ; 30611249Sradhika.jagtap@ARM.com 30711249Sradhika.jagtap@ARM.com dataLastTick 30811249Sradhika.jagtap@ARM.com .name(name() + ".dataLastTick") 30911249Sradhika.jagtap@ARM.com .desc("Last tick simulated from the elastic data trace") 31011249Sradhika.jagtap@ARM.com ; 31111249Sradhika.jagtap@ARM.com} 31211249Sradhika.jagtap@ARM.com 31311249Sradhika.jagtap@ARM.comTick 31411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::init() 31511249Sradhika.jagtap@ARM.com{ 31611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Initializing data memory request generator " 31711249Sradhika.jagtap@ARM.com "DcacheGen: elastic issue with retry.\n"); 31811249Sradhika.jagtap@ARM.com 31911249Sradhika.jagtap@ARM.com if (!readNextWindow()) 32011249Sradhika.jagtap@ARM.com panic("Trace has %d elements. It must have at least %d elements.\n", 32111249Sradhika.jagtap@ARM.com depGraph.size(), 2 * windowSize); 32211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "After 1st read, depGraph size:%d.\n", 32311249Sradhika.jagtap@ARM.com depGraph.size()); 32411249Sradhika.jagtap@ARM.com 32511249Sradhika.jagtap@ARM.com if (!readNextWindow()) 32611249Sradhika.jagtap@ARM.com panic("Trace has %d elements. It must have at least %d elements.\n", 32711249Sradhika.jagtap@ARM.com depGraph.size(), 2 * windowSize); 32811249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "After 2st read, depGraph size:%d.\n", 32911249Sradhika.jagtap@ARM.com depGraph.size()); 33011249Sradhika.jagtap@ARM.com 33111249Sradhika.jagtap@ARM.com // Print readyList 33211249Sradhika.jagtap@ARM.com if (DTRACE(TraceCPUData)) { 33311249Sradhika.jagtap@ARM.com printReadyList(); 33411249Sradhika.jagtap@ARM.com } 33511249Sradhika.jagtap@ARM.com auto free_itr = readyList.begin(); 33611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Execute tick of the first dependency free node %lli" 33711249Sradhika.jagtap@ARM.com " is %d.\n", free_itr->seqNum, free_itr->execTick); 33811249Sradhika.jagtap@ARM.com // Return the execute tick of the earliest ready node so that an event 33911249Sradhika.jagtap@ARM.com // can be scheduled to call execute() 34011249Sradhika.jagtap@ARM.com return (free_itr->execTick); 34111249Sradhika.jagtap@ARM.com} 34211249Sradhika.jagtap@ARM.com 34311249Sradhika.jagtap@ARM.comvoid 34411632Sradhika.jagtap@arm.comTraceCPU::ElasticDataGen::adjustInitTraceOffset(Tick& offset) { 34511632Sradhika.jagtap@arm.com for (auto& free_node : readyList) { 34611632Sradhika.jagtap@arm.com free_node.execTick -= offset; 34711632Sradhika.jagtap@arm.com } 34811632Sradhika.jagtap@arm.com} 34911632Sradhika.jagtap@arm.com 35011632Sradhika.jagtap@arm.comvoid 35111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::exit() 35211249Sradhika.jagtap@ARM.com{ 35311249Sradhika.jagtap@ARM.com trace.reset(); 35411249Sradhika.jagtap@ARM.com} 35511249Sradhika.jagtap@ARM.com 35611249Sradhika.jagtap@ARM.combool 35711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::readNextWindow() 35811249Sradhika.jagtap@ARM.com{ 35911249Sradhika.jagtap@ARM.com 36011249Sradhika.jagtap@ARM.com // Read and add next window 36111249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Reading next window from file.\n"); 36211249Sradhika.jagtap@ARM.com 36311249Sradhika.jagtap@ARM.com if (traceComplete) { 36411249Sradhika.jagtap@ARM.com // We are at the end of the file, thus we have no more records. 36511249Sradhika.jagtap@ARM.com // Return false. 36611249Sradhika.jagtap@ARM.com return false; 36711249Sradhika.jagtap@ARM.com } 36811249Sradhika.jagtap@ARM.com 36911249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Start read: Size of depGraph is %d.\n", 37011249Sradhika.jagtap@ARM.com depGraph.size()); 37111249Sradhika.jagtap@ARM.com 37211249Sradhika.jagtap@ARM.com uint32_t num_read = 0; 37311249Sradhika.jagtap@ARM.com while (num_read != windowSize) { 37411249Sradhika.jagtap@ARM.com 37511249Sradhika.jagtap@ARM.com // Create a new graph node 37611249Sradhika.jagtap@ARM.com GraphNode* new_node = new GraphNode; 37711249Sradhika.jagtap@ARM.com 37811249Sradhika.jagtap@ARM.com // Read the next line to get the next record. If that fails then end of 37911249Sradhika.jagtap@ARM.com // trace has been reached and traceComplete needs to be set in addition 38011249Sradhika.jagtap@ARM.com // to returning false. 38111249Sradhika.jagtap@ARM.com if (!trace.read(new_node)) { 38211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "\tTrace complete!\n"); 38311249Sradhika.jagtap@ARM.com traceComplete = true; 38411249Sradhika.jagtap@ARM.com return false; 38511249Sradhika.jagtap@ARM.com } 38611249Sradhika.jagtap@ARM.com 38711249Sradhika.jagtap@ARM.com // Annotate the ROB dependencies of the new node onto the parent nodes. 38811249Sradhika.jagtap@ARM.com addDepsOnParent(new_node, new_node->robDep, new_node->numRobDep); 38911249Sradhika.jagtap@ARM.com // Annotate the register dependencies of the new node onto the parent 39011249Sradhika.jagtap@ARM.com // nodes. 39111249Sradhika.jagtap@ARM.com addDepsOnParent(new_node, new_node->regDep, new_node->numRegDep); 39211249Sradhika.jagtap@ARM.com 39311249Sradhika.jagtap@ARM.com num_read++; 39411249Sradhika.jagtap@ARM.com // Add to map 39511249Sradhika.jagtap@ARM.com depGraph[new_node->seqNum] = new_node; 39611249Sradhika.jagtap@ARM.com if (new_node->numRobDep == 0 && new_node->numRegDep == 0) { 39711249Sradhika.jagtap@ARM.com // Source dependencies are already complete, check if resources 39811249Sradhika.jagtap@ARM.com // are available and issue. The execution time is approximated 39911249Sradhika.jagtap@ARM.com // to current time plus the computational delay. 40011249Sradhika.jagtap@ARM.com checkAndIssue(new_node); 40111249Sradhika.jagtap@ARM.com } 40211249Sradhika.jagtap@ARM.com } 40311249Sradhika.jagtap@ARM.com 40411249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "End read: Size of depGraph is %d.\n", 40511249Sradhika.jagtap@ARM.com depGraph.size()); 40611249Sradhika.jagtap@ARM.com return true; 40711249Sradhika.jagtap@ARM.com} 40811249Sradhika.jagtap@ARM.com 40911249Sradhika.jagtap@ARM.comtemplate<typename T> void 41011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addDepsOnParent(GraphNode *new_node, 41111249Sradhika.jagtap@ARM.com T& dep_array, uint8_t& num_dep) 41211249Sradhika.jagtap@ARM.com{ 41311249Sradhika.jagtap@ARM.com for (auto& a_dep : dep_array) { 41411249Sradhika.jagtap@ARM.com // The convention is to set the dependencies starting with the first 41511249Sradhika.jagtap@ARM.com // index in the ROB and register dependency arrays. Thus, when we reach 41611249Sradhika.jagtap@ARM.com // a dependency equal to the initialisation value of zero, we know have 41711249Sradhika.jagtap@ARM.com // iterated over all dependencies and can break. 41811249Sradhika.jagtap@ARM.com if (a_dep == 0) 41911249Sradhika.jagtap@ARM.com break; 42011249Sradhika.jagtap@ARM.com // We look up the valid dependency, i.e. the parent of this node 42111249Sradhika.jagtap@ARM.com auto parent_itr = depGraph.find(a_dep); 42211249Sradhika.jagtap@ARM.com if (parent_itr != depGraph.end()) { 42311249Sradhika.jagtap@ARM.com // If the parent is found, it is yet to be executed. Append a 42411249Sradhika.jagtap@ARM.com // pointer to the new node to the dependents list of the parent 42511249Sradhika.jagtap@ARM.com // node. 42611249Sradhika.jagtap@ARM.com parent_itr->second->dependents.push_back(new_node); 42711249Sradhika.jagtap@ARM.com auto num_depts = parent_itr->second->dependents.size(); 42811249Sradhika.jagtap@ARM.com maxDependents = std::max<double>(num_depts, maxDependents.value()); 42911249Sradhika.jagtap@ARM.com } else { 43011249Sradhika.jagtap@ARM.com // The dependency is not found in the graph. So consider 43111249Sradhika.jagtap@ARM.com // the execution of the parent is complete, i.e. remove this 43211249Sradhika.jagtap@ARM.com // dependency. 43311249Sradhika.jagtap@ARM.com a_dep = 0; 43411249Sradhika.jagtap@ARM.com num_dep--; 43511249Sradhika.jagtap@ARM.com } 43611249Sradhika.jagtap@ARM.com } 43711249Sradhika.jagtap@ARM.com} 43811249Sradhika.jagtap@ARM.com 43911249Sradhika.jagtap@ARM.comvoid 44011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::execute() 44111249Sradhika.jagtap@ARM.com{ 44211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Execute start occupancy:\n"); 44311249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, " 44411249Sradhika.jagtap@ARM.com "depFreeQueue = %d ,", depGraph.size(), readyList.size(), 44511249Sradhika.jagtap@ARM.com depFreeQueue.size()); 44611249Sradhika.jagtap@ARM.com hwResource.printOccupancy(); 44711249Sradhika.jagtap@ARM.com 44811249Sradhika.jagtap@ARM.com // Read next window to make sure that dependents of all dep-free nodes 44911249Sradhika.jagtap@ARM.com // are in the depGraph 45011249Sradhika.jagtap@ARM.com if (nextRead) { 45111249Sradhika.jagtap@ARM.com readNextWindow(); 45211249Sradhika.jagtap@ARM.com nextRead = false; 45311249Sradhika.jagtap@ARM.com } 45411249Sradhika.jagtap@ARM.com 45511249Sradhika.jagtap@ARM.com // First attempt to issue the pending dependency-free nodes held 45611249Sradhika.jagtap@ARM.com // in depFreeQueue. If resources have become available for a node, 45711249Sradhika.jagtap@ARM.com // then issue it, i.e. add the node to readyList. 45811249Sradhika.jagtap@ARM.com while (!depFreeQueue.empty()) { 45911249Sradhika.jagtap@ARM.com if (checkAndIssue(depFreeQueue.front(), false)) { 46011249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Removing from depFreeQueue: seq. num " 46111249Sradhika.jagtap@ARM.com "%lli.\n", (depFreeQueue.front())->seqNum); 46211249Sradhika.jagtap@ARM.com depFreeQueue.pop(); 46311249Sradhika.jagtap@ARM.com } else { 46411249Sradhika.jagtap@ARM.com break; 46511249Sradhika.jagtap@ARM.com } 46611249Sradhika.jagtap@ARM.com } 46711249Sradhika.jagtap@ARM.com // Proceed to execute from readyList 46811249Sradhika.jagtap@ARM.com auto graph_itr = depGraph.begin(); 46911249Sradhika.jagtap@ARM.com auto free_itr = readyList.begin(); 47011249Sradhika.jagtap@ARM.com // Iterate through readyList until the next free node has its execute 47111249Sradhika.jagtap@ARM.com // tick later than curTick or the end of readyList is reached 47211249Sradhika.jagtap@ARM.com while (free_itr->execTick <= curTick() && free_itr != readyList.end()) { 47311249Sradhika.jagtap@ARM.com 47411249Sradhika.jagtap@ARM.com // Get pointer to the node to be executed 47511249Sradhika.jagtap@ARM.com graph_itr = depGraph.find(free_itr->seqNum); 47611249Sradhika.jagtap@ARM.com assert(graph_itr != depGraph.end()); 47711249Sradhika.jagtap@ARM.com GraphNode* node_ptr = graph_itr->second; 47811249Sradhika.jagtap@ARM.com 47911249Sradhika.jagtap@ARM.com // If there is a retryPkt send that else execute the load 48011249Sradhika.jagtap@ARM.com if (retryPkt) { 48111249Sradhika.jagtap@ARM.com // The retryPkt must be the request that was created by the 48211249Sradhika.jagtap@ARM.com // first node in the readyList. 48311249Sradhika.jagtap@ARM.com if (retryPkt->req->getReqInstSeqNum() != node_ptr->seqNum) { 48411249Sradhika.jagtap@ARM.com panic("Retry packet's seqence number does not match " 48511249Sradhika.jagtap@ARM.com "the first node in the readyList.\n"); 48611249Sradhika.jagtap@ARM.com } 48711249Sradhika.jagtap@ARM.com if (port.sendTimingReq(retryPkt)) { 48811249Sradhika.jagtap@ARM.com ++numRetrySucceeded; 48911249Sradhika.jagtap@ARM.com retryPkt = nullptr; 49011249Sradhika.jagtap@ARM.com } 49111252Sradhika.jagtap@ARM.com } else if (node_ptr->isLoad() || node_ptr->isStore()) { 49211249Sradhika.jagtap@ARM.com // If there is no retryPkt, attempt to send a memory request in 49311249Sradhika.jagtap@ARM.com // case of a load or store node. If the send fails, executeMemReq() 49411249Sradhika.jagtap@ARM.com // returns a packet pointer, which we save in retryPkt. In case of 49511249Sradhika.jagtap@ARM.com // a comp node we don't do anything and simply continue as if the 49611249Sradhika.jagtap@ARM.com // execution of the comp node succedded. 49711249Sradhika.jagtap@ARM.com retryPkt = executeMemReq(node_ptr); 49811249Sradhika.jagtap@ARM.com } 49911249Sradhika.jagtap@ARM.com // If the retryPkt or a new load/store node failed, we exit from here 50011249Sradhika.jagtap@ARM.com // as a retry from cache will bring the control to execute(). The 50111249Sradhika.jagtap@ARM.com // first node in readyList then, will be the failed node. 50211249Sradhika.jagtap@ARM.com if (retryPkt) { 50311249Sradhika.jagtap@ARM.com break; 50411249Sradhika.jagtap@ARM.com } 50511249Sradhika.jagtap@ARM.com 50611249Sradhika.jagtap@ARM.com // Proceed to remove dependencies for the successfully executed node. 50711249Sradhika.jagtap@ARM.com // If it is a load which is not strictly ordered and we sent a 50811249Sradhika.jagtap@ARM.com // request for it successfully, we do not yet mark any register 50911249Sradhika.jagtap@ARM.com // dependencies complete. But as per dependency modelling we need 51011249Sradhika.jagtap@ARM.com // to mark ROB dependencies of load and non load/store nodes which 51111249Sradhika.jagtap@ARM.com // are based on successful sending of the load as complete. 51211252Sradhika.jagtap@ARM.com if (node_ptr->isLoad() && !node_ptr->isStrictlyOrdered()) { 51311249Sradhika.jagtap@ARM.com // If execute succeeded mark its dependents as complete 51411249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Node seq. num %lli sent. Waking up " 51511249Sradhika.jagtap@ARM.com "dependents..\n", node_ptr->seqNum); 51611249Sradhika.jagtap@ARM.com 51711249Sradhika.jagtap@ARM.com auto child_itr = (node_ptr->dependents).begin(); 51811249Sradhika.jagtap@ARM.com while (child_itr != (node_ptr->dependents).end()) { 51911249Sradhika.jagtap@ARM.com // ROB dependency of a store on a load must not be removed 52011249Sradhika.jagtap@ARM.com // after load is sent but after response is received 52111252Sradhika.jagtap@ARM.com if (!(*child_itr)->isStore() && 52211249Sradhika.jagtap@ARM.com (*child_itr)->removeRobDep(node_ptr->seqNum)) { 52311249Sradhika.jagtap@ARM.com 52411249Sradhika.jagtap@ARM.com // Check if the child node has become dependency free 52511249Sradhika.jagtap@ARM.com if ((*child_itr)->numRobDep == 0 && 52611249Sradhika.jagtap@ARM.com (*child_itr)->numRegDep == 0) { 52711249Sradhika.jagtap@ARM.com 52811249Sradhika.jagtap@ARM.com // Source dependencies are complete, check if 52911249Sradhika.jagtap@ARM.com // resources are available and issue 53011249Sradhika.jagtap@ARM.com checkAndIssue(*child_itr); 53111249Sradhika.jagtap@ARM.com } 53211249Sradhika.jagtap@ARM.com // Remove this child for the sent load and point to new 53311249Sradhika.jagtap@ARM.com // location of the element following the erased element 53411249Sradhika.jagtap@ARM.com child_itr = node_ptr->dependents.erase(child_itr); 53511249Sradhika.jagtap@ARM.com } else { 53611249Sradhika.jagtap@ARM.com // This child is not dependency-free, point to the next 53711249Sradhika.jagtap@ARM.com // child 53811249Sradhika.jagtap@ARM.com child_itr++; 53911249Sradhika.jagtap@ARM.com } 54011249Sradhika.jagtap@ARM.com } 54111249Sradhika.jagtap@ARM.com } else { 54211249Sradhika.jagtap@ARM.com // If it is a strictly ordered load mark its dependents as complete 54311249Sradhika.jagtap@ARM.com // as we do not send a request for this case. If it is a store or a 54411249Sradhika.jagtap@ARM.com // comp node we also mark all its dependents complete. 54511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Node seq. num %lli done. Waking" 54611249Sradhika.jagtap@ARM.com " up dependents..\n", node_ptr->seqNum); 54711249Sradhika.jagtap@ARM.com 54811249Sradhika.jagtap@ARM.com for (auto child : node_ptr->dependents) { 54911249Sradhika.jagtap@ARM.com // If the child node is dependency free removeDepOnInst() 55011249Sradhika.jagtap@ARM.com // returns true. 55111249Sradhika.jagtap@ARM.com if (child->removeDepOnInst(node_ptr->seqNum)) { 55211249Sradhika.jagtap@ARM.com // Source dependencies are complete, check if resources 55311249Sradhika.jagtap@ARM.com // are available and issue 55411249Sradhika.jagtap@ARM.com checkAndIssue(child); 55511249Sradhika.jagtap@ARM.com } 55611249Sradhika.jagtap@ARM.com } 55711249Sradhika.jagtap@ARM.com } 55811249Sradhika.jagtap@ARM.com 55911249Sradhika.jagtap@ARM.com // After executing the node, remove from readyList and delete node. 56011249Sradhika.jagtap@ARM.com readyList.erase(free_itr); 56111249Sradhika.jagtap@ARM.com // If it is a cacheable load which was sent, don't delete 56211249Sradhika.jagtap@ARM.com // just yet. Delete it in completeMemAccess() after the 56311249Sradhika.jagtap@ARM.com // response is received. If it is an strictly ordered 56411249Sradhika.jagtap@ARM.com // load, it was not sent and all dependencies were simply 56511249Sradhika.jagtap@ARM.com // marked complete. Thus it is safe to delete it. For 56611249Sradhika.jagtap@ARM.com // stores and non load/store nodes all dependencies were 56711249Sradhika.jagtap@ARM.com // marked complete so it is safe to delete it. 56811252Sradhika.jagtap@ARM.com if (!node_ptr->isLoad() || node_ptr->isStrictlyOrdered()) { 56911249Sradhika.jagtap@ARM.com // Release all resources occupied by the completed node 57011249Sradhika.jagtap@ARM.com hwResource.release(node_ptr); 57111249Sradhika.jagtap@ARM.com // clear the dynamically allocated set of dependents 57211249Sradhika.jagtap@ARM.com (node_ptr->dependents).clear(); 57311632Sradhika.jagtap@arm.com // Update the stat for numOps simulated 57411632Sradhika.jagtap@arm.com owner.updateNumOps(node_ptr->robNum); 57511249Sradhika.jagtap@ARM.com // delete node 57611249Sradhika.jagtap@ARM.com delete node_ptr; 57711249Sradhika.jagtap@ARM.com // remove from graph 57811249Sradhika.jagtap@ARM.com depGraph.erase(graph_itr); 57911249Sradhika.jagtap@ARM.com } 58011249Sradhika.jagtap@ARM.com // Point to first node to continue to next iteration of while loop 58111249Sradhika.jagtap@ARM.com free_itr = readyList.begin(); 58211249Sradhika.jagtap@ARM.com } // end of while loop 58311249Sradhika.jagtap@ARM.com 58411249Sradhika.jagtap@ARM.com // Print readyList, sizes of queues and resource status after updating 58511249Sradhika.jagtap@ARM.com if (DTRACE(TraceCPUData)) { 58611249Sradhika.jagtap@ARM.com printReadyList(); 58711249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Execute end occupancy:\n"); 58811249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tdepGraph = %d, readyList = %d, " 58911249Sradhika.jagtap@ARM.com "depFreeQueue = %d ,", depGraph.size(), readyList.size(), 59011249Sradhika.jagtap@ARM.com depFreeQueue.size()); 59111249Sradhika.jagtap@ARM.com hwResource.printOccupancy(); 59211249Sradhika.jagtap@ARM.com } 59311249Sradhika.jagtap@ARM.com 59411249Sradhika.jagtap@ARM.com if (retryPkt) { 59511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Not scheduling an event as expecting a retry" 59611249Sradhika.jagtap@ARM.com "event from the cache for seq. num %lli.\n", 59711249Sradhika.jagtap@ARM.com retryPkt->req->getReqInstSeqNum()); 59811249Sradhika.jagtap@ARM.com return; 59911249Sradhika.jagtap@ARM.com } 60011249Sradhika.jagtap@ARM.com // If the size of the dependency graph is less than the dependency window 60111249Sradhika.jagtap@ARM.com // then read from the trace file to populate the graph next time we are in 60211249Sradhika.jagtap@ARM.com // execute. 60311249Sradhika.jagtap@ARM.com if (depGraph.size() < windowSize && !traceComplete) 60411249Sradhika.jagtap@ARM.com nextRead = true; 60511249Sradhika.jagtap@ARM.com 60611249Sradhika.jagtap@ARM.com // If cache is not blocked, schedule an event for the first execTick in 60711249Sradhika.jagtap@ARM.com // readyList else retry from cache will schedule the event. If the ready 60811249Sradhika.jagtap@ARM.com // list is empty then check if the next pending node has resources 60911249Sradhika.jagtap@ARM.com // available to issue. If yes, then schedule an event for the next cycle. 61011249Sradhika.jagtap@ARM.com if (!readyList.empty()) { 61111249Sradhika.jagtap@ARM.com Tick next_event_tick = std::max(readyList.begin()->execTick, 61211249Sradhika.jagtap@ARM.com curTick()); 61311249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n", 61411249Sradhika.jagtap@ARM.com next_event_tick); 61511249Sradhika.jagtap@ARM.com owner.schedDcacheNextEvent(next_event_tick); 61611249Sradhika.jagtap@ARM.com } else if (readyList.empty() && !depFreeQueue.empty() && 61711249Sradhika.jagtap@ARM.com hwResource.isAvailable(depFreeQueue.front())) { 61811249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n", 61911249Sradhika.jagtap@ARM.com owner.clockEdge(Cycles(1))); 62011249Sradhika.jagtap@ARM.com owner.schedDcacheNextEvent(owner.clockEdge(Cycles(1))); 62111249Sradhika.jagtap@ARM.com } 62211249Sradhika.jagtap@ARM.com 62311249Sradhika.jagtap@ARM.com // If trace is completely read, readyList is empty and depGraph is empty, 62411249Sradhika.jagtap@ARM.com // set execComplete to true 62511249Sradhika.jagtap@ARM.com if (depGraph.empty() && readyList.empty() && traceComplete && 62611249Sradhika.jagtap@ARM.com !hwResource.awaitingResponse()) { 62711249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "\tExecution Complete!\n"); 62811249Sradhika.jagtap@ARM.com execComplete = true; 62911249Sradhika.jagtap@ARM.com dataLastTick = curTick(); 63011249Sradhika.jagtap@ARM.com } 63111249Sradhika.jagtap@ARM.com} 63211249Sradhika.jagtap@ARM.com 63311249Sradhika.jagtap@ARM.comPacketPtr 63411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::executeMemReq(GraphNode* node_ptr) 63511249Sradhika.jagtap@ARM.com{ 63611249Sradhika.jagtap@ARM.com 63711253Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Executing memory request %lli (phys addr %d, " 63811253Sradhika.jagtap@ARM.com "virt addr %d, pc %#x, size %d, flags %d).\n", 63911253Sradhika.jagtap@ARM.com node_ptr->seqNum, node_ptr->physAddr, node_ptr->virtAddr, 64011249Sradhika.jagtap@ARM.com node_ptr->pc, node_ptr->size, node_ptr->flags); 64111249Sradhika.jagtap@ARM.com 64211249Sradhika.jagtap@ARM.com // If the request is strictly ordered, do not send it. Just return nullptr 64311249Sradhika.jagtap@ARM.com // as if it was succesfully sent. 64411249Sradhika.jagtap@ARM.com if (node_ptr->isStrictlyOrdered()) { 64511252Sradhika.jagtap@ARM.com node_ptr->isLoad() ? ++numSOLoads : ++numSOStores; 64611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Skipping strictly ordered request %lli.\n", 64711249Sradhika.jagtap@ARM.com node_ptr->seqNum); 64811249Sradhika.jagtap@ARM.com return nullptr; 64911249Sradhika.jagtap@ARM.com } 65011249Sradhika.jagtap@ARM.com 65111249Sradhika.jagtap@ARM.com // Check if the request spans two cache lines as this condition triggers 65211249Sradhika.jagtap@ARM.com // an assert fail in the L1 cache. If it does then truncate the size to 65311249Sradhika.jagtap@ARM.com // access only until the end of that line and ignore the remainder. The 65411249Sradhika.jagtap@ARM.com // stat counting this is useful to keep a check on how frequently this 65511249Sradhika.jagtap@ARM.com // happens. If required the code could be revised to mimick splitting such 65611249Sradhika.jagtap@ARM.com // a request into two. 65711249Sradhika.jagtap@ARM.com unsigned blk_size = owner.cacheLineSize(); 65811253Sradhika.jagtap@ARM.com Addr blk_offset = (node_ptr->physAddr & (Addr)(blk_size - 1)); 65911249Sradhika.jagtap@ARM.com if (!(blk_offset + node_ptr->size <= blk_size)) { 66011249Sradhika.jagtap@ARM.com node_ptr->size = blk_size - blk_offset; 66111249Sradhika.jagtap@ARM.com ++numSplitReqs; 66211249Sradhika.jagtap@ARM.com } 66311249Sradhika.jagtap@ARM.com 66411249Sradhika.jagtap@ARM.com // Create a request and the packet containing request 66511253Sradhika.jagtap@ARM.com Request* req = new Request(node_ptr->physAddr, node_ptr->size, 66611253Sradhika.jagtap@ARM.com node_ptr->flags, masterID, node_ptr->seqNum, 66711435Smitch.hayenga@arm.com ContextID(0)); 66811249Sradhika.jagtap@ARM.com req->setPC(node_ptr->pc); 66911253Sradhika.jagtap@ARM.com // If virtual address is valid, set the asid and virtual address fields 67011253Sradhika.jagtap@ARM.com // of the request. 67111253Sradhika.jagtap@ARM.com if (node_ptr->virtAddr != 0) { 67211253Sradhika.jagtap@ARM.com req->setVirt(node_ptr->asid, node_ptr->virtAddr, node_ptr->size, 67311253Sradhika.jagtap@ARM.com node_ptr->flags, masterID, node_ptr->pc); 67411253Sradhika.jagtap@ARM.com req->setPaddr(node_ptr->physAddr); 67511253Sradhika.jagtap@ARM.com req->setReqInstSeqNum(node_ptr->seqNum); 67611253Sradhika.jagtap@ARM.com } 67711253Sradhika.jagtap@ARM.com 67811249Sradhika.jagtap@ARM.com PacketPtr pkt; 67911249Sradhika.jagtap@ARM.com uint8_t* pkt_data = new uint8_t[req->getSize()]; 68011252Sradhika.jagtap@ARM.com if (node_ptr->isLoad()) { 68111249Sradhika.jagtap@ARM.com pkt = Packet::createRead(req); 68211249Sradhika.jagtap@ARM.com } else { 68311249Sradhika.jagtap@ARM.com pkt = Packet::createWrite(req); 68411249Sradhika.jagtap@ARM.com memset(pkt_data, 0xA, req->getSize()); 68511249Sradhika.jagtap@ARM.com } 68611249Sradhika.jagtap@ARM.com pkt->dataDynamic(pkt_data); 68711249Sradhika.jagtap@ARM.com 68811249Sradhika.jagtap@ARM.com // Call MasterPort method to send a timing request for this packet 68911249Sradhika.jagtap@ARM.com bool success = port.sendTimingReq(pkt); 69011249Sradhika.jagtap@ARM.com ++numSendAttempted; 69111249Sradhika.jagtap@ARM.com 69211249Sradhika.jagtap@ARM.com if (!success) { 69311249Sradhika.jagtap@ARM.com // If it fails, return the packet to retry when a retry is signalled by 69411249Sradhika.jagtap@ARM.com // the cache 69511249Sradhika.jagtap@ARM.com ++numSendFailed; 69611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Send failed. Saving packet for retry.\n"); 69711249Sradhika.jagtap@ARM.com return pkt; 69811249Sradhika.jagtap@ARM.com } else { 69911249Sradhika.jagtap@ARM.com // It is succeeds, return nullptr 70011249Sradhika.jagtap@ARM.com ++numSendSucceeded; 70111249Sradhika.jagtap@ARM.com return nullptr; 70211249Sradhika.jagtap@ARM.com } 70311249Sradhika.jagtap@ARM.com} 70411249Sradhika.jagtap@ARM.com 70511249Sradhika.jagtap@ARM.combool 70611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::checkAndIssue(const GraphNode* node_ptr, bool first) 70711249Sradhika.jagtap@ARM.com{ 70811249Sradhika.jagtap@ARM.com // Assert the node is dependency-free 70911249Sradhika.jagtap@ARM.com assert(node_ptr->numRobDep == 0 && node_ptr->numRegDep == 0); 71011249Sradhika.jagtap@ARM.com 71111249Sradhika.jagtap@ARM.com // If this is the first attempt, print a debug message to indicate this. 71211249Sradhika.jagtap@ARM.com if (first) { 71311249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tseq. num %lli(%s) with rob num %lli is now" 71411252Sradhika.jagtap@ARM.com " dependency free.\n", node_ptr->seqNum, node_ptr->typeToStr(), 71511249Sradhika.jagtap@ARM.com node_ptr->robNum); 71611249Sradhika.jagtap@ARM.com } 71711249Sradhika.jagtap@ARM.com 71811249Sradhika.jagtap@ARM.com // Check if resources are available to issue the specific node 71911249Sradhika.jagtap@ARM.com if (hwResource.isAvailable(node_ptr)) { 72011249Sradhika.jagtap@ARM.com // If resources are free only then add to readyList 72111249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tResources available for seq. num %lli. Adding" 72211249Sradhika.jagtap@ARM.com " to readyList, occupying resources.\n", node_ptr->seqNum); 72311249Sradhika.jagtap@ARM.com // Compute the execute tick by adding the compute delay for the node 72411249Sradhika.jagtap@ARM.com // and add the ready node to the ready list 72511249Sradhika.jagtap@ARM.com addToSortedReadyList(node_ptr->seqNum, 72611249Sradhika.jagtap@ARM.com owner.clockEdge() + node_ptr->compDelay); 72711249Sradhika.jagtap@ARM.com // Account for the resources taken up by this issued node. 72811249Sradhika.jagtap@ARM.com hwResource.occupy(node_ptr); 72911249Sradhika.jagtap@ARM.com return true; 73011249Sradhika.jagtap@ARM.com 73111249Sradhika.jagtap@ARM.com } else { 73211249Sradhika.jagtap@ARM.com if (first) { 73311249Sradhika.jagtap@ARM.com // Although dependencies are complete, resources are not available. 73411249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli." 73511249Sradhika.jagtap@ARM.com " Adding to depFreeQueue.\n", node_ptr->seqNum); 73611249Sradhika.jagtap@ARM.com depFreeQueue.push(node_ptr); 73711249Sradhika.jagtap@ARM.com } else { 73811249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tResources unavailable for seq. num %lli. " 73911249Sradhika.jagtap@ARM.com "Still pending issue.\n", node_ptr->seqNum); 74011249Sradhika.jagtap@ARM.com } 74111249Sradhika.jagtap@ARM.com return false; 74211249Sradhika.jagtap@ARM.com } 74311249Sradhika.jagtap@ARM.com} 74411249Sradhika.jagtap@ARM.com 74511249Sradhika.jagtap@ARM.comvoid 74611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::completeMemAccess(PacketPtr pkt) 74711249Sradhika.jagtap@ARM.com{ 74811249Sradhika.jagtap@ARM.com // Release the resources for this completed node. 74911249Sradhika.jagtap@ARM.com if (pkt->isWrite()) { 75011249Sradhika.jagtap@ARM.com // Consider store complete. 75111249Sradhika.jagtap@ARM.com hwResource.releaseStoreBuffer(); 75211249Sradhika.jagtap@ARM.com // If it is a store response then do nothing since we do not model 75311249Sradhika.jagtap@ARM.com // dependencies on store completion in the trace. But if we were 75411249Sradhika.jagtap@ARM.com // blocking execution due to store buffer fullness, we need to schedule 75511249Sradhika.jagtap@ARM.com // an event and attempt to progress. 75611249Sradhika.jagtap@ARM.com } else { 75711249Sradhika.jagtap@ARM.com // If it is a load response then release the dependents waiting on it. 75811249Sradhika.jagtap@ARM.com // Get pointer to the completed load 75911249Sradhika.jagtap@ARM.com auto graph_itr = depGraph.find(pkt->req->getReqInstSeqNum()); 76011249Sradhika.jagtap@ARM.com assert(graph_itr != depGraph.end()); 76111249Sradhika.jagtap@ARM.com GraphNode* node_ptr = graph_itr->second; 76211249Sradhika.jagtap@ARM.com 76311249Sradhika.jagtap@ARM.com // Release resources occupied by the load 76411249Sradhika.jagtap@ARM.com hwResource.release(node_ptr); 76511249Sradhika.jagtap@ARM.com 76611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Load seq. num %lli response received. Waking up" 76711249Sradhika.jagtap@ARM.com " dependents..\n", node_ptr->seqNum); 76811249Sradhika.jagtap@ARM.com 76911249Sradhika.jagtap@ARM.com for (auto child : node_ptr->dependents) { 77011249Sradhika.jagtap@ARM.com if (child->removeDepOnInst(node_ptr->seqNum)) { 77111249Sradhika.jagtap@ARM.com checkAndIssue(child); 77211249Sradhika.jagtap@ARM.com } 77311249Sradhika.jagtap@ARM.com } 77411249Sradhika.jagtap@ARM.com 77511249Sradhika.jagtap@ARM.com // clear the dynamically allocated set of dependents 77611249Sradhika.jagtap@ARM.com (node_ptr->dependents).clear(); 77711632Sradhika.jagtap@arm.com // Update the stat for numOps completed 77811632Sradhika.jagtap@arm.com owner.updateNumOps(node_ptr->robNum); 77911249Sradhika.jagtap@ARM.com // delete node 78011249Sradhika.jagtap@ARM.com delete node_ptr; 78111249Sradhika.jagtap@ARM.com // remove from graph 78211249Sradhika.jagtap@ARM.com depGraph.erase(graph_itr); 78311249Sradhika.jagtap@ARM.com } 78411249Sradhika.jagtap@ARM.com 78511249Sradhika.jagtap@ARM.com if (DTRACE(TraceCPUData)) { 78611249Sradhika.jagtap@ARM.com printReadyList(); 78711249Sradhika.jagtap@ARM.com } 78811249Sradhika.jagtap@ARM.com 78911249Sradhika.jagtap@ARM.com // If the size of the dependency graph is less than the dependency window 79011249Sradhika.jagtap@ARM.com // then read from the trace file to populate the graph next time we are in 79111249Sradhika.jagtap@ARM.com // execute. 79211249Sradhika.jagtap@ARM.com if (depGraph.size() < windowSize && !traceComplete) 79311249Sradhika.jagtap@ARM.com nextRead = true; 79411249Sradhika.jagtap@ARM.com 79511249Sradhika.jagtap@ARM.com // If not waiting for retry, attempt to schedule next event 79611249Sradhika.jagtap@ARM.com if (!retryPkt) { 79711249Sradhika.jagtap@ARM.com // We might have new dep-free nodes in the list which will have execute 79811249Sradhika.jagtap@ARM.com // tick greater than or equal to curTick. But a new dep-free node might 79911249Sradhika.jagtap@ARM.com // have its execute tick earlier. Therefore, attempt to reschedule. It 80011249Sradhika.jagtap@ARM.com // could happen that the readyList is empty and we got here via a 80111249Sradhika.jagtap@ARM.com // last remaining response. So, either the trace is complete or there 80211249Sradhika.jagtap@ARM.com // are pending nodes in the depFreeQueue. The checking is done in the 80311249Sradhika.jagtap@ARM.com // execute() control flow, so schedule an event to go via that flow. 80411249Sradhika.jagtap@ARM.com Tick next_event_tick = readyList.empty() ? owner.clockEdge(Cycles(1)) : 80511249Sradhika.jagtap@ARM.com std::max(readyList.begin()->execTick, owner.clockEdge(Cycles(1))); 80611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Attempting to schedule @%lli.\n", 80711249Sradhika.jagtap@ARM.com next_event_tick); 80811249Sradhika.jagtap@ARM.com owner.schedDcacheNextEvent(next_event_tick); 80911249Sradhika.jagtap@ARM.com } 81011249Sradhika.jagtap@ARM.com} 81111249Sradhika.jagtap@ARM.com 81211249Sradhika.jagtap@ARM.comvoid 81311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::addToSortedReadyList(NodeSeqNum seq_num, 81411249Sradhika.jagtap@ARM.com Tick exec_tick) 81511249Sradhika.jagtap@ARM.com{ 81611249Sradhika.jagtap@ARM.com ReadyNode ready_node; 81711249Sradhika.jagtap@ARM.com ready_node.seqNum = seq_num; 81811249Sradhika.jagtap@ARM.com ready_node.execTick = exec_tick; 81911249Sradhika.jagtap@ARM.com 82011249Sradhika.jagtap@ARM.com // Iterator to readyList 82111249Sradhika.jagtap@ARM.com auto itr = readyList.begin(); 82211249Sradhika.jagtap@ARM.com 82311249Sradhika.jagtap@ARM.com // If the readyList is empty, simply insert the new node at the beginning 82411249Sradhika.jagtap@ARM.com // and return 82511249Sradhika.jagtap@ARM.com if (itr == readyList.end()) { 82611249Sradhika.jagtap@ARM.com readyList.insert(itr, ready_node); 82711249Sradhika.jagtap@ARM.com maxReadyListSize = std::max<double>(readyList.size(), 82811249Sradhika.jagtap@ARM.com maxReadyListSize.value()); 82911249Sradhika.jagtap@ARM.com return; 83011249Sradhika.jagtap@ARM.com } 83111249Sradhika.jagtap@ARM.com 83211249Sradhika.jagtap@ARM.com // If the new node has its execution tick equal to the first node in the 83311249Sradhika.jagtap@ARM.com // list then go to the next node. If the first node in the list failed 83411249Sradhika.jagtap@ARM.com // to execute, its position as the first is thus maintained. 83511249Sradhika.jagtap@ARM.com if (retryPkt) 83611249Sradhika.jagtap@ARM.com if (retryPkt->req->getReqInstSeqNum() == itr->seqNum) 83711249Sradhika.jagtap@ARM.com itr++; 83811249Sradhika.jagtap@ARM.com 83911249Sradhika.jagtap@ARM.com // Increment the iterator and compare the node pointed to by it to the new 84011249Sradhika.jagtap@ARM.com // node till the position to insert the new node is found. 84111249Sradhika.jagtap@ARM.com bool found = false; 84211249Sradhika.jagtap@ARM.com while (!found && itr != readyList.end()) { 84311249Sradhika.jagtap@ARM.com // If the execution tick of the new node is less than the node then 84411249Sradhika.jagtap@ARM.com // this is the position to insert 84511249Sradhika.jagtap@ARM.com if (exec_tick < itr->execTick) 84611249Sradhika.jagtap@ARM.com found = true; 84711249Sradhika.jagtap@ARM.com // If the execution tick of the new node is equal to the node then 84811249Sradhika.jagtap@ARM.com // sort in ascending order of sequence numbers 84911249Sradhika.jagtap@ARM.com else if (exec_tick == itr->execTick) { 85011249Sradhika.jagtap@ARM.com // If the sequence number of the new node is less than the node 85111249Sradhika.jagtap@ARM.com // then this is the position to insert 85211249Sradhika.jagtap@ARM.com if (seq_num < itr->seqNum) 85311249Sradhika.jagtap@ARM.com found = true; 85411249Sradhika.jagtap@ARM.com // Else go to next node 85511249Sradhika.jagtap@ARM.com else 85611249Sradhika.jagtap@ARM.com itr++; 85711249Sradhika.jagtap@ARM.com } 85811249Sradhika.jagtap@ARM.com // If the execution tick of the new node is greater than the node then 85911249Sradhika.jagtap@ARM.com // go to the next node 86011249Sradhika.jagtap@ARM.com else 86111249Sradhika.jagtap@ARM.com itr++; 86211249Sradhika.jagtap@ARM.com } 86311249Sradhika.jagtap@ARM.com readyList.insert(itr, ready_node); 86411249Sradhika.jagtap@ARM.com // Update the stat for max size reached of the readyList 86511249Sradhika.jagtap@ARM.com maxReadyListSize = std::max<double>(readyList.size(), 86611249Sradhika.jagtap@ARM.com maxReadyListSize.value()); 86711249Sradhika.jagtap@ARM.com} 86811249Sradhika.jagtap@ARM.com 86911249Sradhika.jagtap@ARM.comvoid 87011249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::printReadyList() { 87111249Sradhika.jagtap@ARM.com 87211249Sradhika.jagtap@ARM.com auto itr = readyList.begin(); 87311249Sradhika.jagtap@ARM.com if (itr == readyList.end()) { 87411249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "readyList is empty.\n"); 87511249Sradhika.jagtap@ARM.com return; 87611249Sradhika.jagtap@ARM.com } 87711249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Printing readyList:\n"); 87811249Sradhika.jagtap@ARM.com while (itr != readyList.end()) { 87911249Sradhika.jagtap@ARM.com auto graph_itr = depGraph.find(itr->seqNum); 88011249Sradhika.jagtap@ARM.com GraphNode* node_ptr M5_VAR_USED = graph_itr->second; 88111249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t%lld(%s), %lld\n", itr->seqNum, 88211252Sradhika.jagtap@ARM.com node_ptr->typeToStr(), itr->execTick); 88311249Sradhika.jagtap@ARM.com itr++; 88411249Sradhika.jagtap@ARM.com } 88511249Sradhika.jagtap@ARM.com} 88611249Sradhika.jagtap@ARM.com 88711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::HardwareResource( 88811249Sradhika.jagtap@ARM.com uint16_t max_rob, uint16_t max_stores, uint16_t max_loads) 88911249Sradhika.jagtap@ARM.com : sizeROB(max_rob), 89011249Sradhika.jagtap@ARM.com sizeStoreBuffer(max_stores), 89111249Sradhika.jagtap@ARM.com sizeLoadBuffer(max_loads), 89211249Sradhika.jagtap@ARM.com oldestInFlightRobNum(UINT64_MAX), 89311249Sradhika.jagtap@ARM.com numInFlightLoads(0), 89411249Sradhika.jagtap@ARM.com numInFlightStores(0) 89511249Sradhika.jagtap@ARM.com{} 89611249Sradhika.jagtap@ARM.com 89711249Sradhika.jagtap@ARM.comvoid 89811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::occupy(const GraphNode* new_node) 89911249Sradhika.jagtap@ARM.com{ 90011249Sradhika.jagtap@ARM.com // Occupy ROB entry for the issued node 90111249Sradhika.jagtap@ARM.com // Merely maintain the oldest node, i.e. numerically least robNum by saving 90211249Sradhika.jagtap@ARM.com // it in the variable oldestInFLightRobNum. 90311249Sradhika.jagtap@ARM.com inFlightNodes[new_node->seqNum] = new_node->robNum; 90411249Sradhika.jagtap@ARM.com oldestInFlightRobNum = inFlightNodes.begin()->second; 90511249Sradhika.jagtap@ARM.com 90611249Sradhika.jagtap@ARM.com // Occupy Load/Store Buffer entry for the issued node if applicable 90711252Sradhika.jagtap@ARM.com if (new_node->isLoad()) { 90811249Sradhika.jagtap@ARM.com ++numInFlightLoads; 90911252Sradhika.jagtap@ARM.com } else if (new_node->isStore()) { 91011249Sradhika.jagtap@ARM.com ++numInFlightStores; 91111249Sradhika.jagtap@ARM.com } // else if it is a non load/store node, no buffer entry is occupied 91211249Sradhika.jagtap@ARM.com 91311249Sradhika.jagtap@ARM.com printOccupancy(); 91411249Sradhika.jagtap@ARM.com} 91511249Sradhika.jagtap@ARM.com 91611249Sradhika.jagtap@ARM.comvoid 91711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::release(const GraphNode* done_node) 91811249Sradhika.jagtap@ARM.com{ 91911249Sradhika.jagtap@ARM.com assert(!inFlightNodes.empty()); 92011249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tClearing done seq. num %d from inFlightNodes..\n", 92111249Sradhika.jagtap@ARM.com done_node->seqNum); 92211249Sradhika.jagtap@ARM.com 92311249Sradhika.jagtap@ARM.com assert(inFlightNodes.find(done_node->seqNum) != inFlightNodes.end()); 92411249Sradhika.jagtap@ARM.com inFlightNodes.erase(done_node->seqNum); 92511249Sradhika.jagtap@ARM.com 92611249Sradhika.jagtap@ARM.com if (inFlightNodes.empty()) { 92711249Sradhika.jagtap@ARM.com // If we delete the only in-flight node and then the 92811249Sradhika.jagtap@ARM.com // oldestInFlightRobNum is set to it's initialized (max) value. 92911249Sradhika.jagtap@ARM.com oldestInFlightRobNum = UINT64_MAX; 93011249Sradhika.jagtap@ARM.com } else { 93111249Sradhika.jagtap@ARM.com // Set the oldest in-flight node rob number equal to the first node in 93211249Sradhika.jagtap@ARM.com // the inFlightNodes since that will have the numerically least value. 93311249Sradhika.jagtap@ARM.com oldestInFlightRobNum = inFlightNodes.begin()->second; 93411249Sradhika.jagtap@ARM.com } 93511249Sradhika.jagtap@ARM.com 93611249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tCleared. inFlightNodes.size() = %d, " 93711249Sradhika.jagtap@ARM.com "oldestInFlightRobNum = %d\n", inFlightNodes.size(), 93811249Sradhika.jagtap@ARM.com oldestInFlightRobNum); 93911249Sradhika.jagtap@ARM.com 94011249Sradhika.jagtap@ARM.com // A store is considered complete when a request is sent, thus ROB entry is 94111249Sradhika.jagtap@ARM.com // freed. But it occupies an entry in the Store Buffer until its response 94211249Sradhika.jagtap@ARM.com // is received. A load is considered complete when a response is received, 94311249Sradhika.jagtap@ARM.com // thus both ROB and Load Buffer entries can be released. 94411252Sradhika.jagtap@ARM.com if (done_node->isLoad()) { 94511249Sradhika.jagtap@ARM.com assert(numInFlightLoads != 0); 94611249Sradhika.jagtap@ARM.com --numInFlightLoads; 94711249Sradhika.jagtap@ARM.com } 94811249Sradhika.jagtap@ARM.com // For normal writes, we send the requests out and clear a store buffer 94911249Sradhika.jagtap@ARM.com // entry on response. For writes which are strictly ordered, for e.g. 95011249Sradhika.jagtap@ARM.com // writes to device registers, we do that within release() which is called 95111249Sradhika.jagtap@ARM.com // when node is executed and taken off from readyList. 95211252Sradhika.jagtap@ARM.com if (done_node->isStore() && done_node->isStrictlyOrdered()) { 95311249Sradhika.jagtap@ARM.com releaseStoreBuffer(); 95411249Sradhika.jagtap@ARM.com } 95511249Sradhika.jagtap@ARM.com} 95611249Sradhika.jagtap@ARM.com 95711249Sradhika.jagtap@ARM.comvoid 95811249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::releaseStoreBuffer() 95911249Sradhika.jagtap@ARM.com{ 96011249Sradhika.jagtap@ARM.com assert(numInFlightStores != 0); 96111249Sradhika.jagtap@ARM.com --numInFlightStores; 96211249Sradhika.jagtap@ARM.com} 96311249Sradhika.jagtap@ARM.com 96411249Sradhika.jagtap@ARM.combool 96511249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::isAvailable( 96611249Sradhika.jagtap@ARM.com const GraphNode* new_node) const 96711249Sradhika.jagtap@ARM.com{ 96811249Sradhika.jagtap@ARM.com uint16_t num_in_flight_nodes; 96911249Sradhika.jagtap@ARM.com if (inFlightNodes.empty()) { 97011249Sradhika.jagtap@ARM.com num_in_flight_nodes = 0; 97111249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:" 97211249Sradhika.jagtap@ARM.com " #in-flight nodes = 0", new_node->seqNum); 97311249Sradhika.jagtap@ARM.com } else if (new_node->robNum > oldestInFlightRobNum) { 97411249Sradhika.jagtap@ARM.com // This is the intuitive case where new dep-free node is younger 97511249Sradhika.jagtap@ARM.com // instruction than the oldest instruction in-flight. Thus we make sure 97611249Sradhika.jagtap@ARM.com // in_flight_nodes does not overflow. 97711249Sradhika.jagtap@ARM.com num_in_flight_nodes = new_node->robNum - oldestInFlightRobNum; 97811249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:" 97911249Sradhika.jagtap@ARM.com " #in-flight nodes = %d - %d = %d", new_node->seqNum, 98011249Sradhika.jagtap@ARM.com new_node->robNum, oldestInFlightRobNum, num_in_flight_nodes); 98111249Sradhika.jagtap@ARM.com } else { 98211249Sradhika.jagtap@ARM.com // This is the case where an instruction older than the oldest in- 98311249Sradhika.jagtap@ARM.com // flight instruction becomes dep-free. Thus we must have already 98411249Sradhika.jagtap@ARM.com // accounted for the entry in ROB for this new dep-free node. 98511249Sradhika.jagtap@ARM.com // Immediately after this check returns true, oldestInFlightRobNum will 98611249Sradhika.jagtap@ARM.com // be updated in occupy(). We simply let this node issue now. 98711249Sradhika.jagtap@ARM.com num_in_flight_nodes = 0; 98811249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\t\tChecking resources to issue seq. num %lli:" 98911249Sradhika.jagtap@ARM.com " new oldestInFlightRobNum = %d, #in-flight nodes ignored", 99011249Sradhika.jagtap@ARM.com new_node->seqNum, new_node->robNum); 99111249Sradhika.jagtap@ARM.com } 99211249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ", LQ = %d/%d, SQ = %d/%d.\n", 99311249Sradhika.jagtap@ARM.com numInFlightLoads, sizeLoadBuffer, 99411249Sradhika.jagtap@ARM.com numInFlightStores, sizeStoreBuffer); 99511249Sradhika.jagtap@ARM.com // Check if resources are available to issue the specific node 99611249Sradhika.jagtap@ARM.com if (num_in_flight_nodes >= sizeROB) { 99711249Sradhika.jagtap@ARM.com return false; 99811249Sradhika.jagtap@ARM.com } 99911252Sradhika.jagtap@ARM.com if (new_node->isLoad() && numInFlightLoads >= sizeLoadBuffer) { 100011249Sradhika.jagtap@ARM.com return false; 100111249Sradhika.jagtap@ARM.com } 100211252Sradhika.jagtap@ARM.com if (new_node->isStore() && numInFlightStores >= sizeStoreBuffer) { 100311249Sradhika.jagtap@ARM.com return false; 100411249Sradhika.jagtap@ARM.com } 100511249Sradhika.jagtap@ARM.com return true; 100611249Sradhika.jagtap@ARM.com} 100711249Sradhika.jagtap@ARM.com 100811249Sradhika.jagtap@ARM.combool 100911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::awaitingResponse() const { 101011249Sradhika.jagtap@ARM.com // Return true if there is at least one read or write request in flight 101111249Sradhika.jagtap@ARM.com return (numInFlightStores != 0 || numInFlightLoads != 0); 101211249Sradhika.jagtap@ARM.com} 101311249Sradhika.jagtap@ARM.com 101411249Sradhika.jagtap@ARM.comvoid 101511249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::HardwareResource::printOccupancy() { 101611249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "oldestInFlightRobNum = %d, " 101711249Sradhika.jagtap@ARM.com "LQ = %d/%d, SQ = %d/%d.\n", 101811249Sradhika.jagtap@ARM.com oldestInFlightRobNum, 101911249Sradhika.jagtap@ARM.com numInFlightLoads, sizeLoadBuffer, 102011249Sradhika.jagtap@ARM.com numInFlightStores, sizeStoreBuffer); 102111249Sradhika.jagtap@ARM.com} 102211249Sradhika.jagtap@ARM.com 102311249Sradhika.jagtap@ARM.comvoid 102411249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::regStats() 102511249Sradhika.jagtap@ARM.com{ 102611249Sradhika.jagtap@ARM.com using namespace Stats; 102711249Sradhika.jagtap@ARM.com 102811249Sradhika.jagtap@ARM.com numSendAttempted 102911249Sradhika.jagtap@ARM.com .name(name() + ".numSendAttempted") 103011249Sradhika.jagtap@ARM.com .desc("Number of first attempts to send a request") 103111249Sradhika.jagtap@ARM.com ; 103211249Sradhika.jagtap@ARM.com 103311249Sradhika.jagtap@ARM.com numSendSucceeded 103411249Sradhika.jagtap@ARM.com .name(name() + ".numSendSucceeded") 103511249Sradhika.jagtap@ARM.com .desc("Number of successful first attempts") 103611249Sradhika.jagtap@ARM.com ; 103711249Sradhika.jagtap@ARM.com 103811249Sradhika.jagtap@ARM.com numSendFailed 103911249Sradhika.jagtap@ARM.com .name(name() + ".numSendFailed") 104011249Sradhika.jagtap@ARM.com .desc("Number of failed first attempts") 104111249Sradhika.jagtap@ARM.com ; 104211249Sradhika.jagtap@ARM.com 104311249Sradhika.jagtap@ARM.com numRetrySucceeded 104411249Sradhika.jagtap@ARM.com .name(name() + ".numRetrySucceeded") 104511249Sradhika.jagtap@ARM.com .desc("Number of successful retries") 104611249Sradhika.jagtap@ARM.com ; 104711249Sradhika.jagtap@ARM.com 104811249Sradhika.jagtap@ARM.com instLastTick 104911249Sradhika.jagtap@ARM.com .name(name() + ".instLastTick") 105011249Sradhika.jagtap@ARM.com .desc("Last tick simulated from the fixed inst trace") 105111249Sradhika.jagtap@ARM.com ; 105211249Sradhika.jagtap@ARM.com} 105311249Sradhika.jagtap@ARM.com 105411249Sradhika.jagtap@ARM.comTick 105511249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::init() 105611249Sradhika.jagtap@ARM.com{ 105711249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Initializing instruction fetch request generator" 105811249Sradhika.jagtap@ARM.com " IcacheGen: fixed issue with retry.\n"); 105911249Sradhika.jagtap@ARM.com 106011249Sradhika.jagtap@ARM.com if (nextExecute()) { 106111249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "\tFirst tick = %d.\n", currElement.tick); 106211249Sradhika.jagtap@ARM.com return currElement.tick; 106311249Sradhika.jagtap@ARM.com } else { 106411249Sradhika.jagtap@ARM.com panic("Read of first message in the trace failed.\n"); 106511249Sradhika.jagtap@ARM.com return MaxTick; 106611249Sradhika.jagtap@ARM.com } 106711249Sradhika.jagtap@ARM.com} 106811249Sradhika.jagtap@ARM.com 106911249Sradhika.jagtap@ARM.combool 107011249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::tryNext() 107111249Sradhika.jagtap@ARM.com{ 107211249Sradhika.jagtap@ARM.com // If there is a retry packet, try to send it 107311249Sradhika.jagtap@ARM.com if (retryPkt) { 107411249Sradhika.jagtap@ARM.com 107511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Trying to send retry packet.\n"); 107611249Sradhika.jagtap@ARM.com 107711249Sradhika.jagtap@ARM.com if (!port.sendTimingReq(retryPkt)) { 107811249Sradhika.jagtap@ARM.com // Still blocked! This should never occur. 107911249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Retry packet sending failed.\n"); 108011249Sradhika.jagtap@ARM.com return false; 108111249Sradhika.jagtap@ARM.com } 108211249Sradhika.jagtap@ARM.com ++numRetrySucceeded; 108311249Sradhika.jagtap@ARM.com } else { 108411249Sradhika.jagtap@ARM.com 108511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Trying to send packet for currElement.\n"); 108611249Sradhika.jagtap@ARM.com 108711249Sradhika.jagtap@ARM.com // try sending current element 108811249Sradhika.jagtap@ARM.com assert(currElement.isValid()); 108911249Sradhika.jagtap@ARM.com 109011249Sradhika.jagtap@ARM.com ++numSendAttempted; 109111249Sradhika.jagtap@ARM.com 109211249Sradhika.jagtap@ARM.com if (!send(currElement.addr, currElement.blocksize, 109311249Sradhika.jagtap@ARM.com currElement.cmd, currElement.flags, currElement.pc)) { 109411249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "currElement sending failed.\n"); 109511249Sradhika.jagtap@ARM.com ++numSendFailed; 109611249Sradhika.jagtap@ARM.com // return false to indicate not to schedule next event 109711249Sradhika.jagtap@ARM.com return false; 109811249Sradhika.jagtap@ARM.com } else { 109911249Sradhika.jagtap@ARM.com ++numSendSucceeded; 110011249Sradhika.jagtap@ARM.com } 110111249Sradhika.jagtap@ARM.com } 110211249Sradhika.jagtap@ARM.com // If packet was sent successfully, either retryPkt or currElement, return 110311249Sradhika.jagtap@ARM.com // true to indicate to schedule event at current Tick plus delta. If packet 110411249Sradhika.jagtap@ARM.com // was sent successfully and there is no next packet to send, return false. 110511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Packet sent successfully, trying to read next " 110611249Sradhika.jagtap@ARM.com "element.\n"); 110711249Sradhika.jagtap@ARM.com retryPkt = nullptr; 110811249Sradhika.jagtap@ARM.com // Read next element into currElement, currElement gets cleared so save the 110911249Sradhika.jagtap@ARM.com // tick to calculate delta 111011249Sradhika.jagtap@ARM.com Tick last_tick = currElement.tick; 111111249Sradhika.jagtap@ARM.com if (nextExecute()) { 111211249Sradhika.jagtap@ARM.com assert(currElement.tick >= last_tick); 111311249Sradhika.jagtap@ARM.com delta = currElement.tick - last_tick; 111411249Sradhika.jagtap@ARM.com } 111511249Sradhika.jagtap@ARM.com return !traceComplete; 111611249Sradhika.jagtap@ARM.com} 111711249Sradhika.jagtap@ARM.com 111811249Sradhika.jagtap@ARM.comvoid 111911249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::exit() 112011249Sradhika.jagtap@ARM.com{ 112111249Sradhika.jagtap@ARM.com trace.reset(); 112211249Sradhika.jagtap@ARM.com} 112311249Sradhika.jagtap@ARM.com 112411249Sradhika.jagtap@ARM.combool 112511249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::nextExecute() 112611249Sradhika.jagtap@ARM.com{ 112711249Sradhika.jagtap@ARM.com if (traceComplete) 112811249Sradhika.jagtap@ARM.com // We are at the end of the file, thus we have no more messages. 112911249Sradhika.jagtap@ARM.com // Return false. 113011249Sradhika.jagtap@ARM.com return false; 113111249Sradhika.jagtap@ARM.com 113211249Sradhika.jagtap@ARM.com 113311249Sradhika.jagtap@ARM.com //Reset the currElement to the default values 113411249Sradhika.jagtap@ARM.com currElement.clear(); 113511249Sradhika.jagtap@ARM.com 113611249Sradhika.jagtap@ARM.com // Read the next line to get the next message. If that fails then end of 113711249Sradhika.jagtap@ARM.com // trace has been reached and traceComplete needs to be set in addition 113811249Sradhika.jagtap@ARM.com // to returning false. If successful then next message is in currElement. 113911249Sradhika.jagtap@ARM.com if (!trace.read(&currElement)) { 114011249Sradhika.jagtap@ARM.com traceComplete = true; 114111249Sradhika.jagtap@ARM.com instLastTick = curTick(); 114211249Sradhika.jagtap@ARM.com return false; 114311249Sradhika.jagtap@ARM.com } 114411249Sradhika.jagtap@ARM.com 114511249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "inst fetch: %c addr %d pc %#x size %d tick %d\n", 114611249Sradhika.jagtap@ARM.com currElement.cmd.isRead() ? 'r' : 'w', 114711249Sradhika.jagtap@ARM.com currElement.addr, 114811249Sradhika.jagtap@ARM.com currElement.pc, 114911249Sradhika.jagtap@ARM.com currElement.blocksize, 115011249Sradhika.jagtap@ARM.com currElement.tick); 115111249Sradhika.jagtap@ARM.com 115211249Sradhika.jagtap@ARM.com return true; 115311249Sradhika.jagtap@ARM.com} 115411249Sradhika.jagtap@ARM.com 115511249Sradhika.jagtap@ARM.combool 115611249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::send(Addr addr, unsigned size, const MemCmd& cmd, 115711249Sradhika.jagtap@ARM.com Request::FlagsType flags, Addr pc) 115811249Sradhika.jagtap@ARM.com{ 115911249Sradhika.jagtap@ARM.com 116011249Sradhika.jagtap@ARM.com // Create new request 116111249Sradhika.jagtap@ARM.com Request* req = new Request(addr, size, flags, masterID); 116211249Sradhika.jagtap@ARM.com req->setPC(pc); 116311249Sradhika.jagtap@ARM.com 116411249Sradhika.jagtap@ARM.com // If this is not done it triggers assert in L1 cache for invalid contextId 116511435Smitch.hayenga@arm.com req->setContext(ContextID(0)); 116611249Sradhika.jagtap@ARM.com 116711249Sradhika.jagtap@ARM.com // Embed it in a packet 116811249Sradhika.jagtap@ARM.com PacketPtr pkt = new Packet(req, cmd); 116911249Sradhika.jagtap@ARM.com 117011249Sradhika.jagtap@ARM.com uint8_t* pkt_data = new uint8_t[req->getSize()]; 117111249Sradhika.jagtap@ARM.com pkt->dataDynamic(pkt_data); 117211249Sradhika.jagtap@ARM.com 117311249Sradhika.jagtap@ARM.com if (cmd.isWrite()) { 117411249Sradhika.jagtap@ARM.com memset(pkt_data, 0xA, req->getSize()); 117511249Sradhika.jagtap@ARM.com } 117611249Sradhika.jagtap@ARM.com 117711249Sradhika.jagtap@ARM.com // Call MasterPort method to send a timing request for this packet 117811249Sradhika.jagtap@ARM.com bool success = port.sendTimingReq(pkt); 117911249Sradhika.jagtap@ARM.com if (!success) { 118011249Sradhika.jagtap@ARM.com // If it fails, save the packet to retry when a retry is signalled by 118111249Sradhika.jagtap@ARM.com // the cache 118211249Sradhika.jagtap@ARM.com retryPkt = pkt; 118311249Sradhika.jagtap@ARM.com } 118411249Sradhika.jagtap@ARM.com return success; 118511249Sradhika.jagtap@ARM.com} 118611249Sradhika.jagtap@ARM.com 118711249Sradhika.jagtap@ARM.comvoid 118811249Sradhika.jagtap@ARM.comTraceCPU::icacheRetryRecvd() 118911249Sradhika.jagtap@ARM.com{ 119011249Sradhika.jagtap@ARM.com // Schedule an event to go through the control flow in the same tick as 119111249Sradhika.jagtap@ARM.com // retry is received 119211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUInst, "Icache retry received. Scheduling next IcacheGen" 119311249Sradhika.jagtap@ARM.com " event @%lli.\n", curTick()); 119411249Sradhika.jagtap@ARM.com schedule(icacheNextEvent, curTick()); 119511249Sradhika.jagtap@ARM.com} 119611249Sradhika.jagtap@ARM.com 119711249Sradhika.jagtap@ARM.comvoid 119811249Sradhika.jagtap@ARM.comTraceCPU::dcacheRetryRecvd() 119911249Sradhika.jagtap@ARM.com{ 120011249Sradhika.jagtap@ARM.com // Schedule an event to go through the execute flow in the same tick as 120111249Sradhika.jagtap@ARM.com // retry is received 120211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Dcache retry received. Scheduling next DcacheGen" 120311249Sradhika.jagtap@ARM.com " event @%lli.\n", curTick()); 120411249Sradhika.jagtap@ARM.com schedule(dcacheNextEvent, curTick()); 120511249Sradhika.jagtap@ARM.com} 120611249Sradhika.jagtap@ARM.com 120711249Sradhika.jagtap@ARM.comvoid 120811249Sradhika.jagtap@ARM.comTraceCPU::schedDcacheNextEvent(Tick when) 120911249Sradhika.jagtap@ARM.com{ 121011249Sradhika.jagtap@ARM.com if (!dcacheNextEvent.scheduled()) { 121111249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Scheduling next DcacheGen event at %lli.\n", 121211249Sradhika.jagtap@ARM.com when); 121311249Sradhika.jagtap@ARM.com schedule(dcacheNextEvent, when); 121411249Sradhika.jagtap@ARM.com ++numSchedDcacheEvent; 121511249Sradhika.jagtap@ARM.com } else if (when < dcacheNextEvent.when()) { 121611249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Re-scheduling next dcache event from %lli" 121711249Sradhika.jagtap@ARM.com " to %lli.\n", dcacheNextEvent.when(), when); 121811249Sradhika.jagtap@ARM.com reschedule(dcacheNextEvent, when); 121911249Sradhika.jagtap@ARM.com } 122011249Sradhika.jagtap@ARM.com 122111249Sradhika.jagtap@ARM.com} 122211249Sradhika.jagtap@ARM.com 122311249Sradhika.jagtap@ARM.combool 122411249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvTimingResp(PacketPtr pkt) 122511249Sradhika.jagtap@ARM.com{ 122611249Sradhika.jagtap@ARM.com // All responses on the instruction fetch side are ignored. Simply delete 122711249Sradhika.jagtap@ARM.com // the request and packet to free allocated memory 122811249Sradhika.jagtap@ARM.com delete pkt->req; 122911249Sradhika.jagtap@ARM.com delete pkt; 123011249Sradhika.jagtap@ARM.com 123111249Sradhika.jagtap@ARM.com return true; 123211249Sradhika.jagtap@ARM.com} 123311249Sradhika.jagtap@ARM.com 123411249Sradhika.jagtap@ARM.comvoid 123511249Sradhika.jagtap@ARM.comTraceCPU::IcachePort::recvReqRetry() 123611249Sradhika.jagtap@ARM.com{ 123711249Sradhika.jagtap@ARM.com owner->icacheRetryRecvd(); 123811249Sradhika.jagtap@ARM.com} 123911249Sradhika.jagtap@ARM.com 124011249Sradhika.jagtap@ARM.comvoid 124111249Sradhika.jagtap@ARM.comTraceCPU::dcacheRecvTimingResp(PacketPtr pkt) 124211249Sradhika.jagtap@ARM.com{ 124311249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Received timing response from Dcache.\n"); 124411249Sradhika.jagtap@ARM.com dcacheGen.completeMemAccess(pkt); 124511249Sradhika.jagtap@ARM.com} 124611249Sradhika.jagtap@ARM.com 124711249Sradhika.jagtap@ARM.combool 124811249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvTimingResp(PacketPtr pkt) 124911249Sradhika.jagtap@ARM.com{ 125011249Sradhika.jagtap@ARM.com // Handle the responses for data memory requests which is done inside the 125111249Sradhika.jagtap@ARM.com // elastic data generator 125211249Sradhika.jagtap@ARM.com owner->dcacheRecvTimingResp(pkt); 125311249Sradhika.jagtap@ARM.com // After processing the response delete the request and packet to free 125411249Sradhika.jagtap@ARM.com // memory 125511249Sradhika.jagtap@ARM.com delete pkt->req; 125611249Sradhika.jagtap@ARM.com delete pkt; 125711249Sradhika.jagtap@ARM.com 125811249Sradhika.jagtap@ARM.com return true; 125911249Sradhika.jagtap@ARM.com} 126011249Sradhika.jagtap@ARM.com 126111249Sradhika.jagtap@ARM.comvoid 126211249Sradhika.jagtap@ARM.comTraceCPU::DcachePort::recvReqRetry() 126311249Sradhika.jagtap@ARM.com{ 126411249Sradhika.jagtap@ARM.com owner->dcacheRetryRecvd(); 126511249Sradhika.jagtap@ARM.com} 126611249Sradhika.jagtap@ARM.com 126711631Sradhika.jagtap@arm.comTraceCPU::ElasticDataGen::InputStream::InputStream( 126811631Sradhika.jagtap@arm.com const std::string& filename, 126911631Sradhika.jagtap@arm.com const double time_multiplier) 127011249Sradhika.jagtap@ARM.com : trace(filename), 127111631Sradhika.jagtap@arm.com timeMultiplier(time_multiplier), 127211249Sradhika.jagtap@ARM.com microOpCount(0) 127311249Sradhika.jagtap@ARM.com{ 127411249Sradhika.jagtap@ARM.com // Create a protobuf message for the header and read it from the stream 127511249Sradhika.jagtap@ARM.com ProtoMessage::InstDepRecordHeader header_msg; 127611249Sradhika.jagtap@ARM.com if (!trace.read(header_msg)) { 127711249Sradhika.jagtap@ARM.com panic("Failed to read packet header from %s\n", filename); 127811249Sradhika.jagtap@ARM.com 127911249Sradhika.jagtap@ARM.com if (header_msg.tick_freq() != SimClock::Frequency) { 128011249Sradhika.jagtap@ARM.com panic("Trace %s was recorded with a different tick frequency %d\n", 128111249Sradhika.jagtap@ARM.com header_msg.tick_freq()); 128211249Sradhika.jagtap@ARM.com } 128311249Sradhika.jagtap@ARM.com } else { 128411249Sradhika.jagtap@ARM.com // Assign window size equal to the field in the trace that was recorded 128511249Sradhika.jagtap@ARM.com // when the data dependency trace was captured in the o3cpu model 128611249Sradhika.jagtap@ARM.com windowSize = header_msg.window_size(); 128711249Sradhika.jagtap@ARM.com } 128811249Sradhika.jagtap@ARM.com} 128911249Sradhika.jagtap@ARM.com 129011249Sradhika.jagtap@ARM.comvoid 129111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::reset() 129211249Sradhika.jagtap@ARM.com{ 129311249Sradhika.jagtap@ARM.com trace.reset(); 129411249Sradhika.jagtap@ARM.com} 129511249Sradhika.jagtap@ARM.com 129611249Sradhika.jagtap@ARM.combool 129711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::InputStream::read(GraphNode* element) 129811249Sradhika.jagtap@ARM.com{ 129911249Sradhika.jagtap@ARM.com ProtoMessage::InstDepRecord pkt_msg; 130011249Sradhika.jagtap@ARM.com if (trace.read(pkt_msg)) { 130111249Sradhika.jagtap@ARM.com // Required fields 130211249Sradhika.jagtap@ARM.com element->seqNum = pkt_msg.seq_num(); 130311252Sradhika.jagtap@ARM.com element->type = pkt_msg.type(); 130411631Sradhika.jagtap@arm.com // Scale the compute delay to effectively scale the Trace CPU frequency 130511631Sradhika.jagtap@arm.com element->compDelay = pkt_msg.comp_delay() * timeMultiplier; 130611249Sradhika.jagtap@ARM.com 130711249Sradhika.jagtap@ARM.com // Repeated field robDepList 130811249Sradhika.jagtap@ARM.com element->clearRobDep(); 130911249Sradhika.jagtap@ARM.com assert((pkt_msg.rob_dep()).size() <= element->maxRobDep); 131011249Sradhika.jagtap@ARM.com for (int i = 0; i < (pkt_msg.rob_dep()).size(); i++) { 131111249Sradhika.jagtap@ARM.com element->robDep[element->numRobDep] = pkt_msg.rob_dep(i); 131211249Sradhika.jagtap@ARM.com element->numRobDep += 1; 131311249Sradhika.jagtap@ARM.com } 131411249Sradhika.jagtap@ARM.com 131511249Sradhika.jagtap@ARM.com // Repeated field 131611249Sradhika.jagtap@ARM.com element->clearRegDep(); 131711249Sradhika.jagtap@ARM.com assert((pkt_msg.reg_dep()).size() <= TheISA::MaxInstSrcRegs); 131811249Sradhika.jagtap@ARM.com for (int i = 0; i < (pkt_msg.reg_dep()).size(); i++) { 131911249Sradhika.jagtap@ARM.com // There is a possibility that an instruction has both, a register 132011249Sradhika.jagtap@ARM.com // and order dependency on an instruction. In such a case, the 132111249Sradhika.jagtap@ARM.com // register dependency is omitted 132211249Sradhika.jagtap@ARM.com bool duplicate = false; 132311249Sradhika.jagtap@ARM.com for (int j = 0; j < element->numRobDep; j++) { 132411249Sradhika.jagtap@ARM.com duplicate |= (pkt_msg.reg_dep(i) == element->robDep[j]); 132511249Sradhika.jagtap@ARM.com } 132611249Sradhika.jagtap@ARM.com if (!duplicate) { 132711249Sradhika.jagtap@ARM.com element->regDep[element->numRegDep] = pkt_msg.reg_dep(i); 132811249Sradhika.jagtap@ARM.com element->numRegDep += 1; 132911249Sradhika.jagtap@ARM.com } 133011249Sradhika.jagtap@ARM.com } 133111249Sradhika.jagtap@ARM.com 133211249Sradhika.jagtap@ARM.com // Optional fields 133311253Sradhika.jagtap@ARM.com if (pkt_msg.has_p_addr()) 133411253Sradhika.jagtap@ARM.com element->physAddr = pkt_msg.p_addr(); 133511249Sradhika.jagtap@ARM.com else 133611253Sradhika.jagtap@ARM.com element->physAddr = 0; 133711253Sradhika.jagtap@ARM.com 133811253Sradhika.jagtap@ARM.com if (pkt_msg.has_v_addr()) 133911253Sradhika.jagtap@ARM.com element->virtAddr = pkt_msg.v_addr(); 134011253Sradhika.jagtap@ARM.com else 134111253Sradhika.jagtap@ARM.com element->virtAddr = 0; 134211253Sradhika.jagtap@ARM.com 134311253Sradhika.jagtap@ARM.com if (pkt_msg.has_asid()) 134411253Sradhika.jagtap@ARM.com element->asid = pkt_msg.asid(); 134511253Sradhika.jagtap@ARM.com else 134611253Sradhika.jagtap@ARM.com element->asid = 0; 134711249Sradhika.jagtap@ARM.com 134811249Sradhika.jagtap@ARM.com if (pkt_msg.has_size()) 134911249Sradhika.jagtap@ARM.com element->size = pkt_msg.size(); 135011249Sradhika.jagtap@ARM.com else 135111249Sradhika.jagtap@ARM.com element->size = 0; 135211249Sradhika.jagtap@ARM.com 135311249Sradhika.jagtap@ARM.com if (pkt_msg.has_flags()) 135411249Sradhika.jagtap@ARM.com element->flags = pkt_msg.flags(); 135511249Sradhika.jagtap@ARM.com else 135611249Sradhika.jagtap@ARM.com element->flags = 0; 135711249Sradhika.jagtap@ARM.com 135811249Sradhika.jagtap@ARM.com if (pkt_msg.has_pc()) 135911249Sradhika.jagtap@ARM.com element->pc = pkt_msg.pc(); 136011249Sradhika.jagtap@ARM.com else 136111249Sradhika.jagtap@ARM.com element->pc = 0; 136211249Sradhika.jagtap@ARM.com 136311249Sradhika.jagtap@ARM.com // ROB occupancy number 136411249Sradhika.jagtap@ARM.com ++microOpCount; 136511249Sradhika.jagtap@ARM.com if (pkt_msg.has_weight()) { 136611249Sradhika.jagtap@ARM.com microOpCount += pkt_msg.weight(); 136711249Sradhika.jagtap@ARM.com } 136811249Sradhika.jagtap@ARM.com element->robNum = microOpCount; 136911249Sradhika.jagtap@ARM.com return true; 137011249Sradhika.jagtap@ARM.com } 137111249Sradhika.jagtap@ARM.com 137211249Sradhika.jagtap@ARM.com // We have reached the end of the file 137311249Sradhika.jagtap@ARM.com return false; 137411249Sradhika.jagtap@ARM.com} 137511249Sradhika.jagtap@ARM.com 137611249Sradhika.jagtap@ARM.combool 137711249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRegDep(NodeSeqNum reg_dep) 137811249Sradhika.jagtap@ARM.com{ 137911249Sradhika.jagtap@ARM.com for (auto& own_reg_dep : regDep) { 138011249Sradhika.jagtap@ARM.com if (own_reg_dep == reg_dep) { 138111249Sradhika.jagtap@ARM.com // If register dependency is found, make it zero and return true 138211249Sradhika.jagtap@ARM.com own_reg_dep = 0; 138311294Sandreas.hansson@arm.com assert(numRegDep > 0); 138411249Sradhika.jagtap@ARM.com --numRegDep; 138511249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tFor %lli: Marking register dependency %lli " 138611249Sradhika.jagtap@ARM.com "done.\n", seqNum, reg_dep); 138711249Sradhika.jagtap@ARM.com return true; 138811249Sradhika.jagtap@ARM.com } 138911249Sradhika.jagtap@ARM.com } 139011249Sradhika.jagtap@ARM.com 139111249Sradhika.jagtap@ARM.com // Return false if the dependency is not found 139211249Sradhika.jagtap@ARM.com return false; 139311249Sradhika.jagtap@ARM.com} 139411249Sradhika.jagtap@ARM.com 139511249Sradhika.jagtap@ARM.combool 139611249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeRobDep(NodeSeqNum rob_dep) 139711249Sradhika.jagtap@ARM.com{ 139811249Sradhika.jagtap@ARM.com for (auto& own_rob_dep : robDep) { 139911249Sradhika.jagtap@ARM.com if (own_rob_dep == rob_dep) { 140011249Sradhika.jagtap@ARM.com // If the rob dependency is found, make it zero and return true 140111249Sradhika.jagtap@ARM.com own_rob_dep = 0; 140211294Sandreas.hansson@arm.com assert(numRobDep > 0); 140311249Sradhika.jagtap@ARM.com --numRobDep; 140411249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\tFor %lli: Marking ROB dependency %lli " 140511249Sradhika.jagtap@ARM.com "done.\n", seqNum, rob_dep); 140611249Sradhika.jagtap@ARM.com return true; 140711249Sradhika.jagtap@ARM.com } 140811249Sradhika.jagtap@ARM.com } 140911249Sradhika.jagtap@ARM.com return false; 141011249Sradhika.jagtap@ARM.com} 141111249Sradhika.jagtap@ARM.com 141211249Sradhika.jagtap@ARM.comvoid 141311249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRegDep() { 141411249Sradhika.jagtap@ARM.com for (auto& own_reg_dep : regDep) { 141511249Sradhika.jagtap@ARM.com own_reg_dep = 0; 141611249Sradhika.jagtap@ARM.com } 141711249Sradhika.jagtap@ARM.com numRegDep = 0; 141811249Sradhika.jagtap@ARM.com} 141911249Sradhika.jagtap@ARM.com 142011249Sradhika.jagtap@ARM.comvoid 142111249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::clearRobDep() { 142211249Sradhika.jagtap@ARM.com for (auto& own_rob_dep : robDep) { 142311249Sradhika.jagtap@ARM.com own_rob_dep = 0; 142411249Sradhika.jagtap@ARM.com } 142511249Sradhika.jagtap@ARM.com numRobDep = 0; 142611249Sradhika.jagtap@ARM.com} 142711249Sradhika.jagtap@ARM.com 142811249Sradhika.jagtap@ARM.combool 142911249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::removeDepOnInst(NodeSeqNum done_seq_num) 143011249Sradhika.jagtap@ARM.com{ 143111249Sradhika.jagtap@ARM.com // If it is an rob dependency then remove it 143211249Sradhika.jagtap@ARM.com if (!removeRobDep(done_seq_num)) { 143311249Sradhika.jagtap@ARM.com // If it is not an rob dependency then it must be a register dependency 143411249Sradhika.jagtap@ARM.com // If the register dependency is not found, it violates an assumption 143511249Sradhika.jagtap@ARM.com // and must be caught by assert. 143611249Sradhika.jagtap@ARM.com bool regdep_found M5_VAR_USED = removeRegDep(done_seq_num); 143711249Sradhika.jagtap@ARM.com assert(regdep_found); 143811249Sradhika.jagtap@ARM.com } 143911249Sradhika.jagtap@ARM.com // Return true if the node is dependency free 144011249Sradhika.jagtap@ARM.com return (numRobDep == 0 && numRegDep == 0); 144111249Sradhika.jagtap@ARM.com} 144211249Sradhika.jagtap@ARM.com 144311249Sradhika.jagtap@ARM.comvoid 144411249Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::writeElementAsTrace() const 144511249Sradhika.jagtap@ARM.com{ 144611249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "%lli", seqNum); 144711252Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%s", typeToStr()); 144811252Sradhika.jagtap@ARM.com if (isLoad() || isStore()) { 144911253Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%i", physAddr); 145011249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%i", size); 145111249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%i", flags); 145211249Sradhika.jagtap@ARM.com } 145311249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%lli", compDelay); 145411249Sradhika.jagtap@ARM.com int i = 0; 145511249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "robDep:"); 145611249Sradhika.jagtap@ARM.com while (robDep[i] != 0) { 145711249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%lli", robDep[i]); 145811249Sradhika.jagtap@ARM.com i++; 145911249Sradhika.jagtap@ARM.com } 146011249Sradhika.jagtap@ARM.com i = 0; 146111249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "regDep:"); 146211249Sradhika.jagtap@ARM.com while (regDep[i] != 0) { 146311249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ",%lli", regDep[i]); 146411249Sradhika.jagtap@ARM.com i++; 146511249Sradhika.jagtap@ARM.com } 146611249Sradhika.jagtap@ARM.com auto child_itr = dependents.begin(); 146711249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "dependents:"); 146811249Sradhika.jagtap@ARM.com while (child_itr != dependents.end()) { 146911249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, ":%lli", (*child_itr)->seqNum); 147011249Sradhika.jagtap@ARM.com child_itr++; 147111249Sradhika.jagtap@ARM.com } 147211249Sradhika.jagtap@ARM.com 147311249Sradhika.jagtap@ARM.com DPRINTFR(TraceCPUData, "\n"); 147411249Sradhika.jagtap@ARM.com} 147511249Sradhika.jagtap@ARM.com 147611252Sradhika.jagtap@ARM.comstd::string 147711252Sradhika.jagtap@ARM.comTraceCPU::ElasticDataGen::GraphNode::typeToStr() const 147811252Sradhika.jagtap@ARM.com{ 147911252Sradhika.jagtap@ARM.com return Record::RecordType_Name(type); 148011252Sradhika.jagtap@ARM.com} 148111252Sradhika.jagtap@ARM.com 148211249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::InputStream(const std::string& filename) 148311249Sradhika.jagtap@ARM.com : trace(filename) 148411249Sradhika.jagtap@ARM.com{ 148511249Sradhika.jagtap@ARM.com // Create a protobuf message for the header and read it from the stream 148611249Sradhika.jagtap@ARM.com ProtoMessage::PacketHeader header_msg; 148711249Sradhika.jagtap@ARM.com if (!trace.read(header_msg)) { 148811249Sradhika.jagtap@ARM.com panic("Failed to read packet header from %s\n", filename); 148911249Sradhika.jagtap@ARM.com 149011249Sradhika.jagtap@ARM.com if (header_msg.tick_freq() != SimClock::Frequency) { 149111249Sradhika.jagtap@ARM.com panic("Trace %s was recorded with a different tick frequency %d\n", 149211249Sradhika.jagtap@ARM.com header_msg.tick_freq()); 149311249Sradhika.jagtap@ARM.com } 149411249Sradhika.jagtap@ARM.com } 149511249Sradhika.jagtap@ARM.com} 149611249Sradhika.jagtap@ARM.com 149711249Sradhika.jagtap@ARM.comvoid 149811249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::reset() 149911249Sradhika.jagtap@ARM.com{ 150011249Sradhika.jagtap@ARM.com trace.reset(); 150111249Sradhika.jagtap@ARM.com} 150211249Sradhika.jagtap@ARM.com 150311249Sradhika.jagtap@ARM.combool 150411249Sradhika.jagtap@ARM.comTraceCPU::FixedRetryGen::InputStream::read(TraceElement* element) 150511249Sradhika.jagtap@ARM.com{ 150611249Sradhika.jagtap@ARM.com ProtoMessage::Packet pkt_msg; 150711249Sradhika.jagtap@ARM.com if (trace.read(pkt_msg)) { 150811249Sradhika.jagtap@ARM.com element->cmd = pkt_msg.cmd(); 150911249Sradhika.jagtap@ARM.com element->addr = pkt_msg.addr(); 151011249Sradhika.jagtap@ARM.com element->blocksize = pkt_msg.size(); 151111249Sradhika.jagtap@ARM.com element->tick = pkt_msg.tick(); 151211249Sradhika.jagtap@ARM.com element->flags = pkt_msg.has_flags() ? pkt_msg.flags() : 0; 151311249Sradhika.jagtap@ARM.com element->pc = pkt_msg.has_pc() ? pkt_msg.pc() : 0; 151411249Sradhika.jagtap@ARM.com return true; 151511249Sradhika.jagtap@ARM.com } 151611249Sradhika.jagtap@ARM.com 151711249Sradhika.jagtap@ARM.com // We have reached the end of the file 151811249Sradhika.jagtap@ARM.com return false; 151911249Sradhika.jagtap@ARM.com} 1520