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 __TLB_COALESCER_HH__
3711308Santhony.gutierrez@amd.com#define __TLB_COALESCER_HH__
3811308Santhony.gutierrez@amd.com
3911308Santhony.gutierrez@amd.com#include <list>
4011308Santhony.gutierrez@amd.com#include <queue>
4111308Santhony.gutierrez@amd.com#include <string>
4211308Santhony.gutierrez@amd.com#include <vector>
4311308Santhony.gutierrez@amd.com
4411308Santhony.gutierrez@amd.com#include "arch/generic/tlb.hh"
4511308Santhony.gutierrez@amd.com#include "arch/isa.hh"
4611308Santhony.gutierrez@amd.com#include "arch/isa_traits.hh"
4711308Santhony.gutierrez@amd.com#include "arch/x86/pagetable.hh"
4811308Santhony.gutierrez@amd.com#include "arch/x86/regs/segment.hh"
4912334Sgabeblack@google.com#include "base/logging.hh"
5011308Santhony.gutierrez@amd.com#include "base/statistics.hh"
5111308Santhony.gutierrez@amd.com#include "gpu-compute/gpu_tlb.hh"
5211308Santhony.gutierrez@amd.com#include "mem/port.hh"
5311308Santhony.gutierrez@amd.com#include "mem/request.hh"
5411308Santhony.gutierrez@amd.com#include "params/TLBCoalescer.hh"
5513892Sgabeblack@google.com#include "sim/clocked_object.hh"
5611308Santhony.gutierrez@amd.com
5711308Santhony.gutierrez@amd.comclass BaseTLB;
5811308Santhony.gutierrez@amd.comclass Packet;
5911308Santhony.gutierrez@amd.comclass ThreadContext;
6011308Santhony.gutierrez@amd.com
6111308Santhony.gutierrez@amd.com/**
6213892Sgabeblack@google.com * The TLBCoalescer is a ClockedObject sitting on the front side (CPUSide) of
6311308Santhony.gutierrez@amd.com * each TLB. It receives packets and issues coalesced requests to the
6411308Santhony.gutierrez@amd.com * TLB below it. It controls how requests are coalesced (the rules)
6511308Santhony.gutierrez@amd.com * and the permitted number of TLB probes per cycle (i.e., how many
6611308Santhony.gutierrez@amd.com * coalesced requests it feeds the TLB per cycle).
6711308Santhony.gutierrez@amd.com */
6813892Sgabeblack@google.comclass TLBCoalescer : public ClockedObject
6911308Santhony.gutierrez@amd.com{
7011308Santhony.gutierrez@amd.com   protected:
7111308Santhony.gutierrez@amd.com    // TLB clock: will inherit clock from shader's clock period in terms
7211308Santhony.gutierrez@amd.com    // of nuber of ticks of curTime (aka global simulation clock)
7311308Santhony.gutierrez@amd.com    // The assignment of TLB clock from shader clock is done in the
7411308Santhony.gutierrez@amd.com    // python config files.
7511308Santhony.gutierrez@amd.com    int clock;
7611308Santhony.gutierrez@amd.com
7711308Santhony.gutierrez@amd.com  public:
7811308Santhony.gutierrez@amd.com    typedef TLBCoalescerParams Params;
7911308Santhony.gutierrez@amd.com    TLBCoalescer(const Params *p);
8011308Santhony.gutierrez@amd.com    ~TLBCoalescer() { }
8111308Santhony.gutierrez@amd.com
8211308Santhony.gutierrez@amd.com    // Number of TLB probes per cycle. Parameterizable - default 2.
8311308Santhony.gutierrez@amd.com    int TLBProbesPerCycle;
8411308Santhony.gutierrez@amd.com
8511308Santhony.gutierrez@amd.com    // Consider coalescing across that many ticks.
8611308Santhony.gutierrez@amd.com    // Paraemterizable - default 1.
8711308Santhony.gutierrez@amd.com    int coalescingWindow;
8811308Santhony.gutierrez@amd.com
8911308Santhony.gutierrez@amd.com    // Each coalesced request consists of multiple packets
9011308Santhony.gutierrez@amd.com    // that all fall within the same virtual page
9111308Santhony.gutierrez@amd.com    typedef std::vector<PacketPtr> coalescedReq;
9211308Santhony.gutierrez@amd.com
9311308Santhony.gutierrez@amd.com    // disables coalescing when true
9411308Santhony.gutierrez@amd.com    bool disableCoalescing;
9511308Santhony.gutierrez@amd.com
9611308Santhony.gutierrez@amd.com    /*
9711308Santhony.gutierrez@amd.com     * This is a hash map with <tick_index> as a key.
9811308Santhony.gutierrez@amd.com     * It contains a vector of coalescedReqs per <tick_index>.
9911308Santhony.gutierrez@amd.com     * Requests are buffered here until they can be issued to
10011308Santhony.gutierrez@amd.com     * the TLB, at which point they are copied to the
10111308Santhony.gutierrez@amd.com     * issuedTranslationsTable hash map.
10211308Santhony.gutierrez@amd.com     *
10311308Santhony.gutierrez@amd.com     * In terms of coalescing, we coalesce requests in a given
10411308Santhony.gutierrez@amd.com     * window of x cycles by using tick_index = issueTime/x as a
10511308Santhony.gutierrez@amd.com     * key, where x = coalescingWindow. issueTime is the issueTime
10611308Santhony.gutierrez@amd.com     * of the pkt from the ComputeUnit's perspective, but another
10711308Santhony.gutierrez@amd.com     * option is to change it to curTick(), so we coalesce based
10811308Santhony.gutierrez@amd.com     * on the receive time.
10911308Santhony.gutierrez@amd.com     */
11011308Santhony.gutierrez@amd.com    typedef std::unordered_map<int64_t, std::vector<coalescedReq>> CoalescingFIFO;
11111308Santhony.gutierrez@amd.com
11211308Santhony.gutierrez@amd.com    CoalescingFIFO coalescerFIFO;
11311308Santhony.gutierrez@amd.com
11411308Santhony.gutierrez@amd.com    /*
11511308Santhony.gutierrez@amd.com     * issuedTranslationsTabler: a hash_map indexed by virtual page
11611308Santhony.gutierrez@amd.com     * address. Each hash_map entry has a vector of PacketPtr associated
11711308Santhony.gutierrez@amd.com     * with it denoting the different packets that share an outstanding
11811308Santhony.gutierrez@amd.com     * coalesced translation request for the same virtual page.
11911308Santhony.gutierrez@amd.com     *
12011308Santhony.gutierrez@amd.com     * The rules that determine which requests we can coalesce are
12111308Santhony.gutierrez@amd.com     * specified in the canCoalesce() method.
12211308Santhony.gutierrez@amd.com     */
12311308Santhony.gutierrez@amd.com    typedef std::unordered_map<Addr, coalescedReq> CoalescingTable;
12411308Santhony.gutierrez@amd.com
12511308Santhony.gutierrez@amd.com    CoalescingTable issuedTranslationsTable;
12611308Santhony.gutierrez@amd.com
12711308Santhony.gutierrez@amd.com    // number of packets the coalescer receives
12811308Santhony.gutierrez@amd.com    Stats::Scalar uncoalescedAccesses;
12911308Santhony.gutierrez@amd.com    // number packets the coalescer send to the TLB
13011308Santhony.gutierrez@amd.com    Stats::Scalar coalescedAccesses;
13111308Santhony.gutierrez@amd.com
13211308Santhony.gutierrez@amd.com    // Number of cycles the coalesced requests spend waiting in
13311308Santhony.gutierrez@amd.com    // coalescerFIFO. For each packet the coalescer receives we take into
13411308Santhony.gutierrez@amd.com    // account the number of all uncoalesced requests this pkt "represents"
13511308Santhony.gutierrez@amd.com    Stats::Scalar queuingCycles;
13611308Santhony.gutierrez@amd.com
13711308Santhony.gutierrez@amd.com    // On average how much time a request from the
13811308Santhony.gutierrez@amd.com    // uncoalescedAccesses that reaches the TLB
13911308Santhony.gutierrez@amd.com    // spends waiting?
14011308Santhony.gutierrez@amd.com    Stats::Scalar localqueuingCycles;
14111308Santhony.gutierrez@amd.com    // localqueuingCycles/uncoalescedAccesses
14211308Santhony.gutierrez@amd.com    Stats::Formula localLatency;
14311308Santhony.gutierrez@amd.com
14411308Santhony.gutierrez@amd.com    bool canCoalesce(PacketPtr pkt1, PacketPtr pkt2);
14511308Santhony.gutierrez@amd.com    void updatePhysAddresses(PacketPtr pkt);
14614292Sjqu32@wisc.edu    void regStats() override;
14711308Santhony.gutierrez@amd.com
14811308Santhony.gutierrez@amd.com    // Clock related functions. Maps to-and-from
14911308Santhony.gutierrez@amd.com    // Simulation ticks and object clocks.
15011308Santhony.gutierrez@amd.com    Tick frequency() const { return SimClock::Frequency / clock; }
15111308Santhony.gutierrez@amd.com    Tick ticks(int numCycles) const { return (Tick)clock * numCycles; }
15211308Santhony.gutierrez@amd.com    Tick curCycle() const { return curTick() / clock; }
15311308Santhony.gutierrez@amd.com    Tick tickToCycles(Tick val) const { return val / clock;}
15411308Santhony.gutierrez@amd.com
15511308Santhony.gutierrez@amd.com    class CpuSidePort : public SlavePort
15611308Santhony.gutierrez@amd.com    {
15711308Santhony.gutierrez@amd.com      public:
15811308Santhony.gutierrez@amd.com        CpuSidePort(const std::string &_name, TLBCoalescer *tlb_coalescer,
15911308Santhony.gutierrez@amd.com                    PortID _index)
16011308Santhony.gutierrez@amd.com            : SlavePort(_name, tlb_coalescer), coalescer(tlb_coalescer),
16111308Santhony.gutierrez@amd.com              index(_index) { }
16211308Santhony.gutierrez@amd.com
16311308Santhony.gutierrez@amd.com      protected:
16411308Santhony.gutierrez@amd.com        TLBCoalescer *coalescer;
16511308Santhony.gutierrez@amd.com        int index;
16611308Santhony.gutierrez@amd.com
16711308Santhony.gutierrez@amd.com        virtual bool recvTimingReq(PacketPtr pkt);
16811308Santhony.gutierrez@amd.com        virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
16911308Santhony.gutierrez@amd.com        virtual void recvFunctional(PacketPtr pkt);
17011308Santhony.gutierrez@amd.com        virtual void recvRangeChange() { }
17111308Santhony.gutierrez@amd.com        virtual void recvReqRetry();
17211308Santhony.gutierrez@amd.com
17311308Santhony.gutierrez@amd.com        virtual void
17411308Santhony.gutierrez@amd.com        recvRespRetry()
17511308Santhony.gutierrez@amd.com        {
17611308Santhony.gutierrez@amd.com            fatal("recvRespRetry() is not implemented in the TLB coalescer.\n");
17711308Santhony.gutierrez@amd.com        }
17811308Santhony.gutierrez@amd.com
17911308Santhony.gutierrez@amd.com        virtual AddrRangeList getAddrRanges() const;
18011308Santhony.gutierrez@amd.com    };
18111308Santhony.gutierrez@amd.com
18211308Santhony.gutierrez@amd.com    class MemSidePort : public MasterPort
18311308Santhony.gutierrez@amd.com    {
18411308Santhony.gutierrez@amd.com      public:
18511308Santhony.gutierrez@amd.com        MemSidePort(const std::string &_name, TLBCoalescer *tlb_coalescer,
18611308Santhony.gutierrez@amd.com                    PortID _index)
18711308Santhony.gutierrez@amd.com            : MasterPort(_name, tlb_coalescer), coalescer(tlb_coalescer),
18811308Santhony.gutierrez@amd.com              index(_index) { }
18911308Santhony.gutierrez@amd.com
19011308Santhony.gutierrez@amd.com        std::deque<PacketPtr> retries;
19111308Santhony.gutierrez@amd.com
19211308Santhony.gutierrez@amd.com      protected:
19311308Santhony.gutierrez@amd.com        TLBCoalescer *coalescer;
19411308Santhony.gutierrez@amd.com        int index;
19511308Santhony.gutierrez@amd.com
19611308Santhony.gutierrez@amd.com        virtual bool recvTimingResp(PacketPtr pkt);
19711308Santhony.gutierrez@amd.com        virtual Tick recvAtomic(PacketPtr pkt) { return 0; }
19811308Santhony.gutierrez@amd.com        virtual void recvFunctional(PacketPtr pkt);
19911308Santhony.gutierrez@amd.com        virtual void recvRangeChange() { }
20011308Santhony.gutierrez@amd.com        virtual void recvReqRetry();
20111308Santhony.gutierrez@amd.com
20211308Santhony.gutierrez@amd.com        virtual void
20311308Santhony.gutierrez@amd.com        recvRespRetry()
20411308Santhony.gutierrez@amd.com        {
20511308Santhony.gutierrez@amd.com            fatal("recvRespRetry() not implemented in TLB coalescer");
20611308Santhony.gutierrez@amd.com        }
20711308Santhony.gutierrez@amd.com    };
20811308Santhony.gutierrez@amd.com
20911308Santhony.gutierrez@amd.com    // Coalescer slave ports on the cpu Side
21011308Santhony.gutierrez@amd.com    std::vector<CpuSidePort*> cpuSidePort;
21111308Santhony.gutierrez@amd.com    // Coalescer master ports on the memory side
21211308Santhony.gutierrez@amd.com    std::vector<MemSidePort*> memSidePort;
21311308Santhony.gutierrez@amd.com
21413784Sgabeblack@google.com    Port &getPort(const std::string &if_name,
21513784Sgabeblack@google.com                  PortID idx=InvalidPortID) override;
21611308Santhony.gutierrez@amd.com
21712126Sspwilson2@wisc.edu    void processProbeTLBEvent();
21812126Sspwilson2@wisc.edu    /// This event issues the TLB probes
21912126Sspwilson2@wisc.edu    EventFunctionWrapper probeTLBEvent;
22011308Santhony.gutierrez@amd.com
22112126Sspwilson2@wisc.edu    void processCleanupEvent();
22212126Sspwilson2@wisc.edu    /// The cleanupEvent is scheduled after a TLBEvent triggers
22312126Sspwilson2@wisc.edu    /// in order to free memory and do the required clean-up
22412126Sspwilson2@wisc.edu    EventFunctionWrapper cleanupEvent;
22511308Santhony.gutierrez@amd.com
22611308Santhony.gutierrez@amd.com    // this FIFO queue keeps track of the virt. page
22711308Santhony.gutierrez@amd.com    // addresses that are pending cleanup
22811308Santhony.gutierrez@amd.com    std::queue<Addr> cleanupQueue;
22911308Santhony.gutierrez@amd.com};
23011308Santhony.gutierrez@amd.com
23111308Santhony.gutierrez@amd.com#endif // __TLB_COALESCER_HH__
232