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