dram_ctrl.hh revision 11168
19243SN/A/*
210889Sandreas.hansson@arm.com * Copyright (c) 2012-2015 ARM Limited
39243SN/A * All rights reserved
49243SN/A *
59243SN/A * The license below extends only to copyright in the software and shall
69243SN/A * not be construed as granting a license to any other intellectual
79243SN/A * property including but not limited to intellectual property relating
89243SN/A * to a hardware implementation of the functionality of the software
99243SN/A * licensed hereunder.  You may use the software subject to the license
109243SN/A * terms below provided that you ensure that this notice is replicated
119243SN/A * unmodified and in its entirety in all distributions of the software,
129243SN/A * modified or unmodified, in source code or in binary form.
139243SN/A *
149831SN/A * Copyright (c) 2013 Amin Farmahini-Farahani
159831SN/A * All rights reserved.
169831SN/A *
179243SN/A * Redistribution and use in source and binary forms, with or without
189243SN/A * modification, are permitted provided that the following conditions are
199243SN/A * met: redistributions of source code must retain the above copyright
209243SN/A * notice, this list of conditions and the following disclaimer;
219243SN/A * redistributions in binary form must reproduce the above copyright
229243SN/A * notice, this list of conditions and the following disclaimer in the
239243SN/A * documentation and/or other materials provided with the distribution;
249243SN/A * neither the name of the copyright holders nor the names of its
259243SN/A * contributors may be used to endorse or promote products derived from
269243SN/A * this software without specific prior written permission.
279243SN/A *
289243SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
299243SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
309243SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
319243SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
329243SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
339243SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
349243SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
359243SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
369243SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
379243SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
389243SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
399243SN/A *
409243SN/A * Authors: Andreas Hansson
419243SN/A *          Ani Udipi
429967SN/A *          Neha Agarwal
4310618SOmar.Naji@arm.com *          Omar Naji
449243SN/A */
459243SN/A
469243SN/A/**
479243SN/A * @file
4810146Sandreas.hansson@arm.com * DRAMCtrl declaration
499243SN/A */
509243SN/A
5110146Sandreas.hansson@arm.com#ifndef __MEM_DRAM_CTRL_HH__
5210146Sandreas.hansson@arm.com#define __MEM_DRAM_CTRL_HH__
539243SN/A
549488SN/A#include <deque>
5510618SOmar.Naji@arm.com#include <string>
5610889Sandreas.hansson@arm.com#include <unordered_set>
579488SN/A
589243SN/A#include "base/statistics.hh"
599243SN/A#include "enums/AddrMap.hh"
609243SN/A#include "enums/MemSched.hh"
619243SN/A#include "enums/PageManage.hh"
629243SN/A#include "mem/abstract_mem.hh"
639243SN/A#include "mem/qport.hh"
6410146Sandreas.hansson@arm.com#include "params/DRAMCtrl.hh"
659243SN/A#include "sim/eventq.hh"
6610432SOmar.Naji@arm.com#include "mem/drampower.hh"
679243SN/A
689243SN/A/**
6910287Sandreas.hansson@arm.com * The DRAM controller is a single-channel memory controller capturing
7010287Sandreas.hansson@arm.com * the most important timing constraints associated with a
7110287Sandreas.hansson@arm.com * contemporary DRAM. For multi-channel memory systems, the controller
7210287Sandreas.hansson@arm.com * is combined with a crossbar model, with the channel address
7310287Sandreas.hansson@arm.com * interleaving taking part in the crossbar.
749243SN/A *
7510287Sandreas.hansson@arm.com * As a basic design principle, this controller
7610287Sandreas.hansson@arm.com * model is not cycle callable, but instead uses events to: 1) decide
7710287Sandreas.hansson@arm.com * when new decisions can be made, 2) when resources become available,
7810287Sandreas.hansson@arm.com * 3) when things are to be considered done, and 4) when to send
7910287Sandreas.hansson@arm.com * things back. Through these simple principles, the model delivers
8010287Sandreas.hansson@arm.com * high performance, and lots of flexibility, allowing users to
8110287Sandreas.hansson@arm.com * evaluate the system impact of a wide range of memory technologies,
8210287Sandreas.hansson@arm.com * such as DDR3/4, LPDDR2/3/4, WideIO1/2, HBM and HMC.
8310287Sandreas.hansson@arm.com *
8410287Sandreas.hansson@arm.com * For more details, please see Hansson et al, "Simulating DRAM
8510287Sandreas.hansson@arm.com * controllers for future system architecture exploration",
8610287Sandreas.hansson@arm.com * Proc. ISPASS, 2014. If you use this model as part of your research
8710287Sandreas.hansson@arm.com * please cite the paper.
889243SN/A */
8910146Sandreas.hansson@arm.comclass DRAMCtrl : public AbstractMemory
909243SN/A{
919243SN/A
929243SN/A  private:
939243SN/A
949243SN/A    // For now, make use of a queued slave port to avoid dealing with
959243SN/A    // flow control for the responses being sent back
969243SN/A    class MemoryPort : public QueuedSlavePort
979243SN/A    {
989243SN/A
9910713Sandreas.hansson@arm.com        RespPacketQueue queue;
10010146Sandreas.hansson@arm.com        DRAMCtrl& memory;
1019243SN/A
1029243SN/A      public:
1039243SN/A
10410146Sandreas.hansson@arm.com        MemoryPort(const std::string& name, DRAMCtrl& _memory);
1059243SN/A
1069243SN/A      protected:
1079243SN/A
1089243SN/A        Tick recvAtomic(PacketPtr pkt);
1099243SN/A
1109243SN/A        void recvFunctional(PacketPtr pkt);
1119243SN/A
1129243SN/A        bool recvTimingReq(PacketPtr);
1139243SN/A
1149243SN/A        virtual AddrRangeList getAddrRanges() const;
1159243SN/A
1169243SN/A    };
1179243SN/A
1189243SN/A    /**
1199243SN/A     * Our incoming port, for a multi-ported controller add a crossbar
1209243SN/A     * in front of it
1219243SN/A     */
1229243SN/A    MemoryPort port;
1239243SN/A
1249243SN/A    /**
12510619Sandreas.hansson@arm.com     * Remeber if the memory system is in timing mode
12610619Sandreas.hansson@arm.com     */
12710619Sandreas.hansson@arm.com    bool isTimingMode;
12810619Sandreas.hansson@arm.com
12910619Sandreas.hansson@arm.com    /**
1309243SN/A     * Remember if we have to retry a request when available.
1319243SN/A     */
1329243SN/A    bool retryRdReq;
1339243SN/A    bool retryWrReq;
1349243SN/A
1359243SN/A    /**
13610206Sandreas.hansson@arm.com     * Bus state used to control the read/write switching and drive
13710206Sandreas.hansson@arm.com     * the scheduling of the next request.
1389243SN/A     */
13910206Sandreas.hansson@arm.com    enum BusState {
14010206Sandreas.hansson@arm.com        READ = 0,
14110206Sandreas.hansson@arm.com        READ_TO_WRITE,
14210206Sandreas.hansson@arm.com        WRITE,
14310206Sandreas.hansson@arm.com        WRITE_TO_READ
14410206Sandreas.hansson@arm.com    };
14510206Sandreas.hansson@arm.com
14610206Sandreas.hansson@arm.com    BusState busState;
1479243SN/A
1489243SN/A    /**
14910210Sandreas.hansson@arm.com     * A basic class to track the bank state, i.e. what row is
15010210Sandreas.hansson@arm.com     * currently open (if any), when is the bank free to accept a new
15110211Sandreas.hansson@arm.com     * column (read/write) command, when can it be precharged, and
15210211Sandreas.hansson@arm.com     * when can it be activated.
15310210Sandreas.hansson@arm.com     *
15410210Sandreas.hansson@arm.com     * The bank also keeps track of how many bytes have been accessed
15510210Sandreas.hansson@arm.com     * in the open row since it was opened.
1569243SN/A     */
1579243SN/A    class Bank
1589243SN/A    {
1599243SN/A
1609243SN/A      public:
1619243SN/A
16210207Sandreas.hansson@arm.com        static const uint32_t NO_ROW = -1;
1639243SN/A
1649243SN/A        uint32_t openRow;
16510246Sandreas.hansson@arm.com        uint8_t bank;
16610394Swendy.elsasser@arm.com        uint8_t bankgr;
1679243SN/A
16810211Sandreas.hansson@arm.com        Tick colAllowedAt;
16910210Sandreas.hansson@arm.com        Tick preAllowedAt;
1709969SN/A        Tick actAllowedAt;
1719243SN/A
17210141SN/A        uint32_t rowAccesses;
1739727SN/A        uint32_t bytesAccessed;
1749727SN/A
1759727SN/A        Bank() :
17610618SOmar.Naji@arm.com            openRow(NO_ROW), bank(0), bankgr(0),
17710246Sandreas.hansson@arm.com            colAllowedAt(0), preAllowedAt(0), actAllowedAt(0),
17810141SN/A            rowAccesses(0), bytesAccessed(0)
1799243SN/A        { }
1809243SN/A    };
1819243SN/A
18210618SOmar.Naji@arm.com
18310618SOmar.Naji@arm.com    /**
18410618SOmar.Naji@arm.com     * Rank class includes a vector of banks. Refresh and Power state
18510618SOmar.Naji@arm.com     * machines are defined per rank. Events required to change the
18610618SOmar.Naji@arm.com     * state of the refresh and power state machine are scheduled per
18710618SOmar.Naji@arm.com     * rank. This class allows the implementation of rank-wise refresh
18810618SOmar.Naji@arm.com     * and rank-wise power-down.
18910618SOmar.Naji@arm.com     */
19010618SOmar.Naji@arm.com    class Rank : public EventManager
19110618SOmar.Naji@arm.com    {
19210618SOmar.Naji@arm.com
19310618SOmar.Naji@arm.com      private:
19410618SOmar.Naji@arm.com
19510618SOmar.Naji@arm.com        /**
19610618SOmar.Naji@arm.com         * The power state captures the different operational states of
19710618SOmar.Naji@arm.com         * the DRAM and interacts with the bus read/write state machine,
19810618SOmar.Naji@arm.com         * and the refresh state machine. In the idle state all banks are
19910618SOmar.Naji@arm.com         * precharged. From there we either go to an auto refresh (as
20010618SOmar.Naji@arm.com         * determined by the refresh state machine), or to a precharge
20110618SOmar.Naji@arm.com         * power down mode. From idle the memory can also go to the active
20210618SOmar.Naji@arm.com         * state (with one or more banks active), and in turn from there
20310618SOmar.Naji@arm.com         * to active power down. At the moment we do not capture the deep
20410618SOmar.Naji@arm.com         * power down and self-refresh state.
20510618SOmar.Naji@arm.com         */
20610618SOmar.Naji@arm.com        enum PowerState {
20710618SOmar.Naji@arm.com            PWR_IDLE = 0,
20810618SOmar.Naji@arm.com            PWR_REF,
20910618SOmar.Naji@arm.com            PWR_PRE_PDN,
21010618SOmar.Naji@arm.com            PWR_ACT,
21110618SOmar.Naji@arm.com            PWR_ACT_PDN
21210618SOmar.Naji@arm.com        };
21310618SOmar.Naji@arm.com
21410618SOmar.Naji@arm.com        /**
21510618SOmar.Naji@arm.com         * The refresh state is used to control the progress of the
21610618SOmar.Naji@arm.com         * refresh scheduling. When normal operation is in progress the
21710618SOmar.Naji@arm.com         * refresh state is idle. From there, it progresses to the refresh
21810618SOmar.Naji@arm.com         * drain state once tREFI has passed. The refresh drain state
21910618SOmar.Naji@arm.com         * captures the DRAM row active state, as it will stay there until
22010618SOmar.Naji@arm.com         * all ongoing accesses complete. Thereafter all banks are
22110618SOmar.Naji@arm.com         * precharged, and lastly, the DRAM is refreshed.
22210618SOmar.Naji@arm.com         */
22310618SOmar.Naji@arm.com        enum RefreshState {
22410618SOmar.Naji@arm.com            REF_IDLE = 0,
22510618SOmar.Naji@arm.com            REF_DRAIN,
22610618SOmar.Naji@arm.com            REF_PRE,
22710618SOmar.Naji@arm.com            REF_RUN
22810618SOmar.Naji@arm.com        };
22910618SOmar.Naji@arm.com
23010618SOmar.Naji@arm.com        /**
23110618SOmar.Naji@arm.com         * A reference to the parent DRAMCtrl instance
23210618SOmar.Naji@arm.com         */
23310618SOmar.Naji@arm.com        DRAMCtrl& memory;
23410618SOmar.Naji@arm.com
23510618SOmar.Naji@arm.com        /**
23610618SOmar.Naji@arm.com         * Since we are taking decisions out of order, we need to keep
23710618SOmar.Naji@arm.com         * track of what power transition is happening at what time, such
23810618SOmar.Naji@arm.com         * that we can go back in time and change history. For example, if
23910618SOmar.Naji@arm.com         * we precharge all banks and schedule going to the idle state, we
24010618SOmar.Naji@arm.com         * might at a later point decide to activate a bank before the
24110618SOmar.Naji@arm.com         * transition to idle would have taken place.
24210618SOmar.Naji@arm.com         */
24310618SOmar.Naji@arm.com        PowerState pwrStateTrans;
24410618SOmar.Naji@arm.com
24510618SOmar.Naji@arm.com        /**
24610618SOmar.Naji@arm.com         * Current power state.
24710618SOmar.Naji@arm.com         */
24810618SOmar.Naji@arm.com        PowerState pwrState;
24910618SOmar.Naji@arm.com
25010618SOmar.Naji@arm.com        /**
25110618SOmar.Naji@arm.com         * Track when we transitioned to the current power state
25210618SOmar.Naji@arm.com         */
25310618SOmar.Naji@arm.com        Tick pwrStateTick;
25410618SOmar.Naji@arm.com
25510618SOmar.Naji@arm.com        /**
25610618SOmar.Naji@arm.com         * current refresh state
25710618SOmar.Naji@arm.com         */
25810618SOmar.Naji@arm.com        RefreshState refreshState;
25910618SOmar.Naji@arm.com
26010618SOmar.Naji@arm.com        /**
26110618SOmar.Naji@arm.com         * Keep track of when a refresh is due.
26210618SOmar.Naji@arm.com         */
26310618SOmar.Naji@arm.com        Tick refreshDueAt;
26410618SOmar.Naji@arm.com
26510618SOmar.Naji@arm.com        /*
26610618SOmar.Naji@arm.com         * Command energies
26710618SOmar.Naji@arm.com         */
26810618SOmar.Naji@arm.com        Stats::Scalar actEnergy;
26910618SOmar.Naji@arm.com        Stats::Scalar preEnergy;
27010618SOmar.Naji@arm.com        Stats::Scalar readEnergy;
27110618SOmar.Naji@arm.com        Stats::Scalar writeEnergy;
27210618SOmar.Naji@arm.com        Stats::Scalar refreshEnergy;
27310618SOmar.Naji@arm.com
27410618SOmar.Naji@arm.com        /*
27510618SOmar.Naji@arm.com         * Active Background Energy
27610618SOmar.Naji@arm.com         */
27710618SOmar.Naji@arm.com        Stats::Scalar actBackEnergy;
27810618SOmar.Naji@arm.com
27910618SOmar.Naji@arm.com        /*
28010618SOmar.Naji@arm.com         * Precharge Background Energy
28110618SOmar.Naji@arm.com         */
28210618SOmar.Naji@arm.com        Stats::Scalar preBackEnergy;
28310618SOmar.Naji@arm.com
28410618SOmar.Naji@arm.com        Stats::Scalar totalEnergy;
28510618SOmar.Naji@arm.com        Stats::Scalar averagePower;
28610618SOmar.Naji@arm.com
28710618SOmar.Naji@arm.com        /**
28810618SOmar.Naji@arm.com         * Track time spent in each power state.
28910618SOmar.Naji@arm.com         */
29010618SOmar.Naji@arm.com        Stats::Vector pwrStateTime;
29110618SOmar.Naji@arm.com
29210618SOmar.Naji@arm.com        /**
29310618SOmar.Naji@arm.com         * Function to update Power Stats
29410618SOmar.Naji@arm.com         */
29510618SOmar.Naji@arm.com        void updatePowerStats();
29610618SOmar.Naji@arm.com
29710618SOmar.Naji@arm.com        /**
29810618SOmar.Naji@arm.com         * Schedule a power state transition in the future, and
29910618SOmar.Naji@arm.com         * potentially override an already scheduled transition.
30010618SOmar.Naji@arm.com         *
30110618SOmar.Naji@arm.com         * @param pwr_state Power state to transition to
30210618SOmar.Naji@arm.com         * @param tick Tick when transition should take place
30310618SOmar.Naji@arm.com         */
30410618SOmar.Naji@arm.com        void schedulePowerEvent(PowerState pwr_state, Tick tick);
30510618SOmar.Naji@arm.com
30610618SOmar.Naji@arm.com      public:
30710618SOmar.Naji@arm.com
30810618SOmar.Naji@arm.com        /**
30910618SOmar.Naji@arm.com         * Current Rank index
31010618SOmar.Naji@arm.com         */
31110618SOmar.Naji@arm.com        uint8_t rank;
31210618SOmar.Naji@arm.com
31310618SOmar.Naji@arm.com        /**
31410618SOmar.Naji@arm.com         * One DRAMPower instance per rank
31510618SOmar.Naji@arm.com         */
31610618SOmar.Naji@arm.com        DRAMPower power;
31710618SOmar.Naji@arm.com
31810618SOmar.Naji@arm.com        /**
31910618SOmar.Naji@arm.com         * Vector of Banks. Each rank is made of several devices which in
32010618SOmar.Naji@arm.com         * term are made from several banks.
32110618SOmar.Naji@arm.com         */
32210618SOmar.Naji@arm.com        std::vector<Bank> banks;
32310618SOmar.Naji@arm.com
32410618SOmar.Naji@arm.com        /**
32510618SOmar.Naji@arm.com         *  To track number of banks which are currently active for
32610618SOmar.Naji@arm.com         *  this rank.
32710618SOmar.Naji@arm.com         */
32810618SOmar.Naji@arm.com        unsigned int numBanksActive;
32910618SOmar.Naji@arm.com
33010618SOmar.Naji@arm.com        /** List to keep track of activate ticks */
33110618SOmar.Naji@arm.com        std::deque<Tick> actTicks;
33210618SOmar.Naji@arm.com
33310618SOmar.Naji@arm.com        Rank(DRAMCtrl& _memory, const DRAMCtrlParams* _p);
33410618SOmar.Naji@arm.com
33510618SOmar.Naji@arm.com        const std::string name() const
33610618SOmar.Naji@arm.com        {
33710618SOmar.Naji@arm.com            return csprintf("%s_%d", memory.name(), rank);
33810618SOmar.Naji@arm.com        }
33910618SOmar.Naji@arm.com
34010618SOmar.Naji@arm.com        /**
34110618SOmar.Naji@arm.com         * Kick off accounting for power and refresh states and
34210618SOmar.Naji@arm.com         * schedule initial refresh.
34310618SOmar.Naji@arm.com         *
34410618SOmar.Naji@arm.com         * @param ref_tick Tick for first refresh
34510618SOmar.Naji@arm.com         */
34610618SOmar.Naji@arm.com        void startup(Tick ref_tick);
34710618SOmar.Naji@arm.com
34810618SOmar.Naji@arm.com        /**
34910619Sandreas.hansson@arm.com         * Stop the refresh events.
35010619Sandreas.hansson@arm.com         */
35110619Sandreas.hansson@arm.com        void suspend();
35210619Sandreas.hansson@arm.com
35310619Sandreas.hansson@arm.com        /**
35410618SOmar.Naji@arm.com         * Check if the current rank is available for scheduling.
35510618SOmar.Naji@arm.com         *
35610618SOmar.Naji@arm.com         * @param Return true if the rank is idle from a refresh point of view
35710618SOmar.Naji@arm.com         */
35810618SOmar.Naji@arm.com        bool isAvailable() const { return refreshState == REF_IDLE; }
35910618SOmar.Naji@arm.com
36010618SOmar.Naji@arm.com        /**
36110618SOmar.Naji@arm.com         * Let the rank check if it was waiting for requests to drain
36210618SOmar.Naji@arm.com         * to allow it to transition states.
36310618SOmar.Naji@arm.com         */
36410618SOmar.Naji@arm.com        void checkDrainDone();
36510618SOmar.Naji@arm.com
36610618SOmar.Naji@arm.com        /*
36710618SOmar.Naji@arm.com         * Function to register Stats
36810618SOmar.Naji@arm.com         */
36910618SOmar.Naji@arm.com        void regStats();
37010618SOmar.Naji@arm.com
37110618SOmar.Naji@arm.com        void processActivateEvent();
37210618SOmar.Naji@arm.com        EventWrapper<Rank, &Rank::processActivateEvent>
37310618SOmar.Naji@arm.com        activateEvent;
37410618SOmar.Naji@arm.com
37510618SOmar.Naji@arm.com        void processPrechargeEvent();
37610618SOmar.Naji@arm.com        EventWrapper<Rank, &Rank::processPrechargeEvent>
37710618SOmar.Naji@arm.com        prechargeEvent;
37810618SOmar.Naji@arm.com
37910618SOmar.Naji@arm.com        void processRefreshEvent();
38010618SOmar.Naji@arm.com        EventWrapper<Rank, &Rank::processRefreshEvent>
38110618SOmar.Naji@arm.com        refreshEvent;
38210618SOmar.Naji@arm.com
38310618SOmar.Naji@arm.com        void processPowerEvent();
38410618SOmar.Naji@arm.com        EventWrapper<Rank, &Rank::processPowerEvent>
38510618SOmar.Naji@arm.com        powerEvent;
38610618SOmar.Naji@arm.com
38710618SOmar.Naji@arm.com    };
38810618SOmar.Naji@arm.com
3899243SN/A    /**
3909831SN/A     * A burst helper helps organize and manage a packet that is larger than
3919831SN/A     * the DRAM burst size. A system packet that is larger than the burst size
3929831SN/A     * is split into multiple DRAM packets and all those DRAM packets point to
3939831SN/A     * a single burst helper such that we know when the whole packet is served.
3949831SN/A     */
3959831SN/A    class BurstHelper {
3969831SN/A
3979831SN/A      public:
3989831SN/A
3999831SN/A        /** Number of DRAM bursts requred for a system packet **/
4009831SN/A        const unsigned int burstCount;
4019831SN/A
4029831SN/A        /** Number of DRAM bursts serviced so far for a system packet **/
4039831SN/A        unsigned int burstsServiced;
4049831SN/A
4059831SN/A        BurstHelper(unsigned int _burstCount)
4069831SN/A            : burstCount(_burstCount), burstsServiced(0)
40710618SOmar.Naji@arm.com        { }
4089831SN/A    };
4099831SN/A
4109831SN/A    /**
4119243SN/A     * A DRAM packet stores packets along with the timestamp of when
4129243SN/A     * the packet entered the queue, and also the decoded address.
4139243SN/A     */
4149243SN/A    class DRAMPacket {
4159243SN/A
4169243SN/A      public:
4179243SN/A
4189243SN/A        /** When did request enter the controller */
4199243SN/A        const Tick entryTime;
4209243SN/A
4219243SN/A        /** When will request leave the controller */
4229243SN/A        Tick readyTime;
4239243SN/A
4249243SN/A        /** This comes from the outside world */
4259243SN/A        const PacketPtr pkt;
4269243SN/A
4279966SN/A        const bool isRead;
4289966SN/A
4299243SN/A        /** Will be populated by address decoder */
4309243SN/A        const uint8_t rank;
4319967SN/A        const uint8_t bank;
43210245Sandreas.hansson@arm.com        const uint32_t row;
4339831SN/A
4349831SN/A        /**
4359967SN/A         * Bank id is calculated considering banks in all the ranks
4369967SN/A         * eg: 2 ranks each with 8 banks, then bankId = 0 --> rank0, bank0 and
4379967SN/A         * bankId = 8 --> rank1, bank0
4389967SN/A         */
4399967SN/A        const uint16_t bankId;
4409967SN/A
4419967SN/A        /**
4429831SN/A         * The starting address of the DRAM packet.
4439831SN/A         * This address could be unaligned to burst size boundaries. The
4449831SN/A         * reason is to keep the address offset so we can accurately check
4459831SN/A         * incoming read packets with packets in the write queue.
4469831SN/A         */
4479832SN/A        Addr addr;
4489831SN/A
4499831SN/A        /**
4509831SN/A         * The size of this dram packet in bytes
4519831SN/A         * It is always equal or smaller than DRAM burst size
4529831SN/A         */
4539832SN/A        unsigned int size;
4549831SN/A
4559831SN/A        /**
4569831SN/A         * A pointer to the BurstHelper if this DRAMPacket is a split packet
4579831SN/A         * If not a split packet (common case), this is set to NULL
4589831SN/A         */
4599831SN/A        BurstHelper* burstHelper;
4609967SN/A        Bank& bankRef;
46110618SOmar.Naji@arm.com        Rank& rankRef;
4629243SN/A
4639967SN/A        DRAMPacket(PacketPtr _pkt, bool is_read, uint8_t _rank, uint8_t _bank,
46410245Sandreas.hansson@arm.com                   uint32_t _row, uint16_t bank_id, Addr _addr,
46510618SOmar.Naji@arm.com                   unsigned int _size, Bank& bank_ref, Rank& rank_ref)
4669243SN/A            : entryTime(curTick()), readyTime(curTick()),
4679967SN/A              pkt(_pkt), isRead(is_read), rank(_rank), bank(_bank), row(_row),
4689967SN/A              bankId(bank_id), addr(_addr), size(_size), burstHelper(NULL),
46910618SOmar.Naji@arm.com              bankRef(bank_ref), rankRef(rank_ref)
4709243SN/A        { }
4719243SN/A
4729243SN/A    };
4739243SN/A
4749243SN/A    /**
4759243SN/A     * Bunch of things requires to setup "events" in gem5
47610206Sandreas.hansson@arm.com     * When event "respondEvent" occurs for example, the method
47710206Sandreas.hansson@arm.com     * processRespondEvent is called; no parameters are allowed
4789243SN/A     * in these methods
4799243SN/A     */
48010208Sandreas.hansson@arm.com    void processNextReqEvent();
48110208Sandreas.hansson@arm.com    EventWrapper<DRAMCtrl,&DRAMCtrl::processNextReqEvent> nextReqEvent;
48210208Sandreas.hansson@arm.com
4839243SN/A    void processRespondEvent();
48410146Sandreas.hansson@arm.com    EventWrapper<DRAMCtrl, &DRAMCtrl::processRespondEvent> respondEvent;
4859243SN/A
4869243SN/A    /**
4879243SN/A     * Check if the read queue has room for more entries
4889243SN/A     *
4899831SN/A     * @param pktCount The number of entries needed in the read queue
4909243SN/A     * @return true if read queue is full, false otherwise
4919243SN/A     */
4929831SN/A    bool readQueueFull(unsigned int pktCount) const;
4939243SN/A
4949243SN/A    /**
4959243SN/A     * Check if the write queue has room for more entries
4969243SN/A     *
4979831SN/A     * @param pktCount The number of entries needed in the write queue
4989243SN/A     * @return true if write queue is full, false otherwise
4999243SN/A     */
5009831SN/A    bool writeQueueFull(unsigned int pktCount) const;
5019243SN/A
5029243SN/A    /**
5039243SN/A     * When a new read comes in, first check if the write q has a
5049243SN/A     * pending request to the same address.\ If not, decode the
5059831SN/A     * address to populate rank/bank/row, create one or mutliple
5069831SN/A     * "dram_pkt", and push them to the back of the read queue.\
5079831SN/A     * If this is the only
5089243SN/A     * read request in the system, schedule an event to start
5099243SN/A     * servicing it.
5109243SN/A     *
5119243SN/A     * @param pkt The request packet from the outside world
5129831SN/A     * @param pktCount The number of DRAM bursts the pkt
5139831SN/A     * translate to. If pkt size is larger then one full burst,
5149831SN/A     * then pktCount is greater than one.
5159243SN/A     */
5169831SN/A    void addToReadQueue(PacketPtr pkt, unsigned int pktCount);
5179243SN/A
5189243SN/A    /**
5199243SN/A     * Decode the incoming pkt, create a dram_pkt and push to the
5209243SN/A     * back of the write queue. \If the write q length is more than
5219243SN/A     * the threshold specified by the user, ie the queue is beginning
5229243SN/A     * to get full, stop reads, and start draining writes.
5239243SN/A     *
5249243SN/A     * @param pkt The request packet from the outside world
5259831SN/A     * @param pktCount The number of DRAM bursts the pkt
5269831SN/A     * translate to. If pkt size is larger then one full burst,
5279831SN/A     * then pktCount is greater than one.
5289243SN/A     */
5299831SN/A    void addToWriteQueue(PacketPtr pkt, unsigned int pktCount);
5309243SN/A
5319243SN/A    /**
5329243SN/A     * Actually do the DRAM access - figure out the latency it
5339243SN/A     * will take to service the req based on bank state, channel state etc
5349243SN/A     * and then update those states to account for this request.\ Based
5359243SN/A     * on this, update the packet's "readyTime" and move it to the
5369243SN/A     * response q from where it will eventually go back to the outside
5379243SN/A     * world.
5389243SN/A     *
5399243SN/A     * @param pkt The DRAM packet created from the outside world pkt
5409243SN/A     */
5419243SN/A    void doDRAMAccess(DRAMPacket* dram_pkt);
5429243SN/A
5439243SN/A    /**
5449243SN/A     * When a packet reaches its "readyTime" in the response Q,
5459243SN/A     * use the "access()" method in AbstractMemory to actually
5469243SN/A     * create the response packet, and send it back to the outside
5479243SN/A     * world requestor.
5489243SN/A     *
5499243SN/A     * @param pkt The packet from the outside world
5509726SN/A     * @param static_latency Static latency to add before sending the packet
5519243SN/A     */
5529726SN/A    void accessAndRespond(PacketPtr pkt, Tick static_latency);
5539243SN/A
5549243SN/A    /**
5559243SN/A     * Address decoder to figure out physical mapping onto ranks,
5569831SN/A     * banks, and rows. This function is called multiple times on the same
5579831SN/A     * system packet if the pakcet is larger than burst of the memory. The
5589831SN/A     * dramPktAddr is used for the offset within the packet.
5599243SN/A     *
5609243SN/A     * @param pkt The packet from the outside world
5619831SN/A     * @param dramPktAddr The starting address of the DRAM packet
5629831SN/A     * @param size The size of the DRAM packet in bytes
5639966SN/A     * @param isRead Is the request for a read or a write to DRAM
5649243SN/A     * @return A DRAMPacket pointer with the decoded information
5659243SN/A     */
56610143SN/A    DRAMPacket* decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned int size,
56710143SN/A                           bool isRead);
5689243SN/A
5699243SN/A    /**
57010206Sandreas.hansson@arm.com     * The memory schduler/arbiter - picks which request needs to
5719567SN/A     * go next, based on the specified policy such as FCFS or FR-FCFS
57210206Sandreas.hansson@arm.com     * and moves it to the head of the queue.
57310393Swendy.elsasser@arm.com     * Prioritizes accesses to the same rank as previous burst unless
57410393Swendy.elsasser@arm.com     * controller is switching command type.
57510393Swendy.elsasser@arm.com     *
57610393Swendy.elsasser@arm.com     * @param queue Queued requests to consider
57710890Swendy.elsasser@arm.com     * @param extra_col_delay Any extra delay due to a read/write switch
57810618SOmar.Naji@arm.com     * @return true if a packet is scheduled to a rank which is available else
57910618SOmar.Naji@arm.com     * false
5809243SN/A     */
58110890Swendy.elsasser@arm.com    bool chooseNext(std::deque<DRAMPacket*>& queue, Tick extra_col_delay);
5829243SN/A
5839243SN/A    /**
5849974SN/A     * For FR-FCFS policy reorder the read/write queue depending on row buffer
58510890Swendy.elsasser@arm.com     * hits and earliest bursts available in DRAM
58610393Swendy.elsasser@arm.com     *
58710393Swendy.elsasser@arm.com     * @param queue Queued requests to consider
58810890Swendy.elsasser@arm.com     * @param extra_col_delay Any extra delay due to a read/write switch
58910618SOmar.Naji@arm.com     * @return true if a packet is scheduled to a rank which is available else
59010618SOmar.Naji@arm.com     * false
5919974SN/A     */
59210890Swendy.elsasser@arm.com    bool reorderQueue(std::deque<DRAMPacket*>& queue, Tick extra_col_delay);
5939974SN/A
5949974SN/A    /**
59510211Sandreas.hansson@arm.com     * Find which are the earliest banks ready to issue an activate
59610211Sandreas.hansson@arm.com     * for the enqueued requests. Assumes maximum of 64 banks per DIMM
59710393Swendy.elsasser@arm.com     * Also checks if the bank is already prepped.
5989967SN/A     *
59910393Swendy.elsasser@arm.com     * @param queue Queued requests to consider
60010890Swendy.elsasser@arm.com     * @param time of seamless burst command
6019967SN/A     * @return One-hot encoded mask of bank indices
60210890Swendy.elsasser@arm.com     * @return boolean indicating burst can issue seamlessly, with no gaps
6039967SN/A     */
60410890Swendy.elsasser@arm.com    std::pair<uint64_t, bool> minBankPrep(const std::deque<DRAMPacket*>& queue,
60510890Swendy.elsasser@arm.com                                          Tick min_col_at) const;
6069488SN/A
6079488SN/A    /**
6089488SN/A     * Keep track of when row activations happen, in order to enforce
6099488SN/A     * the maximum number of activations in the activation window. The
6109488SN/A     * method updates the time that the banks become available based
6119488SN/A     * on the current limits.
61210210Sandreas.hansson@arm.com     *
61310618SOmar.Naji@arm.com     * @param rank_ref Reference to the rank
61410618SOmar.Naji@arm.com     * @param bank_ref Reference to the bank
61510210Sandreas.hansson@arm.com     * @param act_tick Time when the activation takes place
61610210Sandreas.hansson@arm.com     * @param row Index of the row
6179488SN/A     */
61810618SOmar.Naji@arm.com    void activateBank(Rank& rank_ref, Bank& bank_ref, Tick act_tick,
61910618SOmar.Naji@arm.com                      uint32_t row);
62010207Sandreas.hansson@arm.com
62110207Sandreas.hansson@arm.com    /**
62210207Sandreas.hansson@arm.com     * Precharge a given bank and also update when the precharge is
62310207Sandreas.hansson@arm.com     * done. This will also deal with any stats related to the
62410207Sandreas.hansson@arm.com     * accesses to the open page.
62510207Sandreas.hansson@arm.com     *
62610618SOmar.Naji@arm.com     * @param rank_ref The rank to precharge
62710247Sandreas.hansson@arm.com     * @param bank_ref The bank to precharge
62810211Sandreas.hansson@arm.com     * @param pre_at Time when the precharge takes place
62910247Sandreas.hansson@arm.com     * @param trace Is this an auto precharge then do not add to trace
63010207Sandreas.hansson@arm.com     */
63110618SOmar.Naji@arm.com    void prechargeBank(Rank& rank_ref, Bank& bank_ref,
63210618SOmar.Naji@arm.com                       Tick pre_at, bool trace = true);
6339488SN/A
63410143SN/A    /**
63510143SN/A     * Used for debugging to observe the contents of the queues.
63610143SN/A     */
6379243SN/A    void printQs() const;
6389243SN/A
6399243SN/A    /**
64010889Sandreas.hansson@arm.com     * Burst-align an address.
64110889Sandreas.hansson@arm.com     *
64210889Sandreas.hansson@arm.com     * @param addr The potentially unaligned address
64310889Sandreas.hansson@arm.com     *
64410889Sandreas.hansson@arm.com     * @return An address aligned to a DRAM burst
64510889Sandreas.hansson@arm.com     */
64610889Sandreas.hansson@arm.com    Addr burstAlign(Addr addr) const { return (addr & ~(Addr(burstSize - 1))); }
64710889Sandreas.hansson@arm.com
64810889Sandreas.hansson@arm.com    /**
6499243SN/A     * The controller's main read and write queues
6509243SN/A     */
6519833SN/A    std::deque<DRAMPacket*> readQueue;
6529833SN/A    std::deque<DRAMPacket*> writeQueue;
6539243SN/A
6549243SN/A    /**
65510889Sandreas.hansson@arm.com     * To avoid iterating over the write queue to check for
65610889Sandreas.hansson@arm.com     * overlapping transactions, maintain a set of burst addresses
65710889Sandreas.hansson@arm.com     * that are currently queued. Since we merge writes to the same
65810889Sandreas.hansson@arm.com     * location we never have more than one address to the same burst
65910889Sandreas.hansson@arm.com     * address.
66010889Sandreas.hansson@arm.com     */
66110889Sandreas.hansson@arm.com    std::unordered_set<Addr> isInWriteQueue;
66210889Sandreas.hansson@arm.com
66310889Sandreas.hansson@arm.com    /**
6649243SN/A     * Response queue where read packets wait after we're done working
6659567SN/A     * with them, but it's not time to send the response yet. The
6669567SN/A     * responses are stored seperately mostly to keep the code clean
6679567SN/A     * and help with events scheduling. For all logical purposes such
6689567SN/A     * as sizing the read queue, this and the main read queue need to
6699567SN/A     * be added together.
6709243SN/A     */
6719833SN/A    std::deque<DRAMPacket*> respQueue;
6729243SN/A
6739567SN/A    /**
67410618SOmar.Naji@arm.com     * Vector of ranks
6759243SN/A     */
67610618SOmar.Naji@arm.com    std::vector<Rank*> ranks;
6779243SN/A
6789243SN/A    /**
6799243SN/A     * The following are basic design parameters of the memory
6809831SN/A     * controller, and are initialized based on parameter values.
6819831SN/A     * The rowsPerBank is determined based on the capacity, number of
6829831SN/A     * ranks and banks, the burst size, and the row buffer size.
6839243SN/A     */
68410489SOmar.Naji@arm.com    const uint32_t deviceSize;
6859831SN/A    const uint32_t deviceBusWidth;
6869831SN/A    const uint32_t burstLength;
6879831SN/A    const uint32_t deviceRowBufferSize;
6889831SN/A    const uint32_t devicesPerRank;
6899831SN/A    const uint32_t burstSize;
6909831SN/A    const uint32_t rowBufferSize;
69110140SN/A    const uint32_t columnsPerRowBuffer;
69210286Sandreas.hansson@arm.com    const uint32_t columnsPerStripe;
6939243SN/A    const uint32_t ranksPerChannel;
69410394Swendy.elsasser@arm.com    const uint32_t bankGroupsPerRank;
69510394Swendy.elsasser@arm.com    const bool bankGroupArch;
6969243SN/A    const uint32_t banksPerRank;
6979566SN/A    const uint32_t channels;
6989243SN/A    uint32_t rowsPerBank;
6999243SN/A    const uint32_t readBufferSize;
7009243SN/A    const uint32_t writeBufferSize;
70110140SN/A    const uint32_t writeHighThreshold;
70210140SN/A    const uint32_t writeLowThreshold;
70310140SN/A    const uint32_t minWritesPerSwitch;
70410140SN/A    uint32_t writesThisTime;
70510147Sandreas.hansson@arm.com    uint32_t readsThisTime;
7069243SN/A
7079243SN/A    /**
7089243SN/A     * Basic memory timing parameters initialized based on parameter
7099243SN/A     * values.
7109243SN/A     */
71110286Sandreas.hansson@arm.com    const Tick M5_CLASS_VAR_USED tCK;
7129243SN/A    const Tick tWTR;
71310206Sandreas.hansson@arm.com    const Tick tRTW;
71410393Swendy.elsasser@arm.com    const Tick tCS;
7159243SN/A    const Tick tBURST;
71610394Swendy.elsasser@arm.com    const Tick tCCD_L;
7179243SN/A    const Tick tRCD;
7189243SN/A    const Tick tCL;
7199243SN/A    const Tick tRP;
7209963SN/A    const Tick tRAS;
72110210Sandreas.hansson@arm.com    const Tick tWR;
72210212Sandreas.hansson@arm.com    const Tick tRTP;
7239243SN/A    const Tick tRFC;
7249243SN/A    const Tick tREFI;
7259971SN/A    const Tick tRRD;
72610394Swendy.elsasser@arm.com    const Tick tRRD_L;
7279488SN/A    const Tick tXAW;
7289488SN/A    const uint32_t activationLimit;
7299243SN/A
7309243SN/A    /**
7319243SN/A     * Memory controller configuration initialized based on parameter
7329243SN/A     * values.
7339243SN/A     */
7349243SN/A    Enums::MemSched memSchedPolicy;
7359243SN/A    Enums::AddrMap addrMapping;
7369243SN/A    Enums::PageManage pageMgmt;
7379243SN/A
7389243SN/A    /**
73910141SN/A     * Max column accesses (read and write) per row, before forefully
74010141SN/A     * closing it.
74110141SN/A     */
74210141SN/A    const uint32_t maxAccessesPerRow;
74310141SN/A
74410141SN/A    /**
7459726SN/A     * Pipeline latency of the controller frontend. The frontend
7469726SN/A     * contribution is added to writes (that complete when they are in
7479726SN/A     * the write buffer) and reads that are serviced the write buffer.
7489726SN/A     */
7499726SN/A    const Tick frontendLatency;
7509726SN/A
7519726SN/A    /**
7529726SN/A     * Pipeline latency of the backend and PHY. Along with the
7539726SN/A     * frontend contribution, this latency is added to reads serviced
7549726SN/A     * by the DRAM.
7559726SN/A     */
7569726SN/A    const Tick backendLatency;
7579726SN/A
7589726SN/A    /**
7599243SN/A     * Till when has the main data bus been spoken for already?
7609243SN/A     */
7619243SN/A    Tick busBusyUntil;
7629243SN/A
7639243SN/A    Tick prevArrival;
7649243SN/A
76510206Sandreas.hansson@arm.com    /**
76610206Sandreas.hansson@arm.com     * The soonest you have to start thinking about the next request
76710206Sandreas.hansson@arm.com     * is the longest access time that can occur before
76810206Sandreas.hansson@arm.com     * busBusyUntil. Assuming you need to precharge, open a new row,
76910206Sandreas.hansson@arm.com     * and access, it is tRP + tRCD + tCL.
77010206Sandreas.hansson@arm.com     */
77110206Sandreas.hansson@arm.com    Tick nextReqTime;
7729972SN/A
7739243SN/A    // All statistics that the model needs to capture
7749243SN/A    Stats::Scalar readReqs;
7759243SN/A    Stats::Scalar writeReqs;
7769831SN/A    Stats::Scalar readBursts;
7779831SN/A    Stats::Scalar writeBursts;
7789975SN/A    Stats::Scalar bytesReadDRAM;
7799975SN/A    Stats::Scalar bytesReadWrQ;
7809243SN/A    Stats::Scalar bytesWritten;
7819977SN/A    Stats::Scalar bytesReadSys;
7829977SN/A    Stats::Scalar bytesWrittenSys;
7839243SN/A    Stats::Scalar servicedByWrQ;
7849977SN/A    Stats::Scalar mergedWrBursts;
7859243SN/A    Stats::Scalar neitherReadNorWrite;
7869977SN/A    Stats::Vector perBankRdBursts;
7879977SN/A    Stats::Vector perBankWrBursts;
7889243SN/A    Stats::Scalar numRdRetry;
7899243SN/A    Stats::Scalar numWrRetry;
7909243SN/A    Stats::Scalar totGap;
7919243SN/A    Stats::Vector readPktSize;
7929243SN/A    Stats::Vector writePktSize;
7939243SN/A    Stats::Vector rdQLenPdf;
7949243SN/A    Stats::Vector wrQLenPdf;
7959727SN/A    Stats::Histogram bytesPerActivate;
79610147Sandreas.hansson@arm.com    Stats::Histogram rdPerTurnAround;
79710147Sandreas.hansson@arm.com    Stats::Histogram wrPerTurnAround;
7989243SN/A
7999243SN/A    // Latencies summed over all requests
8009243SN/A    Stats::Scalar totQLat;
8019243SN/A    Stats::Scalar totMemAccLat;
8029243SN/A    Stats::Scalar totBusLat;
8039243SN/A
8049243SN/A    // Average latencies per request
8059243SN/A    Stats::Formula avgQLat;
8069243SN/A    Stats::Formula avgBusLat;
8079243SN/A    Stats::Formula avgMemAccLat;
8089243SN/A
8099243SN/A    // Average bandwidth
8109243SN/A    Stats::Formula avgRdBW;
8119243SN/A    Stats::Formula avgWrBW;
8129977SN/A    Stats::Formula avgRdBWSys;
8139977SN/A    Stats::Formula avgWrBWSys;
8149243SN/A    Stats::Formula peakBW;
8159243SN/A    Stats::Formula busUtil;
8169975SN/A    Stats::Formula busUtilRead;
8179975SN/A    Stats::Formula busUtilWrite;
8189243SN/A
8199243SN/A    // Average queue lengths
8209243SN/A    Stats::Average avgRdQLen;
8219243SN/A    Stats::Average avgWrQLen;
8229243SN/A
8239243SN/A    // Row hit count and rate
8249243SN/A    Stats::Scalar readRowHits;
8259243SN/A    Stats::Scalar writeRowHits;
8269243SN/A    Stats::Formula readRowHitRate;
8279243SN/A    Stats::Formula writeRowHitRate;
8289243SN/A    Stats::Formula avgGap;
8299243SN/A
8309975SN/A    // DRAM Power Calculation
8319975SN/A    Stats::Formula pageHitRate;
8329975SN/A
83310393Swendy.elsasser@arm.com    // Holds the value of the rank of burst issued
83410393Swendy.elsasser@arm.com    uint8_t activeRank;
83510393Swendy.elsasser@arm.com
83610432SOmar.Naji@arm.com    // timestamp offset
83710432SOmar.Naji@arm.com    uint64_t timeStampOffset;
83810432SOmar.Naji@arm.com
8399349SN/A    /** @todo this is a temporary workaround until the 4-phase code is
8409349SN/A     * committed. upstream caches needs this packet until true is returned, so
8419349SN/A     * hold onto it for deletion until a subsequent call
8429349SN/A     */
8439349SN/A    std::vector<PacketPtr> pendingDelete;
8449349SN/A
84510432SOmar.Naji@arm.com    /**
84610618SOmar.Naji@arm.com     * This function increments the energy when called. If stats are
84710618SOmar.Naji@arm.com     * dumped periodically, note accumulated energy values will
84810618SOmar.Naji@arm.com     * appear in the stats (even if the stats are reset). This is a
84910618SOmar.Naji@arm.com     * result of the energy values coming from DRAMPower, and there
85010618SOmar.Naji@arm.com     * is currently no support for resetting the state.
85110618SOmar.Naji@arm.com     *
85210618SOmar.Naji@arm.com     * @param rank Currrent rank
85310618SOmar.Naji@arm.com     */
85410618SOmar.Naji@arm.com    void updatePowerStats(Rank& rank_ref);
85510432SOmar.Naji@arm.com
85610432SOmar.Naji@arm.com    /**
85710432SOmar.Naji@arm.com     * Function for sorting commands in the command list of DRAMPower.
85810432SOmar.Naji@arm.com     *
85910432SOmar.Naji@arm.com     * @param a Memory Command in command list of DRAMPower library
86010432SOmar.Naji@arm.com     * @param next Memory Command in command list of DRAMPower
86110432SOmar.Naji@arm.com     * @return true if timestamp of Command 1 < timestamp of Command 2
86210432SOmar.Naji@arm.com     */
86310432SOmar.Naji@arm.com    static bool sortTime(const Data::MemCommand& m1,
86410432SOmar.Naji@arm.com                         const Data::MemCommand& m2) {
86510432SOmar.Naji@arm.com        return m1.getTime() < m2.getTime();
86610432SOmar.Naji@arm.com    };
86710432SOmar.Naji@arm.com
86810432SOmar.Naji@arm.com
8699243SN/A  public:
8709243SN/A
8719243SN/A    void regStats();
8729243SN/A
87310146Sandreas.hansson@arm.com    DRAMCtrl(const DRAMCtrlParams* p);
8749243SN/A
87511168Sandreas.hansson@arm.com    DrainState drain() override;
8769243SN/A
8779294SN/A    virtual BaseSlavePort& getSlavePort(const std::string& if_name,
8789294SN/A                                        PortID idx = InvalidPortID);
8799243SN/A
88011168Sandreas.hansson@arm.com    virtual void init() override;
88111168Sandreas.hansson@arm.com    virtual void startup() override;
88211168Sandreas.hansson@arm.com    virtual void drainResume() override;
8839243SN/A
8849243SN/A  protected:
8859243SN/A
8869243SN/A    Tick recvAtomic(PacketPtr pkt);
8879243SN/A    void recvFunctional(PacketPtr pkt);
8889243SN/A    bool recvTimingReq(PacketPtr pkt);
8899243SN/A
8909243SN/A};
8919243SN/A
89210146Sandreas.hansson@arm.com#endif //__MEM_DRAM_CTRL_HH__
893