111308Santhony.gutierrez@amd.com/*
211308Santhony.gutierrez@amd.com * Copyright (c) 2011-2015 Advanced Micro Devices, Inc.
311308Santhony.gutierrez@amd.com * All rights reserved.
411308Santhony.gutierrez@amd.com *
511308Santhony.gutierrez@amd.com * For use for simulation and test purposes only
611308Santhony.gutierrez@amd.com *
711308Santhony.gutierrez@amd.com * Redistribution and use in source and binary forms, with or without
811308Santhony.gutierrez@amd.com * modification, are permitted provided that the following conditions are met:
911308Santhony.gutierrez@amd.com *
1011308Santhony.gutierrez@amd.com * 1. Redistributions of source code must retain the above copyright notice,
1111308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer.
1211308Santhony.gutierrez@amd.com *
1311308Santhony.gutierrez@amd.com * 2. Redistributions in binary form must reproduce the above copyright notice,
1411308Santhony.gutierrez@amd.com * this list of conditions and the following disclaimer in the documentation
1511308Santhony.gutierrez@amd.com * and/or other materials provided with the distribution.
1611308Santhony.gutierrez@amd.com *
1712697Santhony.gutierrez@amd.com * 3. Neither the name of the copyright holder nor the names of its
1812697Santhony.gutierrez@amd.com * contributors may be used to endorse or promote products derived from this
1912697Santhony.gutierrez@amd.com * software without specific prior written permission.
2011308Santhony.gutierrez@amd.com *
2111308Santhony.gutierrez@amd.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2211308Santhony.gutierrez@amd.com * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2311308Santhony.gutierrez@amd.com * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2411308Santhony.gutierrez@amd.com * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
2511308Santhony.gutierrez@amd.com * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2611308Santhony.gutierrez@amd.com * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2711308Santhony.gutierrez@amd.com * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2811308Santhony.gutierrez@amd.com * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2911308Santhony.gutierrez@amd.com * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
3011308Santhony.gutierrez@amd.com * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3111308Santhony.gutierrez@amd.com * POSSIBILITY OF SUCH DAMAGE.
3211308Santhony.gutierrez@amd.com *
3312697Santhony.gutierrez@amd.com * Authors: Lisa Hsu
3411308Santhony.gutierrez@amd.com */
3511308Santhony.gutierrez@amd.com
3611308Santhony.gutierrez@amd.com#ifndef __GPU_TLB_HH__
3711308Santhony.gutierrez@amd.com#define __GPU_TLB_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include <fstream>
4011308Santhony.gutierrez@amd.com#include <list>
4111308Santhony.gutierrez@amd.com#include <queue>
4211308Santhony.gutierrez@amd.com#include <string>
4311308Santhony.gutierrez@amd.com#include <vector>
4411308Santhony.gutierrez@amd.com
4511308Santhony.gutierrez@amd.com#include "arch/generic/tlb.hh"
4611308Santhony.gutierrez@amd.com#include "arch/x86/pagetable.hh"
4711308Santhony.gutierrez@amd.com#include "arch/x86/pagetable_walker.hh"
4811308Santhony.gutierrez@amd.com#include "arch/x86/regs/segment.hh"
4911308Santhony.gutierrez@amd.com#include "base/callback.hh"
5012334Sgabeblack@google.com#include "base/logging.hh"
5111308Santhony.gutierrez@amd.com#include "base/statistics.hh"
5211308Santhony.gutierrez@amd.com#include "gpu-compute/compute_unit.hh"
5311308Santhony.gutierrez@amd.com#include "mem/port.hh"
5411308Santhony.gutierrez@amd.com#include "mem/request.hh"
5511308Santhony.gutierrez@amd.com#include "params/X86GPUTLB.hh"
5613892Sgabeblack@google.com#include "sim/clocked_object.hh"
5711308Santhony.gutierrez@amd.com#include "sim/sim_object.hh"
5811308Santhony.gutierrez@amd.com
5911308Santhony.gutierrez@amd.comclass BaseTLB;
6011308Santhony.gutierrez@amd.comclass Packet;
6111308Santhony.gutierrez@amd.comclass ThreadContext;
6211308Santhony.gutierrez@amd.com
6311308Santhony.gutierrez@amd.comnamespace X86ISA
6411308Santhony.gutierrez@amd.com{
6513892Sgabeblack@google.com    class GpuTLB : public ClockedObject
6611308Santhony.gutierrez@amd.com    {
6711308Santhony.gutierrez@amd.com      protected:
6811308Santhony.gutierrez@amd.com        friend class Walker;
6911308Santhony.gutierrez@amd.com
7012717Sbrandon.potter@amd.com        typedef std::list<TlbEntry*> EntryList;
7111308Santhony.gutierrez@amd.com
7211308Santhony.gutierrez@amd.com        uint32_t configAddress;
7311308Santhony.gutierrez@amd.com
7411308Santhony.gutierrez@amd.com        // TLB clock: will inherit clock from shader's clock period in terms
7511308Santhony.gutierrez@amd.com        // of nuber of ticks of curTime (aka global simulation clock)
7611308Santhony.gutierrez@amd.com        // The assignment of TLB clock from shader clock is done in the python
7711308Santhony.gutierrez@amd.com        // config files.
7811308Santhony.gutierrez@amd.com        int clock;
7911308Santhony.gutierrez@amd.com
8011308Santhony.gutierrez@amd.com      public:
8111308Santhony.gutierrez@amd.com        // clock related functions ; maps to-and-from Simulation ticks and
8211308Santhony.gutierrez@amd.com        // object clocks.
8311308Santhony.gutierrez@amd.com        Tick frequency() const { return SimClock::Frequency / clock; }
8411308Santhony.gutierrez@amd.com
8511308Santhony.gutierrez@amd.com        Tick
8611308Santhony.gutierrez@amd.com        ticks(int numCycles) const
8711308Santhony.gutierrez@amd.com        {
8811308Santhony.gutierrez@amd.com            return (Tick)clock * numCycles;
8911308Santhony.gutierrez@amd.com        }
9011308Santhony.gutierrez@amd.com
9111308Santhony.gutierrez@amd.com        Tick curCycle() const { return curTick() / clock; }
9211308Santhony.gutierrez@amd.com        Tick tickToCycles(Tick val) const { return val / clock;}
9311308Santhony.gutierrez@amd.com
9411308Santhony.gutierrez@amd.com        typedef X86GPUTLBParams Params;
9511308Santhony.gutierrez@amd.com        GpuTLB(const Params *p);
9611308Santhony.gutierrez@amd.com        ~GpuTLB();
9711308Santhony.gutierrez@amd.com
9811308Santhony.gutierrez@amd.com        typedef enum BaseTLB::Mode Mode;
9911308Santhony.gutierrez@amd.com
10011308Santhony.gutierrez@amd.com        class Translation
10111308Santhony.gutierrez@amd.com        {
10211308Santhony.gutierrez@amd.com          public:
10311308Santhony.gutierrez@amd.com            virtual ~Translation() { }
10411308Santhony.gutierrez@amd.com
10511308Santhony.gutierrez@amd.com            /**
10611308Santhony.gutierrez@amd.com             * Signal that the translation has been delayed due to a hw page
10711308Santhony.gutierrez@amd.com             * table walk.
10811308Santhony.gutierrez@amd.com             */
10911308Santhony.gutierrez@amd.com            virtual void markDelayed() = 0;
11011308Santhony.gutierrez@amd.com
11111308Santhony.gutierrez@amd.com            /**
11211308Santhony.gutierrez@amd.com             * The memory for this object may be dynamically allocated, and it
11311308Santhony.gutierrez@amd.com             * may be responsible for cleaning itslef up which will happen in
11411308Santhony.gutierrez@amd.com             * this function. Once it's called the object is no longer valid.
11511308Santhony.gutierrez@amd.com             */
11612749Sgiacomo.travaglini@arm.com            virtual void finish(Fault fault, const RequestPtr &req,
11712749Sgiacomo.travaglini@arm.com                                ThreadContext *tc, Mode mode) = 0;
11811308Santhony.gutierrez@amd.com        };
11911308Santhony.gutierrez@amd.com
12011308Santhony.gutierrez@amd.com        void dumpAll();
12112717Sbrandon.potter@amd.com        TlbEntry *lookup(Addr va, bool update_lru=true);
12211308Santhony.gutierrez@amd.com        void setConfigAddress(uint32_t addr);
12311308Santhony.gutierrez@amd.com
12411308Santhony.gutierrez@amd.com      protected:
12511308Santhony.gutierrez@amd.com        EntryList::iterator lookupIt(Addr va, bool update_lru=true);
12611308Santhony.gutierrez@amd.com        Walker *walker;
12711308Santhony.gutierrez@amd.com
12811308Santhony.gutierrez@amd.com      public:
12911308Santhony.gutierrez@amd.com        Walker *getWalker();
13011308Santhony.gutierrez@amd.com        void invalidateAll();
13111308Santhony.gutierrez@amd.com        void invalidateNonGlobal();
13211308Santhony.gutierrez@amd.com        void demapPage(Addr va, uint64_t asn);
13311308Santhony.gutierrez@amd.com
13411308Santhony.gutierrez@amd.com      protected:
13511308Santhony.gutierrez@amd.com        int size;
13611308Santhony.gutierrez@amd.com        int assoc;
13711308Santhony.gutierrez@amd.com        int numSets;
13811308Santhony.gutierrez@amd.com
13911308Santhony.gutierrez@amd.com        /**
14011308Santhony.gutierrez@amd.com         *  true if this is a fully-associative TLB
14111308Santhony.gutierrez@amd.com         */
14211308Santhony.gutierrez@amd.com        bool FA;
14311308Santhony.gutierrez@amd.com        Addr setMask;
14411308Santhony.gutierrez@amd.com
14511308Santhony.gutierrez@amd.com        /**
14611308Santhony.gutierrez@amd.com         * Allocation Policy: true if we always allocate on a hit, false
14711308Santhony.gutierrez@amd.com         * otherwise. Default is true.
14811308Santhony.gutierrez@amd.com         */
14911308Santhony.gutierrez@amd.com        bool allocationPolicy;
15011308Santhony.gutierrez@amd.com
15111308Santhony.gutierrez@amd.com        /**
15211308Santhony.gutierrez@amd.com         * if true, then this is not the last level TLB
15311308Santhony.gutierrez@amd.com         */
15411308Santhony.gutierrez@amd.com        bool hasMemSidePort;
15511308Santhony.gutierrez@amd.com
15611308Santhony.gutierrez@amd.com        /**
15711308Santhony.gutierrez@amd.com         * Print out accessDistance stats. One stat file
15811308Santhony.gutierrez@amd.com         * per TLB.
15911308Santhony.gutierrez@amd.com         */
16011308Santhony.gutierrez@amd.com        bool accessDistance;
16111308Santhony.gutierrez@amd.com
16212717Sbrandon.potter@amd.com        std::vector<TlbEntry> tlb;
16311308Santhony.gutierrez@amd.com
16411308Santhony.gutierrez@amd.com        /*
16511308Santhony.gutierrez@amd.com         * It's a per-set list. As long as we have not reached
16611308Santhony.gutierrez@amd.com         * the full capacity of the given set, grab an entry from
16711308Santhony.gutierrez@amd.com         * the freeList.
16811308Santhony.gutierrez@amd.com         */
16911308Santhony.gutierrez@amd.com        std::vector<EntryList> freeList;
17011308Santhony.gutierrez@amd.com
17111308Santhony.gutierrez@amd.com        /**
17211308Santhony.gutierrez@amd.com         * An entryList per set is the equivalent of an LRU stack;
17311308Santhony.gutierrez@amd.com         * it's used to guide replacement decisions. The head of the list
17411308Santhony.gutierrez@amd.com         * contains the MRU TLB entry of the given set. If the freeList
17511308Santhony.gutierrez@amd.com         * for this set is empty, the last element of the list
17611308Santhony.gutierrez@amd.com         * is evicted (i.e., dropped on the floor).
17711308Santhony.gutierrez@amd.com         */
17811308Santhony.gutierrez@amd.com        std::vector<EntryList> entryList;
17911308Santhony.gutierrez@amd.com
18012749Sgiacomo.travaglini@arm.com        Fault translateInt(const RequestPtr &req, ThreadContext *tc);
18111308Santhony.gutierrez@amd.com
18212749Sgiacomo.travaglini@arm.com        Fault translate(const RequestPtr &req, ThreadContext *tc,
18311308Santhony.gutierrez@amd.com                Translation *translation, Mode mode, bool &delayedResponse,
18411308Santhony.gutierrez@amd.com                bool timing, int &latency);
18511308Santhony.gutierrez@amd.com
18611308Santhony.gutierrez@amd.com      public:
18711308Santhony.gutierrez@amd.com        // latencies for a TLB hit, miss and page fault
18811308Santhony.gutierrez@amd.com        int hitLatency;
18911308Santhony.gutierrez@amd.com        int missLatency1;
19011308Santhony.gutierrez@amd.com        int missLatency2;
19111308Santhony.gutierrez@amd.com
19211308Santhony.gutierrez@amd.com        // local_stats are as seen from the TLB
19311308Santhony.gutierrez@amd.com        // without taking into account coalescing
19411308Santhony.gutierrez@amd.com        Stats::Scalar localNumTLBAccesses;
19511308Santhony.gutierrez@amd.com        Stats::Scalar localNumTLBHits;
19611308Santhony.gutierrez@amd.com        Stats::Scalar localNumTLBMisses;
19711308Santhony.gutierrez@amd.com        Stats::Formula localTLBMissRate;
19811308Santhony.gutierrez@amd.com
19911308Santhony.gutierrez@amd.com        // global_stats are as seen from the
20011308Santhony.gutierrez@amd.com        // CU's perspective taking into account
20111308Santhony.gutierrez@amd.com        // all coalesced requests.
20211308Santhony.gutierrez@amd.com        Stats::Scalar globalNumTLBAccesses;
20311308Santhony.gutierrez@amd.com        Stats::Scalar globalNumTLBHits;
20411308Santhony.gutierrez@amd.com        Stats::Scalar globalNumTLBMisses;
20511308Santhony.gutierrez@amd.com        Stats::Formula globalTLBMissRate;
20611308Santhony.gutierrez@amd.com
20711308Santhony.gutierrez@amd.com        // from the CU perspective (global)
20811308Santhony.gutierrez@amd.com        Stats::Scalar accessCycles;
20911308Santhony.gutierrez@amd.com        // from the CU perspective (global)
21011308Santhony.gutierrez@amd.com        Stats::Scalar pageTableCycles;
21111308Santhony.gutierrez@amd.com        Stats::Scalar numUniquePages;
21211308Santhony.gutierrez@amd.com        // from the perspective of this TLB
21311308Santhony.gutierrez@amd.com        Stats::Scalar localCycles;
21411308Santhony.gutierrez@amd.com        // from the perspective of this TLB
21511308Santhony.gutierrez@amd.com        Stats::Formula localLatency;
21611308Santhony.gutierrez@amd.com        // I take the avg. per page and then
21711308Santhony.gutierrez@amd.com        // the avg. over all pages.
21811308Santhony.gutierrez@amd.com        Stats::Scalar avgReuseDistance;
21911308Santhony.gutierrez@amd.com
22014292Sjqu32@wisc.edu        void regStats() override;
22111308Santhony.gutierrez@amd.com        void updatePageFootprint(Addr virt_page_addr);
22211308Santhony.gutierrez@amd.com        void printAccessPattern();
22311308Santhony.gutierrez@amd.com
22411308Santhony.gutierrez@amd.com
22512749Sgiacomo.travaglini@arm.com        Fault translateAtomic(const RequestPtr &req, ThreadContext *tc,
22612749Sgiacomo.travaglini@arm.com                              Mode mode, int &latency);
22711308Santhony.gutierrez@amd.com
22812749Sgiacomo.travaglini@arm.com        void translateTiming(const RequestPtr &req, ThreadContext *tc,
22911308Santhony.gutierrez@amd.com                             Translation *translation, Mode mode,
23011308Santhony.gutierrez@amd.com                             int &latency);
23111308Santhony.gutierrez@amd.com
23211308Santhony.gutierrez@amd.com        Tick doMmuRegRead(ThreadContext *tc, Packet *pkt);
23311308Santhony.gutierrez@amd.com        Tick doMmuRegWrite(ThreadContext *tc, Packet *pkt);
23411308Santhony.gutierrez@amd.com
23512717Sbrandon.potter@amd.com        TlbEntry *insert(Addr vpn, TlbEntry &entry);
23611308Santhony.gutierrez@amd.com
23711308Santhony.gutierrez@amd.com        // Checkpointing
23814292Sjqu32@wisc.edu        virtual void serialize(CheckpointOut& cp) const override;
23914292Sjqu32@wisc.edu        virtual void unserialize(CheckpointIn& cp) override;
24011308Santhony.gutierrez@amd.com        void issueTranslation();
24111308Santhony.gutierrez@amd.com        enum tlbOutcome {TLB_HIT, TLB_MISS, PAGE_WALK, MISS_RETURN};
24212749Sgiacomo.travaglini@arm.com        bool tlbLookup(const RequestPtr &req,
24312749Sgiacomo.travaglini@arm.com                       ThreadContext *tc, bool update_stats);
24411308Santhony.gutierrez@amd.com
24511308Santhony.gutierrez@amd.com        void handleTranslationReturn(Addr addr, tlbOutcome outcome,
24611308Santhony.gutierrez@amd.com                                     PacketPtr pkt);
24711308Santhony.gutierrez@amd.com
24811308Santhony.gutierrez@amd.com        void handleFuncTranslationReturn(PacketPtr pkt, tlbOutcome outcome);
24911308Santhony.gutierrez@amd.com
25011308Santhony.gutierrez@amd.com        void pagingProtectionChecks(ThreadContext *tc, PacketPtr pkt,
25112717Sbrandon.potter@amd.com                                    TlbEntry *tlb_entry, Mode mode);
25211308Santhony.gutierrez@amd.com
25312717Sbrandon.potter@amd.com        void updatePhysAddresses(Addr virt_page_addr, TlbEntry *tlb_entry,
25411308Santhony.gutierrez@amd.com                                 Addr phys_page_addr);
25511308Santhony.gutierrez@amd.com
25611308Santhony.gutierrez@amd.com        void issueTLBLookup(PacketPtr pkt);
25711308Santhony.gutierrez@amd.com
25811308Santhony.gutierrez@amd.com        // CpuSidePort is the TLB Port closer to the CPU/CU side
25911308Santhony.gutierrez@amd.com        class CpuSidePort : public SlavePort
26011308Santhony.gutierrez@amd.com        {
26111308Santhony.gutierrez@amd.com          public:
26211308Santhony.gutierrez@amd.com            CpuSidePort(const std::string &_name, GpuTLB * gpu_TLB,
26311308Santhony.gutierrez@amd.com                        PortID _index)
26411308Santhony.gutierrez@amd.com                : SlavePort(_name, gpu_TLB), tlb(gpu_TLB), index(_index) { }
26511308Santhony.gutierrez@amd.com
26611308Santhony.gutierrez@amd.com          protected:
26711308Santhony.gutierrez@amd.com            GpuTLB *tlb;
26811308Santhony.gutierrez@amd.com            int index;
26911308Santhony.gutierrez@amd.com
27011308Santhony.gutierrez@amd.com            virtual bool recvTimingReq(PacketPtr pkt);
27111308Santhony.gutierrez@amd.com            virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
27211308Santhony.gutierrez@amd.com            virtual void recvFunctional(PacketPtr pkt);
27311308Santhony.gutierrez@amd.com            virtual void recvRangeChange() { }
27411308Santhony.gutierrez@amd.com            virtual void recvReqRetry();
27513449Sgabeblack@google.com            virtual void recvRespRetry() { panic("recvRespRetry called"); }
27611308Santhony.gutierrez@amd.com            virtual AddrRangeList getAddrRanges() const;
27711308Santhony.gutierrez@amd.com        };
27811308Santhony.gutierrez@amd.com
27911308Santhony.gutierrez@amd.com        /**
28011308Santhony.gutierrez@amd.com         * MemSidePort is the TLB Port closer to the memory side
28111308Santhony.gutierrez@amd.com         * If this is a last level TLB then this port will not be connected.
28211308Santhony.gutierrez@amd.com         *
28311308Santhony.gutierrez@amd.com         * Future action item: if we ever do real page walks, then this port
28411308Santhony.gutierrez@amd.com         * should be connected to a RubyPort.
28511308Santhony.gutierrez@amd.com         */
28611308Santhony.gutierrez@amd.com        class MemSidePort : public MasterPort
28711308Santhony.gutierrez@amd.com        {
28811308Santhony.gutierrez@amd.com          public:
28911308Santhony.gutierrez@amd.com            MemSidePort(const std::string &_name, GpuTLB * gpu_TLB,
29011308Santhony.gutierrez@amd.com                        PortID _index)
29111308Santhony.gutierrez@amd.com                : MasterPort(_name, gpu_TLB), tlb(gpu_TLB), index(_index) { }
29211308Santhony.gutierrez@amd.com
29311308Santhony.gutierrez@amd.com            std::deque<PacketPtr> retries;
29411308Santhony.gutierrez@amd.com
29511308Santhony.gutierrez@amd.com          protected:
29611308Santhony.gutierrez@amd.com            GpuTLB *tlb;
29711308Santhony.gutierrez@amd.com            int index;
29811308Santhony.gutierrez@amd.com
29911308Santhony.gutierrez@amd.com            virtual bool recvTimingResp(PacketPtr pkt);
30011308Santhony.gutierrez@amd.com            virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
30111308Santhony.gutierrez@amd.com            virtual void recvFunctional(PacketPtr pkt) { }
30211308Santhony.gutierrez@amd.com            virtual void recvRangeChange() { }
30311308Santhony.gutierrez@amd.com            virtual void recvReqRetry();
30411308Santhony.gutierrez@amd.com        };
30511308Santhony.gutierrez@amd.com
30611308Santhony.gutierrez@amd.com        // TLB ports on the cpu Side
30711308Santhony.gutierrez@amd.com        std::vector<CpuSidePort*> cpuSidePort;
30811308Santhony.gutierrez@amd.com        // TLB ports on the memory side
30911308Santhony.gutierrez@amd.com        std::vector<MemSidePort*> memSidePort;
31011308Santhony.gutierrez@amd.com
31113784Sgabeblack@google.com        Port &getPort(const std::string &if_name,
31213784Sgabeblack@google.com                      PortID idx=InvalidPortID) override;
31311308Santhony.gutierrez@amd.com
31411308Santhony.gutierrez@amd.com        /**
31511308Santhony.gutierrez@amd.com         * TLB TranslationState: this currently is a somewhat bastardization of
31611308Santhony.gutierrez@amd.com         * the usage of SenderState, whereby the receiver of a packet is not
31711308Santhony.gutierrez@amd.com         * usually supposed to need to look at the contents of the senderState,
31811308Santhony.gutierrez@amd.com         * you're really only supposed to look at what you pushed on, pop it
31911308Santhony.gutierrez@amd.com         * off, and send it back.
32011308Santhony.gutierrez@amd.com         *
32111308Santhony.gutierrez@amd.com         * However, since there is state that we want to pass to the TLBs using
32211308Santhony.gutierrez@amd.com         * the send/recv Timing/Functional/etc. APIs, which don't allow for new
32311308Santhony.gutierrez@amd.com         * arguments, we need a common TLB senderState to pass between TLBs,
32411308Santhony.gutierrez@amd.com         * both "forwards" and "backwards."
32511308Santhony.gutierrez@amd.com         *
32611308Santhony.gutierrez@amd.com         * So, basically, the rule is that any packet received by a TLB port
32711308Santhony.gutierrez@amd.com         * (cpuside OR memside) must be safely castable to a TranslationState.
32811308Santhony.gutierrez@amd.com         */
32911308Santhony.gutierrez@amd.com
33011308Santhony.gutierrez@amd.com        struct TranslationState : public Packet::SenderState
33111308Santhony.gutierrez@amd.com        {
33211308Santhony.gutierrez@amd.com            // TLB mode, read or write
33311308Santhony.gutierrez@amd.com            Mode tlbMode;
33411308Santhony.gutierrez@amd.com            // Thread context associated with this req
33511308Santhony.gutierrez@amd.com            ThreadContext *tc;
33611308Santhony.gutierrez@amd.com
33711308Santhony.gutierrez@amd.com            /*
33811308Santhony.gutierrez@amd.com            * TLB entry to be populated and passed back and filled in
33911308Santhony.gutierrez@amd.com            * previous TLBs.  Equivalent to the data cache concept of
34011308Santhony.gutierrez@amd.com            * "data return."
34111308Santhony.gutierrez@amd.com            */
34212717Sbrandon.potter@amd.com            TlbEntry *tlbEntry;
34311308Santhony.gutierrez@amd.com            // Is this a TLB prefetch request?
34411308Santhony.gutierrez@amd.com            bool prefetch;
34511308Santhony.gutierrez@amd.com            // When was the req for this translation issued
34611308Santhony.gutierrez@amd.com            uint64_t issueTime;
34711308Santhony.gutierrez@amd.com            // Remember where this came from
34811308Santhony.gutierrez@amd.com            std::vector<SlavePort*>ports;
34911308Santhony.gutierrez@amd.com
35011308Santhony.gutierrez@amd.com            // keep track of #uncoalesced reqs per packet per TLB level;
35111308Santhony.gutierrez@amd.com            // reqCnt per level >= reqCnt higher level
35211308Santhony.gutierrez@amd.com            std::vector<int> reqCnt;
35311308Santhony.gutierrez@amd.com            // TLB level this packet hit in; 0 if it hit in the page table
35411308Santhony.gutierrez@amd.com            int hitLevel;
35511308Santhony.gutierrez@amd.com            Packet::SenderState *saved;
35611308Santhony.gutierrez@amd.com
35711308Santhony.gutierrez@amd.com            TranslationState(Mode tlb_mode, ThreadContext *_tc,
35811308Santhony.gutierrez@amd.com                             bool _prefetch=false,
35911308Santhony.gutierrez@amd.com                             Packet::SenderState *_saved=nullptr)
36011308Santhony.gutierrez@amd.com                : tlbMode(tlb_mode), tc(_tc), tlbEntry(nullptr),
36111308Santhony.gutierrez@amd.com                  prefetch(_prefetch), issueTime(0),
36211308Santhony.gutierrez@amd.com                  hitLevel(0),saved(_saved) { }
36311308Santhony.gutierrez@amd.com        };
36411308Santhony.gutierrez@amd.com
36511308Santhony.gutierrez@amd.com        // maximum number of permitted coalesced requests per cycle
36611308Santhony.gutierrez@amd.com        int maxCoalescedReqs;
36711308Santhony.gutierrez@amd.com
36811308Santhony.gutierrez@amd.com        // Current number of outstandings coalesced requests.
36911308Santhony.gutierrez@amd.com        // Should be <= maxCoalescedReqs
37011308Santhony.gutierrez@amd.com        int outstandingReqs;
37111308Santhony.gutierrez@amd.com
37211308Santhony.gutierrez@amd.com        /**
37311308Santhony.gutierrez@amd.com         * A TLBEvent is scheduled after the TLB lookup and helps us take the
37411308Santhony.gutierrez@amd.com         * appropriate actions:
37511308Santhony.gutierrez@amd.com         *  (e.g., update TLB on a hit,
37611308Santhony.gutierrez@amd.com         *  send request to lower level TLB on a miss,
37711308Santhony.gutierrez@amd.com         *  or start a page walk if this was the last-level TLB).
37811308Santhony.gutierrez@amd.com         */
37911308Santhony.gutierrez@amd.com        void translationReturn(Addr virtPageAddr, tlbOutcome outcome,
38011308Santhony.gutierrez@amd.com                               PacketPtr pkt);
38111308Santhony.gutierrez@amd.com
38211308Santhony.gutierrez@amd.com        class TLBEvent : public Event
38311308Santhony.gutierrez@amd.com        {
38411308Santhony.gutierrez@amd.com            private:
38511308Santhony.gutierrez@amd.com                GpuTLB *tlb;
38611308Santhony.gutierrez@amd.com                Addr virtPageAddr;
38711308Santhony.gutierrez@amd.com                /**
38811308Santhony.gutierrez@amd.com                 * outcome can be TLB_HIT, TLB_MISS, or PAGE_WALK
38911308Santhony.gutierrez@amd.com                 */
39011308Santhony.gutierrez@amd.com                tlbOutcome outcome;
39111308Santhony.gutierrez@amd.com                PacketPtr pkt;
39211308Santhony.gutierrez@amd.com
39311308Santhony.gutierrez@amd.com            public:
39411308Santhony.gutierrez@amd.com                TLBEvent(GpuTLB *_tlb, Addr _addr, tlbOutcome outcome,
39511308Santhony.gutierrez@amd.com                        PacketPtr _pkt);
39611308Santhony.gutierrez@amd.com
39711308Santhony.gutierrez@amd.com                void process();
39811308Santhony.gutierrez@amd.com                const char *description() const;
39911308Santhony.gutierrez@amd.com
40011308Santhony.gutierrez@amd.com                // updateOutcome updates the tlbOutcome of a TLBEvent
40111308Santhony.gutierrez@amd.com                void updateOutcome(tlbOutcome _outcome);
40211308Santhony.gutierrez@amd.com                Addr getTLBEventVaddr();
40311308Santhony.gutierrez@amd.com        };
40411308Santhony.gutierrez@amd.com
40511308Santhony.gutierrez@amd.com        std::unordered_map<Addr, TLBEvent*> translationReturnEvent;
40611308Santhony.gutierrez@amd.com
40711308Santhony.gutierrez@amd.com        // this FIFO queue keeps track of the virt. page addresses
40811308Santhony.gutierrez@amd.com        // that are pending cleanup
40911308Santhony.gutierrez@amd.com        std::queue<Addr> cleanupQueue;
41011308Santhony.gutierrez@amd.com
41111308Santhony.gutierrez@amd.com        // the cleanupEvent is scheduled after a TLBEvent triggers in order to
41211308Santhony.gutierrez@amd.com        // free memory and do the required clean-up
41311308Santhony.gutierrez@amd.com        void cleanup();
41411308Santhony.gutierrez@amd.com
41512085Sspwilson2@wisc.edu        EventFunctionWrapper cleanupEvent;
41611308Santhony.gutierrez@amd.com
41711308Santhony.gutierrez@amd.com        /**
41811308Santhony.gutierrez@amd.com         * This hash map will use the virtual page address as a key
41911308Santhony.gutierrez@amd.com         * and will keep track of total number of accesses per page
42011308Santhony.gutierrez@amd.com         */
42111308Santhony.gutierrez@amd.com
42211308Santhony.gutierrez@amd.com        struct AccessInfo
42311308Santhony.gutierrez@amd.com        {
42411308Santhony.gutierrez@amd.com            unsigned int lastTimeAccessed; // last access to this page
42511308Santhony.gutierrez@amd.com            unsigned int accessesPerPage;
42611308Santhony.gutierrez@amd.com            // need to divide it by accessesPerPage at the end
42711308Santhony.gutierrez@amd.com            unsigned int totalReuseDistance;
42811308Santhony.gutierrez@amd.com
42911308Santhony.gutierrez@amd.com            /**
43011308Santhony.gutierrez@amd.com             * The field below will help us compute the access distance,
43111308Santhony.gutierrez@amd.com             * that is the number of (coalesced) TLB accesses that
43211308Santhony.gutierrez@amd.com             * happened in between each access to this page
43311308Santhony.gutierrez@amd.com             *
43411308Santhony.gutierrez@amd.com             * localTLBAccesses[x] is the value of localTLBNumAccesses
43511308Santhony.gutierrez@amd.com             * when the page <Addr> was accessed for the <x>th time
43611308Santhony.gutierrez@amd.com             */
43711308Santhony.gutierrez@amd.com            std::vector<unsigned int> localTLBAccesses;
43811308Santhony.gutierrez@amd.com            unsigned int sumDistance;
43911308Santhony.gutierrez@amd.com            unsigned int meanDistance;
44011308Santhony.gutierrez@amd.com        };
44111308Santhony.gutierrez@amd.com
44211308Santhony.gutierrez@amd.com        typedef std::unordered_map<Addr, AccessInfo> AccessPatternTable;
44311308Santhony.gutierrez@amd.com        AccessPatternTable TLBFootprint;
44411308Santhony.gutierrez@amd.com
44511308Santhony.gutierrez@amd.com        // Called at the end of simulation to dump page access stats.
44611308Santhony.gutierrez@amd.com        void exitCallback();
44711308Santhony.gutierrez@amd.com
44812085Sspwilson2@wisc.edu        EventFunctionWrapper exitEvent;
44911308Santhony.gutierrez@amd.com    };
45011308Santhony.gutierrez@amd.com}
45111308Santhony.gutierrez@amd.com
45211308Santhony.gutierrez@amd.com#endif // __GPU_TLB_HH__
453