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#ifndef __CPU_TRACE_TRACE_CPU_HH__ 4311249Sradhika.jagtap@ARM.com#define __CPU_TRACE_TRACE_CPU_HH__ 4411249Sradhika.jagtap@ARM.com 4511249Sradhika.jagtap@ARM.com#include <array> 4611249Sradhika.jagtap@ARM.com#include <cstdint> 4711249Sradhika.jagtap@ARM.com#include <queue> 4811249Sradhika.jagtap@ARM.com#include <set> 4911249Sradhika.jagtap@ARM.com#include <unordered_map> 5011249Sradhika.jagtap@ARM.com 5111249Sradhika.jagtap@ARM.com#include "arch/registers.hh" 5211249Sradhika.jagtap@ARM.com#include "base/statistics.hh" 5311249Sradhika.jagtap@ARM.com#include "cpu/base.hh" 5411249Sradhika.jagtap@ARM.com#include "debug/TraceCPUData.hh" 5511249Sradhika.jagtap@ARM.com#include "debug/TraceCPUInst.hh" 5611249Sradhika.jagtap@ARM.com#include "params/TraceCPU.hh" 5711249Sradhika.jagtap@ARM.com#include "proto/inst_dep_record.pb.h" 5811249Sradhika.jagtap@ARM.com#include "proto/packet.pb.h" 5911249Sradhika.jagtap@ARM.com#include "proto/protoio.hh" 6011249Sradhika.jagtap@ARM.com#include "sim/sim_events.hh" 6111249Sradhika.jagtap@ARM.com 6211249Sradhika.jagtap@ARM.com/** 6311249Sradhika.jagtap@ARM.com * The trace cpu replays traces generated using the elastic trace probe 6411249Sradhika.jagtap@ARM.com * attached to the O3 CPU model. The elastic trace is an execution trace with 6511249Sradhika.jagtap@ARM.com * register data dependencies and ordering dependencies annotated to it. The 6611249Sradhika.jagtap@ARM.com * trace cpu also replays a fixed timestamp fetch trace that is also generated 6711249Sradhika.jagtap@ARM.com * by the elastic trace probe. This trace cpu model aims at achieving faster 6811249Sradhika.jagtap@ARM.com * simulation compared to the detailed cpu model and good correlation when the 6911249Sradhika.jagtap@ARM.com * same trace is used for playback on different memory sub-systems. 7011249Sradhika.jagtap@ARM.com * 7111249Sradhika.jagtap@ARM.com * The TraceCPU inherits from BaseCPU so some virtual methods need to be 7211249Sradhika.jagtap@ARM.com * defined. It has two port subclasses inherited from MasterPort for 7311249Sradhika.jagtap@ARM.com * instruction and data ports. It issues the memory requests deducing the 7411249Sradhika.jagtap@ARM.com * timing from the trace and without performing real execution of micro-ops. As 7511249Sradhika.jagtap@ARM.com * soon as the last dependency for an instruction is complete, its 7611249Sradhika.jagtap@ARM.com * computational delay, also provided in the input trace is added. The 7711249Sradhika.jagtap@ARM.com * dependency-free nodes are maintained in a list, called 'ReadyList', ordered 7811249Sradhika.jagtap@ARM.com * by ready time. Instructions which depend on load stall until the responses 7911249Sradhika.jagtap@ARM.com * for read requests are received thus achieving elastic replay. If the 8011249Sradhika.jagtap@ARM.com * dependency is not found when adding a new node, it is assumed complete. 8111249Sradhika.jagtap@ARM.com * Thus, if this node is found to be completely dependency-free its issue time 8211249Sradhika.jagtap@ARM.com * is calculated and it is added to the ready list immediately. This is 8311249Sradhika.jagtap@ARM.com * encapsulated in the subclass ElasticDataGen. 8411249Sradhika.jagtap@ARM.com * 8511249Sradhika.jagtap@ARM.com * If ready nodes are issued in an unconstrained way there can be more nodes 8611249Sradhika.jagtap@ARM.com * outstanding which results in divergence in timing compared to the O3CPU. 8711249Sradhika.jagtap@ARM.com * Therefore, the Trace CPU also models hardware resources. A sub-class to 8811249Sradhika.jagtap@ARM.com * model hardware resources contains the maximum sizes of load buffer, store 8911249Sradhika.jagtap@ARM.com * buffer and ROB. If resources are not available, the node is not issued. Such 9011249Sradhika.jagtap@ARM.com * nodes that are pending issue are held in the 'depFreeQueue' structure. 9111249Sradhika.jagtap@ARM.com * 9211249Sradhika.jagtap@ARM.com * Modeling the ROB size in the Trace CPU as a resource limitation is arguably 9311249Sradhika.jagtap@ARM.com * the most important parameter of all resources. The ROB occupancy is 9411249Sradhika.jagtap@ARM.com * estimated using the newly added field 'robNum'. We need to use ROB number as 9511249Sradhika.jagtap@ARM.com * sequence number is at times much higher due to squashing and trace replay is 9611249Sradhika.jagtap@ARM.com * focused on correct path modeling. 9711249Sradhika.jagtap@ARM.com * 9811249Sradhika.jagtap@ARM.com * A map called 'inFlightNodes' is added to track nodes that are not only in 9911249Sradhika.jagtap@ARM.com * the readyList but also load nodes that are executed (and thus removed from 10011249Sradhika.jagtap@ARM.com * readyList) but are not complete. ReadyList handles what and when to execute 10111249Sradhika.jagtap@ARM.com * next node while the inFlightNodes is used for resource modelling. The oldest 10211249Sradhika.jagtap@ARM.com * ROB number is updated when any node occupies the ROB or when an entry in the 10311249Sradhika.jagtap@ARM.com * ROB is released. The ROB occupancy is equal to the difference in the ROB 10411249Sradhika.jagtap@ARM.com * number of the newly dependency-free node and the oldest ROB number in 10511249Sradhika.jagtap@ARM.com * flight. 10611249Sradhika.jagtap@ARM.com * 10711249Sradhika.jagtap@ARM.com * If no node depends on a non load/store node then there is no reason to 10811249Sradhika.jagtap@ARM.com * track it in the dependency graph. We filter out such nodes but count them 10911249Sradhika.jagtap@ARM.com * and add a weight field to the subsequent node that we do include in the 11011249Sradhika.jagtap@ARM.com * trace. The weight field is used to model ROB occupancy during replay. 11111249Sradhika.jagtap@ARM.com * 11211249Sradhika.jagtap@ARM.com * The depFreeQueue is chosen to be FIFO so that child nodes which are in 11311249Sradhika.jagtap@ARM.com * program order get pushed into it in that order and thus issued in program 11411249Sradhika.jagtap@ARM.com * order, like in the O3CPU. This is also why the dependents is made a 11511249Sradhika.jagtap@ARM.com * sequential container, std::set to std::vector. We only check head of the 11611249Sradhika.jagtap@ARM.com * depFreeQueue as nodes are issued in order and blocking on head models that 11711249Sradhika.jagtap@ARM.com * better than looping the entire queue. An alternative choice would be to 11811249Sradhika.jagtap@ARM.com * inspect top N pending nodes where N is the issue-width. This is left for 11911249Sradhika.jagtap@ARM.com * future as the timing correlation looks good as it is. 12011249Sradhika.jagtap@ARM.com * 12111249Sradhika.jagtap@ARM.com * At the start of an execution event, first we attempt to issue such pending 12211249Sradhika.jagtap@ARM.com * nodes by checking if appropriate resources have become available. If yes, we 12311249Sradhika.jagtap@ARM.com * compute the execute tick with respect to the time then. Then we proceed to 12411249Sradhika.jagtap@ARM.com * complete nodes from the readyList. 12511249Sradhika.jagtap@ARM.com * 12611249Sradhika.jagtap@ARM.com * When a read response is received, sometimes a dependency on it that was 12711249Sradhika.jagtap@ARM.com * supposed to be released when it was issued is still not released. This 12811249Sradhika.jagtap@ARM.com * occurs because the dependent gets added to the graph after the read was 12911249Sradhika.jagtap@ARM.com * sent. So the check is made less strict and the dependency is marked complete 13011249Sradhika.jagtap@ARM.com * on read response instead of insisting that it should have been removed on 13111249Sradhika.jagtap@ARM.com * read sent. 13211249Sradhika.jagtap@ARM.com * 13311249Sradhika.jagtap@ARM.com * There is a check for requests spanning two cache lines as this condition 13411249Sradhika.jagtap@ARM.com * triggers an assert fail in the L1 cache. If it does then truncate the size 13511249Sradhika.jagtap@ARM.com * to access only until the end of that line and ignore the remainder. 13611249Sradhika.jagtap@ARM.com * Strictly-ordered requests are skipped and the dependencies on such requests 13711249Sradhika.jagtap@ARM.com * are handled by simply marking them complete immediately. 13811249Sradhika.jagtap@ARM.com * 13911632Sradhika.jagtap@arm.com * A CountedExitEvent that contains a static int belonging to the Trace CPU 14011632Sradhika.jagtap@arm.com * class as a down counter is used to implement multi Trace CPU simulation 14111632Sradhika.jagtap@arm.com * exit. 14211249Sradhika.jagtap@ARM.com */ 14311249Sradhika.jagtap@ARM.com 14411249Sradhika.jagtap@ARM.comclass TraceCPU : public BaseCPU 14511249Sradhika.jagtap@ARM.com{ 14611249Sradhika.jagtap@ARM.com 14711249Sradhika.jagtap@ARM.com public: 14811249Sradhika.jagtap@ARM.com TraceCPU(TraceCPUParams *params); 14911249Sradhika.jagtap@ARM.com ~TraceCPU(); 15011249Sradhika.jagtap@ARM.com 15111249Sradhika.jagtap@ARM.com void init(); 15211249Sradhika.jagtap@ARM.com 15311249Sradhika.jagtap@ARM.com /** 15411249Sradhika.jagtap@ARM.com * This is a pure virtual function in BaseCPU. As we don't know how many 15511249Sradhika.jagtap@ARM.com * insts are in the trace but only know how how many micro-ops are we 15611249Sradhika.jagtap@ARM.com * cannot count this stat. 15711249Sradhika.jagtap@ARM.com * 15811249Sradhika.jagtap@ARM.com * @return 0 15911249Sradhika.jagtap@ARM.com */ 16011249Sradhika.jagtap@ARM.com Counter totalInsts() const 16111249Sradhika.jagtap@ARM.com { 16211249Sradhika.jagtap@ARM.com return 0; 16311249Sradhika.jagtap@ARM.com } 16411249Sradhika.jagtap@ARM.com 16511249Sradhika.jagtap@ARM.com /** 16611249Sradhika.jagtap@ARM.com * Return totalOps as the number of committed micro-ops plus the 16711249Sradhika.jagtap@ARM.com * speculatively issued loads that are modelled in the TraceCPU replay. 16811249Sradhika.jagtap@ARM.com * 16911249Sradhika.jagtap@ARM.com * @return number of micro-ops i.e. nodes in the elastic data generator 17011249Sradhika.jagtap@ARM.com */ 17111249Sradhika.jagtap@ARM.com Counter totalOps() const 17211249Sradhika.jagtap@ARM.com { 17311632Sradhika.jagtap@arm.com return numOps.value(); 17411249Sradhika.jagtap@ARM.com } 17511249Sradhika.jagtap@ARM.com 17611632Sradhika.jagtap@arm.com /* 17711632Sradhika.jagtap@arm.com * Set the no. of ops when elastic data generator completes executing a 17811632Sradhika.jagtap@arm.com * node. 17911632Sradhika.jagtap@arm.com */ 18011918Sradhika.jagtap@arm.com void updateNumOps(uint64_t rob_num); 18111632Sradhika.jagtap@arm.com 18211249Sradhika.jagtap@ARM.com /* Pure virtual function in BaseCPU. Do nothing. */ 18311249Sradhika.jagtap@ARM.com void wakeup(ThreadID tid = 0) 18411249Sradhika.jagtap@ARM.com { 18511249Sradhika.jagtap@ARM.com return; 18611249Sradhika.jagtap@ARM.com } 18711249Sradhika.jagtap@ARM.com 18811249Sradhika.jagtap@ARM.com /* 18911249Sradhika.jagtap@ARM.com * When resuming from checkpoint in FS mode, the TraceCPU takes over from 19011249Sradhika.jagtap@ARM.com * the old cpu. This function overrides the takeOverFrom() function in the 19111249Sradhika.jagtap@ARM.com * BaseCPU. It unbinds the ports of the old CPU and binds the ports of the 19211249Sradhika.jagtap@ARM.com * TraceCPU. 19311249Sradhika.jagtap@ARM.com */ 19411249Sradhika.jagtap@ARM.com void takeOverFrom(BaseCPU *oldCPU); 19511249Sradhika.jagtap@ARM.com 19611249Sradhika.jagtap@ARM.com /** 19711249Sradhika.jagtap@ARM.com * When instruction cache port receives a retry, schedule event 19811249Sradhika.jagtap@ARM.com * icacheNextEvent. 19911249Sradhika.jagtap@ARM.com */ 20011249Sradhika.jagtap@ARM.com void icacheRetryRecvd(); 20111249Sradhika.jagtap@ARM.com 20211249Sradhika.jagtap@ARM.com /** 20311249Sradhika.jagtap@ARM.com * When data cache port receives a retry, schedule event 20411249Sradhika.jagtap@ARM.com * dcacheNextEvent. 20511249Sradhika.jagtap@ARM.com */ 20611249Sradhika.jagtap@ARM.com void dcacheRetryRecvd(); 20711249Sradhika.jagtap@ARM.com 20811249Sradhika.jagtap@ARM.com /** 20911249Sradhika.jagtap@ARM.com * When data cache port receives a response, this calls the dcache 21011249Sradhika.jagtap@ARM.com * generator method handle to complete the load writeback. 21111249Sradhika.jagtap@ARM.com * 21211249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 21311249Sradhika.jagtap@ARM.com */ 21411249Sradhika.jagtap@ARM.com void dcacheRecvTimingResp(PacketPtr pkt); 21511249Sradhika.jagtap@ARM.com 21611249Sradhika.jagtap@ARM.com /** 21711249Sradhika.jagtap@ARM.com * Schedule event dcacheNextEvent at the given tick 21811249Sradhika.jagtap@ARM.com * 21911249Sradhika.jagtap@ARM.com * @param when Tick at which to schedule event 22011249Sradhika.jagtap@ARM.com */ 22111249Sradhika.jagtap@ARM.com void schedDcacheNextEvent(Tick when); 22211249Sradhika.jagtap@ARM.com 22311249Sradhika.jagtap@ARM.com protected: 22411249Sradhika.jagtap@ARM.com 22511249Sradhika.jagtap@ARM.com /** 22611249Sradhika.jagtap@ARM.com * IcachePort class that interfaces with L1 Instruction Cache. 22711249Sradhika.jagtap@ARM.com */ 22811249Sradhika.jagtap@ARM.com class IcachePort : public MasterPort 22911249Sradhika.jagtap@ARM.com { 23011249Sradhika.jagtap@ARM.com public: 23111249Sradhika.jagtap@ARM.com /** Default constructor. */ 23211249Sradhika.jagtap@ARM.com IcachePort(TraceCPU* _cpu) 23311249Sradhika.jagtap@ARM.com : MasterPort(_cpu->name() + ".icache_port", _cpu), 23411249Sradhika.jagtap@ARM.com owner(_cpu) 23511249Sradhika.jagtap@ARM.com { } 23611249Sradhika.jagtap@ARM.com 23711249Sradhika.jagtap@ARM.com public: 23811249Sradhika.jagtap@ARM.com /** 23911249Sradhika.jagtap@ARM.com * Receive the timing reponse and simply delete the packet since 24011249Sradhika.jagtap@ARM.com * instruction fetch requests are issued as per the timing in the trace 24111249Sradhika.jagtap@ARM.com * and responses are ignored. 24211249Sradhika.jagtap@ARM.com * 24311249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 24411249Sradhika.jagtap@ARM.com * @return true 24511249Sradhika.jagtap@ARM.com */ 24611249Sradhika.jagtap@ARM.com bool recvTimingResp(PacketPtr pkt); 24711249Sradhika.jagtap@ARM.com 24811249Sradhika.jagtap@ARM.com /** 24911249Sradhika.jagtap@ARM.com * Required functionally but do nothing. 25011249Sradhika.jagtap@ARM.com * 25111249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 25211249Sradhika.jagtap@ARM.com */ 25311249Sradhika.jagtap@ARM.com void recvTimingSnoopReq(PacketPtr pkt) { } 25411249Sradhika.jagtap@ARM.com 25511249Sradhika.jagtap@ARM.com /** 25611249Sradhika.jagtap@ARM.com * Handle a retry signalled by the cache if instruction read failed in 25711249Sradhika.jagtap@ARM.com * the first attempt. 25811249Sradhika.jagtap@ARM.com */ 25911249Sradhika.jagtap@ARM.com void recvReqRetry(); 26011249Sradhika.jagtap@ARM.com 26111249Sradhika.jagtap@ARM.com private: 26211249Sradhika.jagtap@ARM.com TraceCPU* owner; 26311249Sradhika.jagtap@ARM.com }; 26411249Sradhika.jagtap@ARM.com 26511249Sradhika.jagtap@ARM.com /** 26611249Sradhika.jagtap@ARM.com * DcachePort class that interfaces with L1 Data Cache. 26711249Sradhika.jagtap@ARM.com */ 26811249Sradhika.jagtap@ARM.com class DcachePort : public MasterPort 26911249Sradhika.jagtap@ARM.com { 27011249Sradhika.jagtap@ARM.com 27111249Sradhika.jagtap@ARM.com public: 27211249Sradhika.jagtap@ARM.com /** Default constructor. */ 27311249Sradhika.jagtap@ARM.com DcachePort(TraceCPU* _cpu) 27411249Sradhika.jagtap@ARM.com : MasterPort(_cpu->name() + ".dcache_port", _cpu), 27511249Sradhika.jagtap@ARM.com owner(_cpu) 27611249Sradhika.jagtap@ARM.com { } 27711249Sradhika.jagtap@ARM.com 27811249Sradhika.jagtap@ARM.com public: 27911249Sradhika.jagtap@ARM.com 28011249Sradhika.jagtap@ARM.com /** 28111249Sradhika.jagtap@ARM.com * Receive the timing reponse and call dcacheRecvTimingResp() method 28211249Sradhika.jagtap@ARM.com * of the dcacheGen to handle completing the load 28311249Sradhika.jagtap@ARM.com * 28411249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 28511249Sradhika.jagtap@ARM.com * @return true 28611249Sradhika.jagtap@ARM.com */ 28711249Sradhika.jagtap@ARM.com bool recvTimingResp(PacketPtr pkt); 28811249Sradhika.jagtap@ARM.com 28911249Sradhika.jagtap@ARM.com /** 29011249Sradhika.jagtap@ARM.com * Required functionally but do nothing. 29111249Sradhika.jagtap@ARM.com * 29211249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 29311249Sradhika.jagtap@ARM.com */ 29411249Sradhika.jagtap@ARM.com void recvTimingSnoopReq(PacketPtr pkt) 29511249Sradhika.jagtap@ARM.com { } 29611249Sradhika.jagtap@ARM.com 29711249Sradhika.jagtap@ARM.com /** 29811249Sradhika.jagtap@ARM.com * Required functionally but do nothing. 29911249Sradhika.jagtap@ARM.com * 30011249Sradhika.jagtap@ARM.com * @param pkt Pointer to packet received 30111249Sradhika.jagtap@ARM.com */ 30211249Sradhika.jagtap@ARM.com void recvFunctionalSnoop(PacketPtr pkt) 30311249Sradhika.jagtap@ARM.com { } 30411249Sradhika.jagtap@ARM.com 30511249Sradhika.jagtap@ARM.com /** 30611249Sradhika.jagtap@ARM.com * Handle a retry signalled by the cache if data access failed in the 30711249Sradhika.jagtap@ARM.com * first attempt. 30811249Sradhika.jagtap@ARM.com */ 30911249Sradhika.jagtap@ARM.com void recvReqRetry(); 31011249Sradhika.jagtap@ARM.com 31111249Sradhika.jagtap@ARM.com /** 31211249Sradhika.jagtap@ARM.com * Required functionally. 31311249Sradhika.jagtap@ARM.com * 31411249Sradhika.jagtap@ARM.com * @return true since we have to snoop 31511249Sradhika.jagtap@ARM.com */ 31611249Sradhika.jagtap@ARM.com bool isSnooping() const { return true; } 31711249Sradhika.jagtap@ARM.com 31811249Sradhika.jagtap@ARM.com private: 31911249Sradhika.jagtap@ARM.com TraceCPU* owner; 32011249Sradhika.jagtap@ARM.com }; 32111249Sradhika.jagtap@ARM.com 32211249Sradhika.jagtap@ARM.com /** Port to connect to L1 instruction cache. */ 32311249Sradhika.jagtap@ARM.com IcachePort icachePort; 32411249Sradhika.jagtap@ARM.com 32511249Sradhika.jagtap@ARM.com /** Port to connect to L1 data cache. */ 32611249Sradhika.jagtap@ARM.com DcachePort dcachePort; 32711249Sradhika.jagtap@ARM.com 32811249Sradhika.jagtap@ARM.com /** Master id for instruction read requests. */ 32911249Sradhika.jagtap@ARM.com const MasterID instMasterID; 33011249Sradhika.jagtap@ARM.com 33111249Sradhika.jagtap@ARM.com /** Master id for data read and write requests. */ 33211249Sradhika.jagtap@ARM.com const MasterID dataMasterID; 33311249Sradhika.jagtap@ARM.com 33411249Sradhika.jagtap@ARM.com /** File names for input instruction and data traces. */ 33511249Sradhika.jagtap@ARM.com std::string instTraceFile, dataTraceFile; 33611249Sradhika.jagtap@ARM.com 33711249Sradhika.jagtap@ARM.com /** 33811249Sradhika.jagtap@ARM.com * Generator to read protobuf trace containing memory requests at fixed 33911249Sradhika.jagtap@ARM.com * timestamps, perform flow control and issue memory requests. If L1 cache 34011249Sradhika.jagtap@ARM.com * port sends packet succesfully, determine the tick to send the next 34111249Sradhika.jagtap@ARM.com * packet else wait for retry from cache. 34211249Sradhika.jagtap@ARM.com */ 34311249Sradhika.jagtap@ARM.com class FixedRetryGen 34411249Sradhika.jagtap@ARM.com { 34511249Sradhika.jagtap@ARM.com 34611249Sradhika.jagtap@ARM.com private: 34711249Sradhika.jagtap@ARM.com 34811249Sradhika.jagtap@ARM.com /** 34911249Sradhika.jagtap@ARM.com * This struct stores a line in the trace file. 35011249Sradhika.jagtap@ARM.com */ 35111249Sradhika.jagtap@ARM.com struct TraceElement { 35211249Sradhika.jagtap@ARM.com 35311249Sradhika.jagtap@ARM.com /** Specifies if the request is to be a read or a write */ 35411249Sradhika.jagtap@ARM.com MemCmd cmd; 35511249Sradhika.jagtap@ARM.com 35611249Sradhika.jagtap@ARM.com /** The address for the request */ 35711249Sradhika.jagtap@ARM.com Addr addr; 35811249Sradhika.jagtap@ARM.com 35911249Sradhika.jagtap@ARM.com /** The size of the access for the request */ 36011249Sradhika.jagtap@ARM.com Addr blocksize; 36111249Sradhika.jagtap@ARM.com 36211249Sradhika.jagtap@ARM.com /** The time at which the request should be sent */ 36311249Sradhika.jagtap@ARM.com Tick tick; 36411249Sradhika.jagtap@ARM.com 36511249Sradhika.jagtap@ARM.com /** Potential request flags to use */ 36611249Sradhika.jagtap@ARM.com Request::FlagsType flags; 36711249Sradhika.jagtap@ARM.com 36811249Sradhika.jagtap@ARM.com /** Instruction PC */ 36911249Sradhika.jagtap@ARM.com Addr pc; 37011249Sradhika.jagtap@ARM.com 37111249Sradhika.jagtap@ARM.com /** 37211249Sradhika.jagtap@ARM.com * Check validity of this element. 37311249Sradhika.jagtap@ARM.com * 37411249Sradhika.jagtap@ARM.com * @return if this element is valid 37511249Sradhika.jagtap@ARM.com */ 37611249Sradhika.jagtap@ARM.com bool isValid() const { 37711249Sradhika.jagtap@ARM.com return cmd != MemCmd::InvalidCmd; 37811249Sradhika.jagtap@ARM.com } 37911249Sradhika.jagtap@ARM.com 38011249Sradhika.jagtap@ARM.com /** 38111249Sradhika.jagtap@ARM.com * Make this element invalid. 38211249Sradhika.jagtap@ARM.com */ 38311249Sradhika.jagtap@ARM.com void clear() { 38411249Sradhika.jagtap@ARM.com cmd = MemCmd::InvalidCmd; 38511249Sradhika.jagtap@ARM.com } 38611249Sradhika.jagtap@ARM.com }; 38711249Sradhika.jagtap@ARM.com 38811249Sradhika.jagtap@ARM.com /** 38911249Sradhika.jagtap@ARM.com * The InputStream encapsulates a trace file and the 39011249Sradhika.jagtap@ARM.com * internal buffers and populates TraceElements based on 39111249Sradhika.jagtap@ARM.com * the input. 39211249Sradhika.jagtap@ARM.com */ 39311249Sradhika.jagtap@ARM.com class InputStream 39411249Sradhika.jagtap@ARM.com { 39511249Sradhika.jagtap@ARM.com 39611249Sradhika.jagtap@ARM.com private: 39711249Sradhika.jagtap@ARM.com 39811249Sradhika.jagtap@ARM.com // Input file stream for the protobuf trace 39911249Sradhika.jagtap@ARM.com ProtoInputStream trace; 40011249Sradhika.jagtap@ARM.com 40111249Sradhika.jagtap@ARM.com public: 40211249Sradhika.jagtap@ARM.com 40311249Sradhika.jagtap@ARM.com /** 40411249Sradhika.jagtap@ARM.com * Create a trace input stream for a given file name. 40511249Sradhika.jagtap@ARM.com * 40611249Sradhika.jagtap@ARM.com * @param filename Path to the file to read from 40711249Sradhika.jagtap@ARM.com */ 40811249Sradhika.jagtap@ARM.com InputStream(const std::string& filename); 40911249Sradhika.jagtap@ARM.com 41011249Sradhika.jagtap@ARM.com /** 41111249Sradhika.jagtap@ARM.com * Reset the stream such that it can be played once 41211249Sradhika.jagtap@ARM.com * again. 41311249Sradhika.jagtap@ARM.com */ 41411249Sradhika.jagtap@ARM.com void reset(); 41511249Sradhika.jagtap@ARM.com 41611249Sradhika.jagtap@ARM.com /** 41711249Sradhika.jagtap@ARM.com * Attempt to read a trace element from the stream, 41811249Sradhika.jagtap@ARM.com * and also notify the caller if the end of the file 41911249Sradhika.jagtap@ARM.com * was reached. 42011249Sradhika.jagtap@ARM.com * 42111249Sradhika.jagtap@ARM.com * @param element Trace element to populate 42211249Sradhika.jagtap@ARM.com * @return True if an element could be read successfully 42311249Sradhika.jagtap@ARM.com */ 42411249Sradhika.jagtap@ARM.com bool read(TraceElement* element); 42511249Sradhika.jagtap@ARM.com }; 42611249Sradhika.jagtap@ARM.com 42711249Sradhika.jagtap@ARM.com public: 42811249Sradhika.jagtap@ARM.com /* Constructor */ 42911249Sradhika.jagtap@ARM.com FixedRetryGen(TraceCPU& _owner, const std::string& _name, 43011249Sradhika.jagtap@ARM.com MasterPort& _port, MasterID master_id, 43111249Sradhika.jagtap@ARM.com const std::string& trace_file) 43211249Sradhika.jagtap@ARM.com : owner(_owner), 43311249Sradhika.jagtap@ARM.com port(_port), 43411249Sradhika.jagtap@ARM.com masterID(master_id), 43511249Sradhika.jagtap@ARM.com trace(trace_file), 43611249Sradhika.jagtap@ARM.com genName(owner.name() + ".fixedretry" + _name), 43711249Sradhika.jagtap@ARM.com retryPkt(nullptr), 43811249Sradhika.jagtap@ARM.com delta(0), 43911249Sradhika.jagtap@ARM.com traceComplete(false) 44011249Sradhika.jagtap@ARM.com { 44111249Sradhika.jagtap@ARM.com } 44211249Sradhika.jagtap@ARM.com 44311249Sradhika.jagtap@ARM.com /** 44411249Sradhika.jagtap@ARM.com * Called from TraceCPU init(). Reads the first message from the 44511249Sradhika.jagtap@ARM.com * input trace file and returns the send tick. 44611249Sradhika.jagtap@ARM.com * 44711249Sradhika.jagtap@ARM.com * @return Tick when first packet must be sent 44811249Sradhika.jagtap@ARM.com */ 44911249Sradhika.jagtap@ARM.com Tick init(); 45011249Sradhika.jagtap@ARM.com 45111249Sradhika.jagtap@ARM.com /** 45211249Sradhika.jagtap@ARM.com * This tries to send current or retry packet and returns true if 45311249Sradhika.jagtap@ARM.com * successfull. It calls nextExecute() to read next message. 45411249Sradhika.jagtap@ARM.com * 45511249Sradhika.jagtap@ARM.com * @return bool true if packet is sent successfully 45611249Sradhika.jagtap@ARM.com */ 45711249Sradhika.jagtap@ARM.com bool tryNext(); 45811249Sradhika.jagtap@ARM.com 45911249Sradhika.jagtap@ARM.com /** Returns name of the FixedRetryGen instance. */ 46011249Sradhika.jagtap@ARM.com const std::string& name() const { return genName; } 46111249Sradhika.jagtap@ARM.com 46211249Sradhika.jagtap@ARM.com /** 46311249Sradhika.jagtap@ARM.com * Creates a new request assigning the request parameters passed by the 46411249Sradhika.jagtap@ARM.com * arguments. Calls the port's sendTimingReq() and returns true if 46511249Sradhika.jagtap@ARM.com * the packet was sent succesfully. It is called by tryNext() 46611249Sradhika.jagtap@ARM.com * 46711249Sradhika.jagtap@ARM.com * @param addr address of request 46811249Sradhika.jagtap@ARM.com * @param size size of request 46911249Sradhika.jagtap@ARM.com * @param cmd if it is a read or write request 47011249Sradhika.jagtap@ARM.com * @param flags associated request flags 47111249Sradhika.jagtap@ARM.com * @param pc instruction PC that generated the request 47211249Sradhika.jagtap@ARM.com * 47311249Sradhika.jagtap@ARM.com * @return true if packet was sent successfully 47411249Sradhika.jagtap@ARM.com */ 47511249Sradhika.jagtap@ARM.com bool send(Addr addr, unsigned size, const MemCmd& cmd, 47611249Sradhika.jagtap@ARM.com Request::FlagsType flags, Addr pc); 47711249Sradhika.jagtap@ARM.com 47811249Sradhika.jagtap@ARM.com /** Exit the FixedRetryGen. */ 47911249Sradhika.jagtap@ARM.com void exit(); 48011249Sradhika.jagtap@ARM.com 48111249Sradhika.jagtap@ARM.com /** 48211249Sradhika.jagtap@ARM.com * Reads a line of the trace file. Returns the tick 48311249Sradhika.jagtap@ARM.com * when the next request should be generated. If the end 48411249Sradhika.jagtap@ARM.com * of the file has been reached, it returns false. 48511249Sradhika.jagtap@ARM.com * 48611249Sradhika.jagtap@ARM.com * @return bool false id end of file has been reached 48711249Sradhika.jagtap@ARM.com */ 48811249Sradhika.jagtap@ARM.com bool nextExecute(); 48911249Sradhika.jagtap@ARM.com 49011249Sradhika.jagtap@ARM.com /** 49111249Sradhika.jagtap@ARM.com * Returns the traceComplete variable which is set when end of the 49211249Sradhika.jagtap@ARM.com * input trace file is reached. 49311249Sradhika.jagtap@ARM.com * 49411249Sradhika.jagtap@ARM.com * @return bool true if traceComplete is set, false otherwise. 49511249Sradhika.jagtap@ARM.com */ 49611249Sradhika.jagtap@ARM.com bool isTraceComplete() { return traceComplete; } 49711249Sradhika.jagtap@ARM.com 49811249Sradhika.jagtap@ARM.com int64_t tickDelta() { return delta; } 49911249Sradhika.jagtap@ARM.com 50011249Sradhika.jagtap@ARM.com void regStats(); 50111249Sradhika.jagtap@ARM.com 50211249Sradhika.jagtap@ARM.com private: 50311249Sradhika.jagtap@ARM.com 50411249Sradhika.jagtap@ARM.com /** Reference of the TraceCPU. */ 50511249Sradhika.jagtap@ARM.com TraceCPU& owner; 50611249Sradhika.jagtap@ARM.com 50711249Sradhika.jagtap@ARM.com /** Reference of the port to be used to issue memory requests. */ 50811249Sradhika.jagtap@ARM.com MasterPort& port; 50911249Sradhika.jagtap@ARM.com 51011249Sradhika.jagtap@ARM.com /** MasterID used for the requests being sent. */ 51111249Sradhika.jagtap@ARM.com const MasterID masterID; 51211249Sradhika.jagtap@ARM.com 51311249Sradhika.jagtap@ARM.com /** Input stream used for reading the input trace file. */ 51411249Sradhika.jagtap@ARM.com InputStream trace; 51511249Sradhika.jagtap@ARM.com 51611249Sradhika.jagtap@ARM.com /** String to store the name of the FixedRetryGen. */ 51711249Sradhika.jagtap@ARM.com std::string genName; 51811249Sradhika.jagtap@ARM.com 51911249Sradhika.jagtap@ARM.com /** PacketPtr used to store the packet to retry. */ 52011249Sradhika.jagtap@ARM.com PacketPtr retryPkt; 52111249Sradhika.jagtap@ARM.com 52211249Sradhika.jagtap@ARM.com /** 52311249Sradhika.jagtap@ARM.com * Stores the difference in the send ticks of the current and last 52411249Sradhika.jagtap@ARM.com * packets. Keeping this signed to check overflow to a negative value 52511249Sradhika.jagtap@ARM.com * which will be caught by assert(delta > 0) 52611249Sradhika.jagtap@ARM.com */ 52711249Sradhika.jagtap@ARM.com int64_t delta; 52811249Sradhika.jagtap@ARM.com 52911249Sradhika.jagtap@ARM.com /** 53011249Sradhika.jagtap@ARM.com * Set to true when end of trace is reached. 53111249Sradhika.jagtap@ARM.com */ 53211249Sradhika.jagtap@ARM.com bool traceComplete; 53311249Sradhika.jagtap@ARM.com 53411249Sradhika.jagtap@ARM.com /** Store an element read from the trace to send as the next packet. */ 53511249Sradhika.jagtap@ARM.com TraceElement currElement; 53611249Sradhika.jagtap@ARM.com 53711249Sradhika.jagtap@ARM.com /** Stats for instruction accesses replayed. */ 53811249Sradhika.jagtap@ARM.com Stats::Scalar numSendAttempted; 53911249Sradhika.jagtap@ARM.com Stats::Scalar numSendSucceeded; 54011249Sradhika.jagtap@ARM.com Stats::Scalar numSendFailed; 54111249Sradhika.jagtap@ARM.com Stats::Scalar numRetrySucceeded; 54211249Sradhika.jagtap@ARM.com /** Last simulated tick by the FixedRetryGen */ 54311249Sradhika.jagtap@ARM.com Stats::Scalar instLastTick; 54411249Sradhika.jagtap@ARM.com 54511249Sradhika.jagtap@ARM.com }; 54611249Sradhika.jagtap@ARM.com 54711249Sradhika.jagtap@ARM.com /** 54811249Sradhika.jagtap@ARM.com * The elastic data memory request generator to read protobuf trace 54911249Sradhika.jagtap@ARM.com * containing execution trace annotated with data and ordering 55011249Sradhika.jagtap@ARM.com * dependencies. It deduces the time at which to send a load/store request 55111249Sradhika.jagtap@ARM.com * by tracking the dependencies. It attempts to send a memory request for a 55211249Sradhika.jagtap@ARM.com * load/store without performing real execution of micro-ops. If L1 cache 55311249Sradhika.jagtap@ARM.com * port sends packet succesfully, the generator checks which instructions 55411249Sradhika.jagtap@ARM.com * became dependency free as a result of this and schedules an event 55511249Sradhika.jagtap@ARM.com * accordingly. If it fails to send the packet, it waits for a retry from 55611249Sradhika.jagtap@ARM.com * the cache. 55711249Sradhika.jagtap@ARM.com */ 55811249Sradhika.jagtap@ARM.com class ElasticDataGen 55911249Sradhika.jagtap@ARM.com { 56011249Sradhika.jagtap@ARM.com 56111249Sradhika.jagtap@ARM.com private: 56211249Sradhika.jagtap@ARM.com 56311249Sradhika.jagtap@ARM.com /** Node sequence number type. */ 56411249Sradhika.jagtap@ARM.com typedef uint64_t NodeSeqNum; 56511249Sradhika.jagtap@ARM.com 56611249Sradhika.jagtap@ARM.com /** Node ROB number type. */ 56711249Sradhika.jagtap@ARM.com typedef uint64_t NodeRobNum; 56811249Sradhika.jagtap@ARM.com 56911252Sradhika.jagtap@ARM.com typedef ProtoMessage::InstDepRecord::RecordType RecordType; 57011252Sradhika.jagtap@ARM.com typedef ProtoMessage::InstDepRecord Record; 57111252Sradhika.jagtap@ARM.com 57211249Sradhika.jagtap@ARM.com /** 57311249Sradhika.jagtap@ARM.com * The struct GraphNode stores an instruction in the trace file. The 57411249Sradhika.jagtap@ARM.com * format of the trace file favours constructing a dependency graph of 57511249Sradhika.jagtap@ARM.com * the execution and this struct is used to encapsulate the request 57611249Sradhika.jagtap@ARM.com * data as well as pointers to its dependent GraphNodes. 57711249Sradhika.jagtap@ARM.com */ 57811249Sradhika.jagtap@ARM.com class GraphNode { 57911249Sradhika.jagtap@ARM.com 58011249Sradhika.jagtap@ARM.com public: 58111249Sradhika.jagtap@ARM.com /** 58211249Sradhika.jagtap@ARM.com * The maximum no. of ROB dependencies. There can be at most 2 58311249Sradhika.jagtap@ARM.com * order dependencies which could exist for a store. For a load 58411249Sradhika.jagtap@ARM.com * and comp node there can be at most one order dependency. 58511249Sradhika.jagtap@ARM.com */ 58611249Sradhika.jagtap@ARM.com static const uint8_t maxRobDep = 2; 58711249Sradhika.jagtap@ARM.com 58811249Sradhika.jagtap@ARM.com /** Typedef for the array containing the ROB dependencies */ 58911249Sradhika.jagtap@ARM.com typedef std::array<NodeSeqNum, maxRobDep> RobDepArray; 59011249Sradhika.jagtap@ARM.com 59111249Sradhika.jagtap@ARM.com /** Typedef for the array containing the register dependencies */ 59211249Sradhika.jagtap@ARM.com typedef std::array<NodeSeqNum, TheISA::MaxInstSrcRegs> RegDepArray; 59311249Sradhika.jagtap@ARM.com 59411249Sradhika.jagtap@ARM.com /** Instruction sequence number */ 59511249Sradhika.jagtap@ARM.com NodeSeqNum seqNum; 59611249Sradhika.jagtap@ARM.com 59711249Sradhika.jagtap@ARM.com /** ROB occupancy number */ 59811249Sradhika.jagtap@ARM.com NodeRobNum robNum; 59911249Sradhika.jagtap@ARM.com 60011252Sradhika.jagtap@ARM.com /** Type of the node corresponding to the instruction modelled by it */ 60111252Sradhika.jagtap@ARM.com RecordType type; 60211249Sradhika.jagtap@ARM.com 60311249Sradhika.jagtap@ARM.com /** The address for the request if any */ 60411253Sradhika.jagtap@ARM.com Addr physAddr; 60511253Sradhika.jagtap@ARM.com 60611253Sradhika.jagtap@ARM.com /** The virtual address for the request if any */ 60711253Sradhika.jagtap@ARM.com Addr virtAddr; 60811253Sradhika.jagtap@ARM.com 60911253Sradhika.jagtap@ARM.com /** The address space id which is set if the virtual address is set */ 61011253Sradhika.jagtap@ARM.com uint32_t asid; 61111249Sradhika.jagtap@ARM.com 61211249Sradhika.jagtap@ARM.com /** Size of request if any */ 61311249Sradhika.jagtap@ARM.com uint32_t size; 61411249Sradhika.jagtap@ARM.com 61511249Sradhika.jagtap@ARM.com /** Request flags if any */ 61611249Sradhika.jagtap@ARM.com Request::Flags flags; 61711249Sradhika.jagtap@ARM.com 61811249Sradhika.jagtap@ARM.com /** Instruction PC */ 61911249Sradhika.jagtap@ARM.com Addr pc; 62011249Sradhika.jagtap@ARM.com 62111249Sradhika.jagtap@ARM.com /** Array of order dependencies. */ 62211249Sradhika.jagtap@ARM.com RobDepArray robDep; 62311249Sradhika.jagtap@ARM.com 62411249Sradhika.jagtap@ARM.com /** Number of order dependencies */ 62511249Sradhika.jagtap@ARM.com uint8_t numRobDep; 62611249Sradhika.jagtap@ARM.com 62711249Sradhika.jagtap@ARM.com /** Computational delay */ 62811249Sradhika.jagtap@ARM.com uint64_t compDelay; 62911249Sradhika.jagtap@ARM.com 63011249Sradhika.jagtap@ARM.com /** 63111249Sradhika.jagtap@ARM.com * Array of register dependencies (incoming) if any. Maximum number 63211249Sradhika.jagtap@ARM.com * of source registers used to set maximum size of the array 63311249Sradhika.jagtap@ARM.com */ 63411249Sradhika.jagtap@ARM.com RegDepArray regDep; 63511249Sradhika.jagtap@ARM.com 63611249Sradhika.jagtap@ARM.com /** Number of register dependencies */ 63711249Sradhika.jagtap@ARM.com uint8_t numRegDep; 63811249Sradhika.jagtap@ARM.com 63911249Sradhika.jagtap@ARM.com /** 64011249Sradhika.jagtap@ARM.com * A vector of nodes dependent (outgoing) on this node. A 64111249Sradhika.jagtap@ARM.com * sequential container is chosen because when dependents become 64211249Sradhika.jagtap@ARM.com * free, they attempt to issue in program order. 64311249Sradhika.jagtap@ARM.com */ 64411249Sradhika.jagtap@ARM.com std::vector<GraphNode *> dependents; 64511249Sradhika.jagtap@ARM.com 64611252Sradhika.jagtap@ARM.com /** Is the node a load */ 64711252Sradhika.jagtap@ARM.com bool isLoad() const { return (type == Record::LOAD); } 64811252Sradhika.jagtap@ARM.com 64911252Sradhika.jagtap@ARM.com /** Is the node a store */ 65011252Sradhika.jagtap@ARM.com bool isStore() const { return (type == Record::STORE); } 65111252Sradhika.jagtap@ARM.com 65211252Sradhika.jagtap@ARM.com /** Is the node a compute (non load/store) node */ 65311252Sradhika.jagtap@ARM.com bool isComp() const { return (type == Record::COMP); } 65411252Sradhika.jagtap@ARM.com 65511249Sradhika.jagtap@ARM.com /** Initialize register dependency array to all zeroes */ 65611249Sradhika.jagtap@ARM.com void clearRegDep(); 65711249Sradhika.jagtap@ARM.com 65811249Sradhika.jagtap@ARM.com /** Initialize register dependency array to all zeroes */ 65911249Sradhika.jagtap@ARM.com void clearRobDep(); 66011249Sradhika.jagtap@ARM.com 66111249Sradhika.jagtap@ARM.com /** Remove completed instruction from register dependency array */ 66211249Sradhika.jagtap@ARM.com bool removeRegDep(NodeSeqNum reg_dep); 66311249Sradhika.jagtap@ARM.com 66411249Sradhika.jagtap@ARM.com /** Remove completed instruction from order dependency array */ 66511249Sradhika.jagtap@ARM.com bool removeRobDep(NodeSeqNum rob_dep); 66611249Sradhika.jagtap@ARM.com 66711249Sradhika.jagtap@ARM.com /** Check for all dependencies on completed inst */ 66811249Sradhika.jagtap@ARM.com bool removeDepOnInst(NodeSeqNum done_seq_num); 66911249Sradhika.jagtap@ARM.com 67011249Sradhika.jagtap@ARM.com /** Return true if node has a request which is strictly ordered */ 67111249Sradhika.jagtap@ARM.com bool isStrictlyOrdered() const { 67211249Sradhika.jagtap@ARM.com return (flags.isSet(Request::STRICT_ORDER)); 67311249Sradhika.jagtap@ARM.com } 67411249Sradhika.jagtap@ARM.com /** 67511249Sradhika.jagtap@ARM.com * Write out element in trace-compatible format using debug flag 67611249Sradhika.jagtap@ARM.com * TraceCPUData. 67711249Sradhika.jagtap@ARM.com */ 67811249Sradhika.jagtap@ARM.com void writeElementAsTrace() const; 67911252Sradhika.jagtap@ARM.com 68011252Sradhika.jagtap@ARM.com /** Return string specifying the type of the node */ 68111252Sradhika.jagtap@ARM.com std::string typeToStr() const; 68211249Sradhika.jagtap@ARM.com }; 68311249Sradhika.jagtap@ARM.com 68411249Sradhika.jagtap@ARM.com /** Struct to store a ready-to-execute node and its execution tick. */ 68511249Sradhika.jagtap@ARM.com struct ReadyNode 68611249Sradhika.jagtap@ARM.com { 68711249Sradhika.jagtap@ARM.com /** The sequence number of the ready node */ 68811249Sradhika.jagtap@ARM.com NodeSeqNum seqNum; 68911249Sradhika.jagtap@ARM.com 69011249Sradhika.jagtap@ARM.com /** The tick at which the ready node must be executed */ 69111249Sradhika.jagtap@ARM.com Tick execTick; 69211249Sradhika.jagtap@ARM.com }; 69311249Sradhika.jagtap@ARM.com 69411249Sradhika.jagtap@ARM.com /** 69511249Sradhika.jagtap@ARM.com * The HardwareResource class models structures that hold the in-flight 69611249Sradhika.jagtap@ARM.com * nodes. When a node becomes dependency free, first check if resources 69711249Sradhika.jagtap@ARM.com * are available to issue it. 69811249Sradhika.jagtap@ARM.com */ 69911249Sradhika.jagtap@ARM.com class HardwareResource 70011249Sradhika.jagtap@ARM.com { 70111249Sradhika.jagtap@ARM.com public: 70211249Sradhika.jagtap@ARM.com /** 70311249Sradhika.jagtap@ARM.com * Constructor that initializes the sizes of the structures. 70411249Sradhika.jagtap@ARM.com * 70511249Sradhika.jagtap@ARM.com * @param max_rob size of the Reorder Buffer 70611249Sradhika.jagtap@ARM.com * @param max_stores size of Store Buffer 70711249Sradhika.jagtap@ARM.com * @param max_loads size of Load Buffer 70811249Sradhika.jagtap@ARM.com */ 70911249Sradhika.jagtap@ARM.com HardwareResource(uint16_t max_rob, uint16_t max_stores, 71011249Sradhika.jagtap@ARM.com uint16_t max_loads); 71111249Sradhika.jagtap@ARM.com 71211249Sradhika.jagtap@ARM.com /** 71311249Sradhika.jagtap@ARM.com * Occupy appropriate structures for an issued node. 71411249Sradhika.jagtap@ARM.com * 71511249Sradhika.jagtap@ARM.com * @param node_ptr pointer to the issued node 71611249Sradhika.jagtap@ARM.com */ 71711249Sradhika.jagtap@ARM.com void occupy(const GraphNode* new_node); 71811249Sradhika.jagtap@ARM.com 71911249Sradhika.jagtap@ARM.com /** 72011249Sradhika.jagtap@ARM.com * Release appropriate structures for a completed node. 72111249Sradhika.jagtap@ARM.com * 72211249Sradhika.jagtap@ARM.com * @param node_ptr pointer to the completed node 72311249Sradhika.jagtap@ARM.com */ 72411249Sradhika.jagtap@ARM.com void release(const GraphNode* done_node); 72511249Sradhika.jagtap@ARM.com 72611249Sradhika.jagtap@ARM.com /** Release store buffer entry for a completed store */ 72711249Sradhika.jagtap@ARM.com void releaseStoreBuffer(); 72811249Sradhika.jagtap@ARM.com 72911249Sradhika.jagtap@ARM.com /** 73011249Sradhika.jagtap@ARM.com * Check if structures required to issue a node are free. 73111249Sradhika.jagtap@ARM.com * 73211249Sradhika.jagtap@ARM.com * @param node_ptr pointer to the node ready to issue 73311249Sradhika.jagtap@ARM.com * @return true if resources are available 73411249Sradhika.jagtap@ARM.com */ 73511249Sradhika.jagtap@ARM.com bool isAvailable(const GraphNode* new_node) const; 73611249Sradhika.jagtap@ARM.com 73711249Sradhika.jagtap@ARM.com /** 73811249Sradhika.jagtap@ARM.com * Check if there are any outstanding requests, i.e. requests for 73911249Sradhika.jagtap@ARM.com * which we are yet to receive a response. 74011249Sradhika.jagtap@ARM.com * 74111249Sradhika.jagtap@ARM.com * @return true if there is at least one read or write request 74211249Sradhika.jagtap@ARM.com * outstanding 74311249Sradhika.jagtap@ARM.com */ 74411249Sradhika.jagtap@ARM.com bool awaitingResponse() const; 74511249Sradhika.jagtap@ARM.com 74611249Sradhika.jagtap@ARM.com /** Print resource occupancy for debugging */ 74711249Sradhika.jagtap@ARM.com void printOccupancy(); 74811249Sradhika.jagtap@ARM.com 74911249Sradhika.jagtap@ARM.com private: 75011249Sradhika.jagtap@ARM.com /** 75111249Sradhika.jagtap@ARM.com * The size of the ROB used to throttle the max. number of in-flight 75211249Sradhika.jagtap@ARM.com * nodes. 75311249Sradhika.jagtap@ARM.com */ 75411249Sradhika.jagtap@ARM.com const uint16_t sizeROB; 75511249Sradhika.jagtap@ARM.com 75611249Sradhika.jagtap@ARM.com /** 75711249Sradhika.jagtap@ARM.com * The size of store buffer. This is used to throttle the max. number 75811249Sradhika.jagtap@ARM.com * of in-flight stores. 75911249Sradhika.jagtap@ARM.com */ 76011249Sradhika.jagtap@ARM.com const uint16_t sizeStoreBuffer; 76111249Sradhika.jagtap@ARM.com 76211249Sradhika.jagtap@ARM.com /** 76311249Sradhika.jagtap@ARM.com * The size of load buffer. This is used to throttle the max. number 76411249Sradhika.jagtap@ARM.com * of in-flight loads. 76511249Sradhika.jagtap@ARM.com */ 76611249Sradhika.jagtap@ARM.com const uint16_t sizeLoadBuffer; 76711249Sradhika.jagtap@ARM.com 76811249Sradhika.jagtap@ARM.com /** 76911249Sradhika.jagtap@ARM.com * A map from the sequence number to the ROB number of the in- 77011249Sradhika.jagtap@ARM.com * flight nodes. This includes all nodes that are in the readyList 77111249Sradhika.jagtap@ARM.com * plus the loads for which a request has been sent which are not 77211249Sradhika.jagtap@ARM.com * present in the readyList. But such loads are not yet complete 77311249Sradhika.jagtap@ARM.com * and thus occupy resources. We need to query the oldest in-flight 77411249Sradhika.jagtap@ARM.com * node and since a map container keeps all its keys sorted using 77511249Sradhika.jagtap@ARM.com * the less than criterion, the first element is the in-flight node 77611249Sradhika.jagtap@ARM.com * with the least sequence number, i.e. the oldest in-flight node. 77711249Sradhika.jagtap@ARM.com */ 77811249Sradhika.jagtap@ARM.com std::map<NodeSeqNum, NodeRobNum> inFlightNodes; 77911249Sradhika.jagtap@ARM.com 78011249Sradhika.jagtap@ARM.com /** The ROB number of the oldest in-flight node */ 78111249Sradhika.jagtap@ARM.com NodeRobNum oldestInFlightRobNum; 78211249Sradhika.jagtap@ARM.com 78311249Sradhika.jagtap@ARM.com /** Number of ready loads for which request may or may not be sent */ 78411249Sradhika.jagtap@ARM.com uint16_t numInFlightLoads; 78511249Sradhika.jagtap@ARM.com 78611249Sradhika.jagtap@ARM.com /** Number of ready stores for which request may or may not be sent */ 78711249Sradhika.jagtap@ARM.com uint16_t numInFlightStores; 78811249Sradhika.jagtap@ARM.com }; 78911249Sradhika.jagtap@ARM.com 79011249Sradhika.jagtap@ARM.com /** 79111249Sradhika.jagtap@ARM.com * The InputStream encapsulates a trace file and the 79211249Sradhika.jagtap@ARM.com * internal buffers and populates GraphNodes based on 79311249Sradhika.jagtap@ARM.com * the input. 79411249Sradhika.jagtap@ARM.com */ 79511249Sradhika.jagtap@ARM.com class InputStream 79611249Sradhika.jagtap@ARM.com { 79711249Sradhika.jagtap@ARM.com 79811249Sradhika.jagtap@ARM.com private: 79911249Sradhika.jagtap@ARM.com 80011249Sradhika.jagtap@ARM.com /** Input file stream for the protobuf trace */ 80111249Sradhika.jagtap@ARM.com ProtoInputStream trace; 80211249Sradhika.jagtap@ARM.com 80311631Sradhika.jagtap@arm.com /** 80411631Sradhika.jagtap@arm.com * A multiplier for the compute delays in the trace to modulate 80511631Sradhika.jagtap@arm.com * the Trace CPU frequency either up or down. The Trace CPU's 80611631Sradhika.jagtap@arm.com * clock domain frequency must also be set to match the expected 80711631Sradhika.jagtap@arm.com * result of frequency scaling. 80811631Sradhika.jagtap@arm.com */ 80911631Sradhika.jagtap@arm.com const double timeMultiplier; 81011631Sradhika.jagtap@arm.com 81111249Sradhika.jagtap@ARM.com /** Count of committed ops read from trace plus the filtered ops */ 81211249Sradhika.jagtap@ARM.com uint64_t microOpCount; 81311249Sradhika.jagtap@ARM.com 81411249Sradhika.jagtap@ARM.com /** 81511249Sradhika.jagtap@ARM.com * The window size that is read from the header of the protobuf 81611249Sradhika.jagtap@ARM.com * trace and used to process the dependency trace 81711249Sradhika.jagtap@ARM.com */ 81811249Sradhika.jagtap@ARM.com uint32_t windowSize; 81911249Sradhika.jagtap@ARM.com public: 82011249Sradhika.jagtap@ARM.com 82111249Sradhika.jagtap@ARM.com /** 82211249Sradhika.jagtap@ARM.com * Create a trace input stream for a given file name. 82311249Sradhika.jagtap@ARM.com * 82411249Sradhika.jagtap@ARM.com * @param filename Path to the file to read from 82511631Sradhika.jagtap@arm.com * @param time_multiplier used to scale the compute delays 82611249Sradhika.jagtap@ARM.com */ 82711631Sradhika.jagtap@arm.com InputStream(const std::string& filename, 82811631Sradhika.jagtap@arm.com const double time_multiplier); 82911249Sradhika.jagtap@ARM.com 83011249Sradhika.jagtap@ARM.com /** 83111249Sradhika.jagtap@ARM.com * Reset the stream such that it can be played once 83211249Sradhika.jagtap@ARM.com * again. 83311249Sradhika.jagtap@ARM.com */ 83411249Sradhika.jagtap@ARM.com void reset(); 83511249Sradhika.jagtap@ARM.com 83611249Sradhika.jagtap@ARM.com /** 83711249Sradhika.jagtap@ARM.com * Attempt to read a trace element from the stream, 83811249Sradhika.jagtap@ARM.com * and also notify the caller if the end of the file 83911249Sradhika.jagtap@ARM.com * was reached. 84011249Sradhika.jagtap@ARM.com * 84111249Sradhika.jagtap@ARM.com * @param element Trace element to populate 84211249Sradhika.jagtap@ARM.com * @param size of register dependency array stored in the element 84311249Sradhika.jagtap@ARM.com * @return True if an element could be read successfully 84411249Sradhika.jagtap@ARM.com */ 84511249Sradhika.jagtap@ARM.com bool read(GraphNode* element); 84611249Sradhika.jagtap@ARM.com 84711249Sradhika.jagtap@ARM.com /** Get window size from trace */ 84811249Sradhika.jagtap@ARM.com uint32_t getWindowSize() const { return windowSize; } 84911249Sradhika.jagtap@ARM.com 85011249Sradhika.jagtap@ARM.com /** Get number of micro-ops modelled in the TraceCPU replay */ 85111249Sradhika.jagtap@ARM.com uint64_t getMicroOpCount() const { return microOpCount; } 85211249Sradhika.jagtap@ARM.com }; 85311249Sradhika.jagtap@ARM.com 85411249Sradhika.jagtap@ARM.com public: 85511249Sradhika.jagtap@ARM.com /* Constructor */ 85611249Sradhika.jagtap@ARM.com ElasticDataGen(TraceCPU& _owner, const std::string& _name, 85711249Sradhika.jagtap@ARM.com MasterPort& _port, MasterID master_id, 85811631Sradhika.jagtap@arm.com const std::string& trace_file, TraceCPUParams *params) 85911249Sradhika.jagtap@ARM.com : owner(_owner), 86011249Sradhika.jagtap@ARM.com port(_port), 86111249Sradhika.jagtap@ARM.com masterID(master_id), 86211631Sradhika.jagtap@arm.com trace(trace_file, 1.0 / params->freqMultiplier), 86311249Sradhika.jagtap@ARM.com genName(owner.name() + ".elastic" + _name), 86411249Sradhika.jagtap@ARM.com retryPkt(nullptr), 86511249Sradhika.jagtap@ARM.com traceComplete(false), 86611249Sradhika.jagtap@ARM.com nextRead(false), 86711249Sradhika.jagtap@ARM.com execComplete(false), 86811249Sradhika.jagtap@ARM.com windowSize(trace.getWindowSize()), 86911631Sradhika.jagtap@arm.com hwResource(params->sizeROB, params->sizeStoreBuffer, 87011631Sradhika.jagtap@arm.com params->sizeLoadBuffer) 87111249Sradhika.jagtap@ARM.com { 87211249Sradhika.jagtap@ARM.com DPRINTF(TraceCPUData, "Window size in the trace is %d.\n", 87311249Sradhika.jagtap@ARM.com windowSize); 87411249Sradhika.jagtap@ARM.com } 87511249Sradhika.jagtap@ARM.com 87611249Sradhika.jagtap@ARM.com /** 87711249Sradhika.jagtap@ARM.com * Called from TraceCPU init(). Reads the first message from the 87811249Sradhika.jagtap@ARM.com * input trace file and returns the send tick. 87911249Sradhika.jagtap@ARM.com * 88011249Sradhika.jagtap@ARM.com * @return Tick when first packet must be sent 88111249Sradhika.jagtap@ARM.com */ 88211249Sradhika.jagtap@ARM.com Tick init(); 88311249Sradhika.jagtap@ARM.com 88411632Sradhika.jagtap@arm.com /** 88511632Sradhika.jagtap@arm.com * Adjust traceOffset based on what TraceCPU init() determines on 88611632Sradhika.jagtap@arm.com * comparing the offsets in the fetch request and elastic traces. 88711632Sradhika.jagtap@arm.com * 88811632Sradhika.jagtap@arm.com * @param trace_offset trace offset set by comparing both traces 88911632Sradhika.jagtap@arm.com */ 89011632Sradhika.jagtap@arm.com void adjustInitTraceOffset(Tick& offset); 89111632Sradhika.jagtap@arm.com 89211249Sradhika.jagtap@ARM.com /** Returns name of the ElasticDataGen instance. */ 89311249Sradhika.jagtap@ARM.com const std::string& name() const { return genName; } 89411249Sradhika.jagtap@ARM.com 89511249Sradhika.jagtap@ARM.com /** Exit the ElasticDataGen. */ 89611249Sradhika.jagtap@ARM.com void exit(); 89711249Sradhika.jagtap@ARM.com 89811249Sradhika.jagtap@ARM.com /** 89911249Sradhika.jagtap@ARM.com * Reads a line of the trace file. Returns the tick when the next 90011249Sradhika.jagtap@ARM.com * request should be generated. If the end of the file has been 90111249Sradhika.jagtap@ARM.com * reached, it returns false. 90211249Sradhika.jagtap@ARM.com * 90311249Sradhika.jagtap@ARM.com * @return bool false if end of file has been reached else true 90411249Sradhika.jagtap@ARM.com */ 90511249Sradhika.jagtap@ARM.com bool readNextWindow(); 90611249Sradhika.jagtap@ARM.com 90711249Sradhika.jagtap@ARM.com /** 90811249Sradhika.jagtap@ARM.com * Iterate over the dependencies of a new node and add the new node 90911249Sradhika.jagtap@ARM.com * to the list of dependents of the parent node. 91011249Sradhika.jagtap@ARM.com * 91111249Sradhika.jagtap@ARM.com * @param new_node new node to add to the graph 91211249Sradhika.jagtap@ARM.com * @tparam dep_array the dependency array of type rob or register, 91311249Sradhika.jagtap@ARM.com * that is to be iterated, and may get modified 91411249Sradhika.jagtap@ARM.com * @param num_dep the number of dependencies set in the array 91511249Sradhika.jagtap@ARM.com * which may get modified during iteration 91611249Sradhika.jagtap@ARM.com */ 91711249Sradhika.jagtap@ARM.com template<typename T> void addDepsOnParent(GraphNode *new_node, 91811249Sradhika.jagtap@ARM.com T& dep_array, 91911249Sradhika.jagtap@ARM.com uint8_t& num_dep); 92011249Sradhika.jagtap@ARM.com 92111249Sradhika.jagtap@ARM.com /** 92211249Sradhika.jagtap@ARM.com * This is the main execute function which consumes nodes from the 92311249Sradhika.jagtap@ARM.com * sorted readyList. First attempt to issue the pending dependency-free 92411249Sradhika.jagtap@ARM.com * nodes held in the depFreeQueue. Insert the ready-to-issue nodes into 92511249Sradhika.jagtap@ARM.com * the readyList. Then iterate through the readyList and when a node 92611249Sradhika.jagtap@ARM.com * has its execute tick equal to curTick(), execute it. If the node is 92711249Sradhika.jagtap@ARM.com * a load or a store call executeMemReq() and if it is neither, simply 92811249Sradhika.jagtap@ARM.com * mark it complete. 92911249Sradhika.jagtap@ARM.com */ 93011249Sradhika.jagtap@ARM.com void execute(); 93111249Sradhika.jagtap@ARM.com 93211249Sradhika.jagtap@ARM.com /** 93311249Sradhika.jagtap@ARM.com * Creates a new request for a load or store assigning the request 93411249Sradhika.jagtap@ARM.com * parameters. Calls the port's sendTimingReq() and returns a packet 93511249Sradhika.jagtap@ARM.com * if the send failed so that it can be saved for a retry. 93611249Sradhika.jagtap@ARM.com * 93711249Sradhika.jagtap@ARM.com * @param node_ptr pointer to the load or store node to be executed 93811249Sradhika.jagtap@ARM.com * 93911249Sradhika.jagtap@ARM.com * @return packet pointer if the request failed and nullptr if it was 94011249Sradhika.jagtap@ARM.com * sent successfully 94111249Sradhika.jagtap@ARM.com */ 94211249Sradhika.jagtap@ARM.com PacketPtr executeMemReq(GraphNode* node_ptr); 94311249Sradhika.jagtap@ARM.com 94411249Sradhika.jagtap@ARM.com /** 94511249Sradhika.jagtap@ARM.com * Add a ready node to the readyList. When inserting, ensure the nodes 94611249Sradhika.jagtap@ARM.com * are sorted in ascending order of their execute ticks. 94711249Sradhika.jagtap@ARM.com * 94811249Sradhika.jagtap@ARM.com * @param seq_num seq. num of ready node 94911249Sradhika.jagtap@ARM.com * @param exec_tick the execute tick of the ready node 95011249Sradhika.jagtap@ARM.com */ 95111249Sradhika.jagtap@ARM.com void addToSortedReadyList(NodeSeqNum seq_num, Tick exec_tick); 95211249Sradhika.jagtap@ARM.com 95311249Sradhika.jagtap@ARM.com /** Print readyList for debugging using debug flag TraceCPUData. */ 95411249Sradhika.jagtap@ARM.com void printReadyList(); 95511249Sradhika.jagtap@ARM.com 95611249Sradhika.jagtap@ARM.com /** 95711249Sradhika.jagtap@ARM.com * When a load writeback is received, that is when the load completes, 95811249Sradhika.jagtap@ARM.com * release the dependents on it. This is called from the dcache port 95911249Sradhika.jagtap@ARM.com * recvTimingResp(). 96011249Sradhika.jagtap@ARM.com */ 96111249Sradhika.jagtap@ARM.com void completeMemAccess(PacketPtr pkt); 96211249Sradhika.jagtap@ARM.com 96311249Sradhika.jagtap@ARM.com /** 96411249Sradhika.jagtap@ARM.com * Returns the execComplete variable which is set when the last 96511249Sradhika.jagtap@ARM.com * node is executed. 96611249Sradhika.jagtap@ARM.com * 96711249Sradhika.jagtap@ARM.com * @return bool true if execComplete is set, false otherwise. 96811249Sradhika.jagtap@ARM.com */ 96911249Sradhika.jagtap@ARM.com bool isExecComplete() const { return execComplete; } 97011249Sradhika.jagtap@ARM.com 97111249Sradhika.jagtap@ARM.com /** 97211249Sradhika.jagtap@ARM.com * Attempts to issue a node once the node's source dependencies are 97311249Sradhika.jagtap@ARM.com * complete. If resources are available then add it to the readyList, 97411249Sradhika.jagtap@ARM.com * otherwise the node is not issued and is stored in depFreeQueue 97511249Sradhika.jagtap@ARM.com * until resources become available. 97611249Sradhika.jagtap@ARM.com * 97711249Sradhika.jagtap@ARM.com * @param node_ptr pointer to node to be issued 97811249Sradhika.jagtap@ARM.com * @param first true if this is the first attempt to issue this node 97911249Sradhika.jagtap@ARM.com * @return true if node was added to readyList 98011249Sradhika.jagtap@ARM.com */ 98111249Sradhika.jagtap@ARM.com bool checkAndIssue(const GraphNode* node_ptr, bool first = true); 98211249Sradhika.jagtap@ARM.com 98311249Sradhika.jagtap@ARM.com /** Get number of micro-ops modelled in the TraceCPU replay */ 98411249Sradhika.jagtap@ARM.com uint64_t getMicroOpCount() const { return trace.getMicroOpCount(); } 98511249Sradhika.jagtap@ARM.com 98611249Sradhika.jagtap@ARM.com void regStats(); 98711249Sradhika.jagtap@ARM.com 98811249Sradhika.jagtap@ARM.com private: 98911249Sradhika.jagtap@ARM.com 99011249Sradhika.jagtap@ARM.com /** Reference of the TraceCPU. */ 99111249Sradhika.jagtap@ARM.com TraceCPU& owner; 99211249Sradhika.jagtap@ARM.com 99311249Sradhika.jagtap@ARM.com /** Reference of the port to be used to issue memory requests. */ 99411249Sradhika.jagtap@ARM.com MasterPort& port; 99511249Sradhika.jagtap@ARM.com 99611249Sradhika.jagtap@ARM.com /** MasterID used for the requests being sent. */ 99711249Sradhika.jagtap@ARM.com const MasterID masterID; 99811249Sradhika.jagtap@ARM.com 99911249Sradhika.jagtap@ARM.com /** Input stream used for reading the input trace file. */ 100011249Sradhika.jagtap@ARM.com InputStream trace; 100111249Sradhika.jagtap@ARM.com 100211249Sradhika.jagtap@ARM.com /** String to store the name of the FixedRetryGen. */ 100311249Sradhika.jagtap@ARM.com std::string genName; 100411249Sradhika.jagtap@ARM.com 100511249Sradhika.jagtap@ARM.com /** PacketPtr used to store the packet to retry. */ 100611249Sradhika.jagtap@ARM.com PacketPtr retryPkt; 100711249Sradhika.jagtap@ARM.com 100811249Sradhika.jagtap@ARM.com /** Set to true when end of trace is reached. */ 100911249Sradhika.jagtap@ARM.com bool traceComplete; 101011249Sradhika.jagtap@ARM.com 101111249Sradhika.jagtap@ARM.com /** Set to true when the next window of instructions need to be read */ 101211249Sradhika.jagtap@ARM.com bool nextRead; 101311249Sradhika.jagtap@ARM.com 101411249Sradhika.jagtap@ARM.com /** Set true when execution of trace is complete */ 101511249Sradhika.jagtap@ARM.com bool execComplete; 101611249Sradhika.jagtap@ARM.com 101711249Sradhika.jagtap@ARM.com /** 101811249Sradhika.jagtap@ARM.com * Window size within which to check for dependencies. Its value is 101911249Sradhika.jagtap@ARM.com * made equal to the window size used to generate the trace which is 102011249Sradhika.jagtap@ARM.com * recorded in the trace header. The dependency graph must be 102111249Sradhika.jagtap@ARM.com * populated enough such that when a node completes, its potential 102211249Sradhika.jagtap@ARM.com * child node must be found and the dependency removed before the 102311249Sradhika.jagtap@ARM.com * completed node itself is removed. Thus as soon as the graph shrinks 102411249Sradhika.jagtap@ARM.com * to become smaller than this window, we read in the next window. 102511249Sradhika.jagtap@ARM.com */ 102611249Sradhika.jagtap@ARM.com const uint32_t windowSize; 102711249Sradhika.jagtap@ARM.com 102811249Sradhika.jagtap@ARM.com /** 102911249Sradhika.jagtap@ARM.com * Hardware resources required to contain in-flight nodes and to 103011249Sradhika.jagtap@ARM.com * throttle issuing of new nodes when resources are not available. 103111249Sradhika.jagtap@ARM.com */ 103211249Sradhika.jagtap@ARM.com HardwareResource hwResource; 103311249Sradhika.jagtap@ARM.com 103411249Sradhika.jagtap@ARM.com /** Store the depGraph of GraphNodes */ 103511249Sradhika.jagtap@ARM.com std::unordered_map<NodeSeqNum, GraphNode*> depGraph; 103611249Sradhika.jagtap@ARM.com 103711249Sradhika.jagtap@ARM.com /** 103811249Sradhika.jagtap@ARM.com * Queue of dependency-free nodes that are pending issue because 103911249Sradhika.jagtap@ARM.com * resources are not available. This is chosen to be FIFO so that 104011249Sradhika.jagtap@ARM.com * dependent nodes which become free in program order get pushed 104111249Sradhika.jagtap@ARM.com * into the queue in that order. Thus nodes are more likely to 104211249Sradhika.jagtap@ARM.com * issue in program order. 104311249Sradhika.jagtap@ARM.com */ 104411249Sradhika.jagtap@ARM.com std::queue<const GraphNode*> depFreeQueue; 104511249Sradhika.jagtap@ARM.com 104611249Sradhika.jagtap@ARM.com /** List of nodes that are ready to execute */ 104711249Sradhika.jagtap@ARM.com std::list<ReadyNode> readyList; 104811249Sradhika.jagtap@ARM.com 104911249Sradhika.jagtap@ARM.com /** Stats for data memory accesses replayed. */ 105011249Sradhika.jagtap@ARM.com Stats::Scalar maxDependents; 105111249Sradhika.jagtap@ARM.com Stats::Scalar maxReadyListSize; 105211249Sradhika.jagtap@ARM.com Stats::Scalar numSendAttempted; 105311249Sradhika.jagtap@ARM.com Stats::Scalar numSendSucceeded; 105411249Sradhika.jagtap@ARM.com Stats::Scalar numSendFailed; 105511249Sradhika.jagtap@ARM.com Stats::Scalar numRetrySucceeded; 105611249Sradhika.jagtap@ARM.com Stats::Scalar numSplitReqs; 105711249Sradhika.jagtap@ARM.com Stats::Scalar numSOLoads; 105811249Sradhika.jagtap@ARM.com Stats::Scalar numSOStores; 105911249Sradhika.jagtap@ARM.com /** Tick when ElasticDataGen completes execution */ 106011249Sradhika.jagtap@ARM.com Stats::Scalar dataLastTick; 106111249Sradhika.jagtap@ARM.com }; 106211249Sradhika.jagtap@ARM.com 106311249Sradhika.jagtap@ARM.com /** Instance of FixedRetryGen to replay instruction read requests. */ 106411249Sradhika.jagtap@ARM.com FixedRetryGen icacheGen; 106511249Sradhika.jagtap@ARM.com 106611249Sradhika.jagtap@ARM.com /** Instance of ElasticDataGen to replay data read and write requests. */ 106711249Sradhika.jagtap@ARM.com ElasticDataGen dcacheGen; 106811249Sradhika.jagtap@ARM.com 106911249Sradhika.jagtap@ARM.com /** 107011249Sradhika.jagtap@ARM.com * This is the control flow that uses the functionality of the icacheGen to 107111249Sradhika.jagtap@ARM.com * replay the trace. It calls tryNext(). If it returns true then next event 107211249Sradhika.jagtap@ARM.com * is scheduled at curTick() plus delta. If it returns false then delta is 107311249Sradhika.jagtap@ARM.com * ignored and control is brought back via recvRetry(). 107411249Sradhika.jagtap@ARM.com */ 107511249Sradhika.jagtap@ARM.com void schedIcacheNext(); 107611249Sradhika.jagtap@ARM.com 107711249Sradhika.jagtap@ARM.com /** 107811249Sradhika.jagtap@ARM.com * This is the control flow that uses the functionality of the dcacheGen to 107911249Sradhika.jagtap@ARM.com * replay the trace. It calls execute(). It checks if execution is complete 108011249Sradhika.jagtap@ARM.com * and schedules an event to exit simulation accordingly. 108111249Sradhika.jagtap@ARM.com */ 108211249Sradhika.jagtap@ARM.com void schedDcacheNext(); 108311249Sradhika.jagtap@ARM.com 108411249Sradhika.jagtap@ARM.com /** Event for the control flow method schedIcacheNext() */ 108512085Sspwilson2@wisc.edu EventFunctionWrapper icacheNextEvent; 108611249Sradhika.jagtap@ARM.com 108711249Sradhika.jagtap@ARM.com /** Event for the control flow method schedDcacheNext() */ 108812085Sspwilson2@wisc.edu EventFunctionWrapper dcacheNextEvent; 108911249Sradhika.jagtap@ARM.com 109011249Sradhika.jagtap@ARM.com /** This is called when either generator finishes executing from the trace */ 109111249Sradhika.jagtap@ARM.com void checkAndSchedExitEvent(); 109211249Sradhika.jagtap@ARM.com 109311249Sradhika.jagtap@ARM.com /** Set to true when one of the generators finishes replaying its trace. */ 109411249Sradhika.jagtap@ARM.com bool oneTraceComplete; 109511249Sradhika.jagtap@ARM.com 109611249Sradhika.jagtap@ARM.com /** 109711632Sradhika.jagtap@arm.com * This stores the time offset in the trace, which is taken away from 109811632Sradhika.jagtap@arm.com * the ready times of requests. This is specially useful because the time 109911632Sradhika.jagtap@arm.com * offset can be very large if the traces are generated from the middle of 110011632Sradhika.jagtap@arm.com * a program. 110111249Sradhika.jagtap@ARM.com */ 110211632Sradhika.jagtap@arm.com Tick traceOffset; 110311249Sradhika.jagtap@ARM.com 110411249Sradhika.jagtap@ARM.com /** 110511249Sradhika.jagtap@ARM.com * Number of Trace CPUs in the system used as a shared variable and passed 110611249Sradhika.jagtap@ARM.com * to the CountedExitEvent event used for counting down exit events. It is 110711249Sradhika.jagtap@ARM.com * incremented in the constructor call so that the total is arrived at 110811249Sradhika.jagtap@ARM.com * automatically. 110911249Sradhika.jagtap@ARM.com */ 111011249Sradhika.jagtap@ARM.com static int numTraceCPUs; 111111249Sradhika.jagtap@ARM.com 111211249Sradhika.jagtap@ARM.com /** 111311249Sradhika.jagtap@ARM.com * A CountedExitEvent which when serviced decrements the counter. A sim 111411249Sradhika.jagtap@ARM.com * exit event is scheduled when the counter equals zero, that is all 111511249Sradhika.jagtap@ARM.com * instances of Trace CPU have had their execCompleteEvent serviced. 111611249Sradhika.jagtap@ARM.com */ 111711249Sradhika.jagtap@ARM.com CountedExitEvent *execCompleteEvent; 111811249Sradhika.jagtap@ARM.com 111911633Sradhika.jagtap@arm.com /** 112011633Sradhika.jagtap@arm.com * Exit when any one Trace CPU completes its execution. If this is 112111633Sradhika.jagtap@arm.com * configured true then the execCompleteEvent is not scheduled. 112211633Sradhika.jagtap@arm.com */ 112311633Sradhika.jagtap@arm.com const bool enableEarlyExit; 112411633Sradhika.jagtap@arm.com 112511918Sradhika.jagtap@arm.com /** 112611918Sradhika.jagtap@arm.com * Interval of committed instructions specified by the user at which a 112711918Sradhika.jagtap@arm.com * progress info message is printed 112811918Sradhika.jagtap@arm.com */ 112911918Sradhika.jagtap@arm.com const uint64_t progressMsgInterval; 113011918Sradhika.jagtap@arm.com 113111918Sradhika.jagtap@arm.com /* 113211918Sradhika.jagtap@arm.com * The progress msg threshold is kept updated to the next multiple of the 113311918Sradhika.jagtap@arm.com * progress msg interval. As soon as the threshold is reached, an info 113411918Sradhika.jagtap@arm.com * message is printed. 113511918Sradhika.jagtap@arm.com */ 113611918Sradhika.jagtap@arm.com uint64_t progressMsgThreshold; 113711918Sradhika.jagtap@arm.com 113811249Sradhika.jagtap@ARM.com Stats::Scalar numSchedDcacheEvent; 113911249Sradhika.jagtap@ARM.com Stats::Scalar numSchedIcacheEvent; 114011249Sradhika.jagtap@ARM.com 114111249Sradhika.jagtap@ARM.com /** Stat for number of simulated micro-ops. */ 114211249Sradhika.jagtap@ARM.com Stats::Scalar numOps; 114311249Sradhika.jagtap@ARM.com /** Stat for the CPI. This is really cycles per micro-op and not inst. */ 114411249Sradhika.jagtap@ARM.com Stats::Formula cpi; 114511249Sradhika.jagtap@ARM.com 114611249Sradhika.jagtap@ARM.com public: 114711249Sradhika.jagtap@ARM.com 114811249Sradhika.jagtap@ARM.com /** Used to get a reference to the icache port. */ 114914198Sgabeblack@google.com Port &getInstPort() { return icachePort; } 115011249Sradhika.jagtap@ARM.com 115111249Sradhika.jagtap@ARM.com /** Used to get a reference to the dcache port. */ 115214198Sgabeblack@google.com Port &getDataPort() { return dcachePort; } 115311249Sradhika.jagtap@ARM.com 115411249Sradhika.jagtap@ARM.com void regStats(); 115511249Sradhika.jagtap@ARM.com}; 115611249Sradhika.jagtap@ARM.com#endif // __CPU_TRACE_TRACE_CPU_HH__ 1157