dram_ctrl.hh revision 10212:acc1131e01d6
15132Sgblack@eecs.umich.edu/* 25132Sgblack@eecs.umich.edu * Copyright (c) 2012-2014 ARM Limited 35132Sgblack@eecs.umich.edu * All rights reserved 45132Sgblack@eecs.umich.edu * 57087Snate@binkert.org * The license below extends only to copyright in the software and shall 67087Snate@binkert.org * not be construed as granting a license to any other intellectual 77087Snate@binkert.org * property including but not limited to intellectual property relating 87087Snate@binkert.org * to a hardware implementation of the functionality of the software 97087Snate@binkert.org * licensed hereunder. You may use the software subject to the license 107087Snate@binkert.org * terms below provided that you ensure that this notice is replicated 117087Snate@binkert.org * unmodified and in its entirety in all distributions of the software, 127087Snate@binkert.org * modified or unmodified, in source code or in binary form. 135132Sgblack@eecs.umich.edu * 147087Snate@binkert.org * Copyright (c) 2013 Amin Farmahini-Farahani 157087Snate@binkert.org * All rights reserved. 167087Snate@binkert.org * 177087Snate@binkert.org * Redistribution and use in source and binary forms, with or without 187087Snate@binkert.org * modification, are permitted provided that the following conditions are 197087Snate@binkert.org * met: redistributions of source code must retain the above copyright 207087Snate@binkert.org * notice, this list of conditions and the following disclaimer; 217087Snate@binkert.org * redistributions in binary form must reproduce the above copyright 225132Sgblack@eecs.umich.edu * notice, this list of conditions and the following disclaimer in the 237087Snate@binkert.org * documentation and/or other materials provided with the distribution; 245132Sgblack@eecs.umich.edu * neither the name of the copyright holders nor the names of its 255132Sgblack@eecs.umich.edu * contributors may be used to endorse or promote products derived from 265132Sgblack@eecs.umich.edu * this software without specific prior written permission. 275132Sgblack@eecs.umich.edu * 285132Sgblack@eecs.umich.edu * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 295132Sgblack@eecs.umich.edu * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 305132Sgblack@eecs.umich.edu * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 315132Sgblack@eecs.umich.edu * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 325132Sgblack@eecs.umich.edu * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 335132Sgblack@eecs.umich.edu * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 345132Sgblack@eecs.umich.edu * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 355132Sgblack@eecs.umich.edu * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 365132Sgblack@eecs.umich.edu * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 375132Sgblack@eecs.umich.edu * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 385132Sgblack@eecs.umich.edu * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 395132Sgblack@eecs.umich.edu * 405612Sgblack@eecs.umich.edu * Authors: Andreas Hansson 415625Sgblack@eecs.umich.edu * Ani Udipi 427629Sgblack@eecs.umich.edu * Neha Agarwal 435132Sgblack@eecs.umich.edu */ 445132Sgblack@eecs.umich.edu 455625Sgblack@eecs.umich.edu/** 465132Sgblack@eecs.umich.edu * @file 475132Sgblack@eecs.umich.edu * DRAMCtrl declaration 485132Sgblack@eecs.umich.edu */ 495299Sgblack@eecs.umich.edu 505132Sgblack@eecs.umich.edu#ifndef __MEM_DRAM_CTRL_HH__ 515132Sgblack@eecs.umich.edu#define __MEM_DRAM_CTRL_HH__ 525132Sgblack@eecs.umich.edu 535132Sgblack@eecs.umich.edu#include <deque> 545132Sgblack@eecs.umich.edu 555299Sgblack@eecs.umich.edu#include "base/statistics.hh" 565299Sgblack@eecs.umich.edu#include "enums/AddrMap.hh" 575132Sgblack@eecs.umich.edu#include "enums/MemSched.hh" 585625Sgblack@eecs.umich.edu#include "enums/PageManage.hh" 595625Sgblack@eecs.umich.edu#include "mem/abstract_mem.hh" 605625Sgblack@eecs.umich.edu#include "mem/qport.hh" 615627Sgblack@eecs.umich.edu#include "params/DRAMCtrl.hh" 625627Sgblack@eecs.umich.edu#include "sim/eventq.hh" 637704Sgblack@eecs.umich.edu 647704Sgblack@eecs.umich.edu/** 657704Sgblack@eecs.umich.edu * The DRAM controller is a basic single-channel memory controller 667704Sgblack@eecs.umich.edu * aiming to mimic a high-level DRAM controller and the most important 675132Sgblack@eecs.umich.edu * timing constraints associated with the DRAM. The focus is really on 686220Sgblack@eecs.umich.edu * modelling the impact on the system rather than the DRAM itself, 696220Sgblack@eecs.umich.edu * hence the focus is on the controller model and not on the 706220Sgblack@eecs.umich.edu * memory. By adhering to the correct timing constraints, ultimately 716220Sgblack@eecs.umich.edu * there is no need for a memory model in addition to the controller 726220Sgblack@eecs.umich.edu * model. 736220Sgblack@eecs.umich.edu * 746220Sgblack@eecs.umich.edu * As a basic design principle, this controller is not cycle callable, 756220Sgblack@eecs.umich.edu * but instead uses events to decide when new decisions can be made, 766220Sgblack@eecs.umich.edu * when resources become available, when things are to be considered 776220Sgblack@eecs.umich.edu * done, and when to send things back. Through these simple 786220Sgblack@eecs.umich.edu * principles, we achieve a performant model that is not 796220Sgblack@eecs.umich.edu * cycle-accurate, but enables us to evaluate the system impact of a 806222Sgblack@eecs.umich.edu * wide range of memory technologies, and also collect statistics 816222Sgblack@eecs.umich.edu * about the use of the memory. 826222Sgblack@eecs.umich.edu */ 836222Sgblack@eecs.umich.educlass DRAMCtrl : public AbstractMemory 846222Sgblack@eecs.umich.edu{ 856222Sgblack@eecs.umich.edu 866222Sgblack@eecs.umich.edu private: 876222Sgblack@eecs.umich.edu 886222Sgblack@eecs.umich.edu // For now, make use of a queued slave port to avoid dealing with 896222Sgblack@eecs.umich.edu // flow control for the responses being sent back 906220Sgblack@eecs.umich.edu class MemoryPort : public QueuedSlavePort 916220Sgblack@eecs.umich.edu { 926220Sgblack@eecs.umich.edu 936222Sgblack@eecs.umich.edu SlavePacketQueue queue; 946220Sgblack@eecs.umich.edu DRAMCtrl& memory; 956222Sgblack@eecs.umich.edu 966220Sgblack@eecs.umich.edu public: 976220Sgblack@eecs.umich.edu 986222Sgblack@eecs.umich.edu MemoryPort(const std::string& name, DRAMCtrl& _memory); 996220Sgblack@eecs.umich.edu 1006220Sgblack@eecs.umich.edu protected: 1016220Sgblack@eecs.umich.edu 1026220Sgblack@eecs.umich.edu Tick recvAtomic(PacketPtr pkt); 1036222Sgblack@eecs.umich.edu 1046220Sgblack@eecs.umich.edu void recvFunctional(PacketPtr pkt); 1056220Sgblack@eecs.umich.edu 1066220Sgblack@eecs.umich.edu bool recvTimingReq(PacketPtr); 1076220Sgblack@eecs.umich.edu 1086220Sgblack@eecs.umich.edu virtual AddrRangeList getAddrRanges() const; 1096220Sgblack@eecs.umich.edu 1106220Sgblack@eecs.umich.edu }; 1116220Sgblack@eecs.umich.edu 1126220Sgblack@eecs.umich.edu /** 1136220Sgblack@eecs.umich.edu * Our incoming port, for a multi-ported controller add a crossbar 1145299Sgblack@eecs.umich.edu * in front of it 1157532Ssteve.reinhardt@amd.com */ 1165299Sgblack@eecs.umich.edu MemoryPort port; 1177532Ssteve.reinhardt@amd.com 1187532Ssteve.reinhardt@amd.com /** 1196220Sgblack@eecs.umich.edu * Remember if we have to retry a request when available. 1205299Sgblack@eecs.umich.edu */ 1215299Sgblack@eecs.umich.edu bool retryRdReq; 1225299Sgblack@eecs.umich.edu bool retryWrReq; 1235299Sgblack@eecs.umich.edu 1245299Sgblack@eecs.umich.edu /** 1255299Sgblack@eecs.umich.edu * Bus state used to control the read/write switching and drive 1265299Sgblack@eecs.umich.edu * the scheduling of the next request. 1275299Sgblack@eecs.umich.edu */ 1285299Sgblack@eecs.umich.edu enum BusState { 1295299Sgblack@eecs.umich.edu READ = 0, 1305299Sgblack@eecs.umich.edu READ_TO_WRITE, 1315299Sgblack@eecs.umich.edu WRITE, 1325299Sgblack@eecs.umich.edu WRITE_TO_READ 1335299Sgblack@eecs.umich.edu }; 1345299Sgblack@eecs.umich.edu 1355299Sgblack@eecs.umich.edu BusState busState; 1365299Sgblack@eecs.umich.edu 1375299Sgblack@eecs.umich.edu /** List to keep track of activate ticks */ 1385299Sgblack@eecs.umich.edu std::vector<std::deque<Tick>> actTicks; 1395299Sgblack@eecs.umich.edu 1405299Sgblack@eecs.umich.edu /** 1416220Sgblack@eecs.umich.edu * A basic class to track the bank state, i.e. what row is 1425299Sgblack@eecs.umich.edu * currently open (if any), when is the bank free to accept a new 1435299Sgblack@eecs.umich.edu * column (read/write) command, when can it be precharged, and 1445299Sgblack@eecs.umich.edu * when can it be activated. 1455299Sgblack@eecs.umich.edu * 1466220Sgblack@eecs.umich.edu * The bank also keeps track of how many bytes have been accessed 1475299Sgblack@eecs.umich.edu * in the open row since it was opened. 1485299Sgblack@eecs.umich.edu */ 1496220Sgblack@eecs.umich.edu class Bank 1506220Sgblack@eecs.umich.edu { 1516220Sgblack@eecs.umich.edu 1525299Sgblack@eecs.umich.edu public: 1535299Sgblack@eecs.umich.edu 1545299Sgblack@eecs.umich.edu static const uint32_t NO_ROW = -1; 1556220Sgblack@eecs.umich.edu 1565299Sgblack@eecs.umich.edu uint32_t openRow; 1576220Sgblack@eecs.umich.edu 1585299Sgblack@eecs.umich.edu Tick colAllowedAt; 1595299Sgblack@eecs.umich.edu Tick preAllowedAt; 1605299Sgblack@eecs.umich.edu Tick actAllowedAt; 1615299Sgblack@eecs.umich.edu 1626220Sgblack@eecs.umich.edu uint32_t rowAccesses; 1636220Sgblack@eecs.umich.edu uint32_t bytesAccessed; 1646220Sgblack@eecs.umich.edu 1656220Sgblack@eecs.umich.edu Bank() : 1665299Sgblack@eecs.umich.edu openRow(NO_ROW), colAllowedAt(0), preAllowedAt(0), actAllowedAt(0), 1675299Sgblack@eecs.umich.edu rowAccesses(0), bytesAccessed(0) 1685299Sgblack@eecs.umich.edu { } 1695299Sgblack@eecs.umich.edu }; 1705299Sgblack@eecs.umich.edu 1716220Sgblack@eecs.umich.edu /** 1726220Sgblack@eecs.umich.edu * A burst helper helps organize and manage a packet that is larger than 1735299Sgblack@eecs.umich.edu * the DRAM burst size. A system packet that is larger than the burst size 1746220Sgblack@eecs.umich.edu * is split into multiple DRAM packets and all those DRAM packets point to 1756220Sgblack@eecs.umich.edu * a single burst helper such that we know when the whole packet is served. 1766220Sgblack@eecs.umich.edu */ 1776220Sgblack@eecs.umich.edu class BurstHelper { 1786220Sgblack@eecs.umich.edu 1796220Sgblack@eecs.umich.edu public: 1806220Sgblack@eecs.umich.edu 1816220Sgblack@eecs.umich.edu /** Number of DRAM bursts requred for a system packet **/ 1826220Sgblack@eecs.umich.edu const unsigned int burstCount; 1836220Sgblack@eecs.umich.edu 1846220Sgblack@eecs.umich.edu /** Number of DRAM bursts serviced so far for a system packet **/ 1856220Sgblack@eecs.umich.edu unsigned int burstsServiced; 1866220Sgblack@eecs.umich.edu 1876220Sgblack@eecs.umich.edu BurstHelper(unsigned int _burstCount) 1886220Sgblack@eecs.umich.edu : burstCount(_burstCount), burstsServiced(0) 1896220Sgblack@eecs.umich.edu { } 1906220Sgblack@eecs.umich.edu }; 1916220Sgblack@eecs.umich.edu 1926220Sgblack@eecs.umich.edu /** 1936220Sgblack@eecs.umich.edu * A DRAM packet stores packets along with the timestamp of when 1946220Sgblack@eecs.umich.edu * the packet entered the queue, and also the decoded address. 1956220Sgblack@eecs.umich.edu */ 1966220Sgblack@eecs.umich.edu class DRAMPacket { 1976220Sgblack@eecs.umich.edu 1986220Sgblack@eecs.umich.edu public: 1996712Snate@binkert.org 2006220Sgblack@eecs.umich.edu /** When did request enter the controller */ 2016220Sgblack@eecs.umich.edu const Tick entryTime; 2026220Sgblack@eecs.umich.edu 2036220Sgblack@eecs.umich.edu /** When will request leave the controller */ 2046220Sgblack@eecs.umich.edu Tick readyTime; 2056220Sgblack@eecs.umich.edu 2066220Sgblack@eecs.umich.edu /** This comes from the outside world */ 2076220Sgblack@eecs.umich.edu const PacketPtr pkt; 2086220Sgblack@eecs.umich.edu 2096220Sgblack@eecs.umich.edu const bool isRead; 2106220Sgblack@eecs.umich.edu 2116220Sgblack@eecs.umich.edu /** Will be populated by address decoder */ 2126220Sgblack@eecs.umich.edu const uint8_t rank; 2136220Sgblack@eecs.umich.edu const uint8_t bank; 2146220Sgblack@eecs.umich.edu const uint16_t row; 2156220Sgblack@eecs.umich.edu 2166220Sgblack@eecs.umich.edu /** 2176220Sgblack@eecs.umich.edu * Bank id is calculated considering banks in all the ranks 2186220Sgblack@eecs.umich.edu * eg: 2 ranks each with 8 banks, then bankId = 0 --> rank0, bank0 and 2196220Sgblack@eecs.umich.edu * bankId = 8 --> rank1, bank0 2206220Sgblack@eecs.umich.edu */ 2216220Sgblack@eecs.umich.edu const uint16_t bankId; 2226220Sgblack@eecs.umich.edu 2236220Sgblack@eecs.umich.edu /** 2246220Sgblack@eecs.umich.edu * The starting address of the DRAM packet. 2256220Sgblack@eecs.umich.edu * This address could be unaligned to burst size boundaries. The 2266220Sgblack@eecs.umich.edu * reason is to keep the address offset so we can accurately check 2276220Sgblack@eecs.umich.edu * incoming read packets with packets in the write queue. 2286220Sgblack@eecs.umich.edu */ 2296220Sgblack@eecs.umich.edu Addr addr; 2306220Sgblack@eecs.umich.edu 2316220Sgblack@eecs.umich.edu /** 2325299Sgblack@eecs.umich.edu * The size of this dram packet in bytes 2335299Sgblack@eecs.umich.edu * It is always equal or smaller than DRAM burst size 2345299Sgblack@eecs.umich.edu */ 2355299Sgblack@eecs.umich.edu unsigned int size; 2365299Sgblack@eecs.umich.edu 2375299Sgblack@eecs.umich.edu /** 2385299Sgblack@eecs.umich.edu * A pointer to the BurstHelper if this DRAMPacket is a split packet 2395299Sgblack@eecs.umich.edu * If not a split packet (common case), this is set to NULL 2405299Sgblack@eecs.umich.edu */ 2415299Sgblack@eecs.umich.edu BurstHelper* burstHelper; 2425299Sgblack@eecs.umich.edu Bank& bankRef; 2435299Sgblack@eecs.umich.edu 2445299Sgblack@eecs.umich.edu DRAMPacket(PacketPtr _pkt, bool is_read, uint8_t _rank, uint8_t _bank, 2455299Sgblack@eecs.umich.edu uint16_t _row, uint16_t bank_id, Addr _addr, 2465299Sgblack@eecs.umich.edu unsigned int _size, Bank& bank_ref) 2475299Sgblack@eecs.umich.edu : entryTime(curTick()), readyTime(curTick()), 2485299Sgblack@eecs.umich.edu pkt(_pkt), isRead(is_read), rank(_rank), bank(_bank), row(_row), 2495299Sgblack@eecs.umich.edu bankId(bank_id), addr(_addr), size(_size), burstHelper(NULL), 2505299Sgblack@eecs.umich.edu bankRef(bank_ref) 2515299Sgblack@eecs.umich.edu { } 2525299Sgblack@eecs.umich.edu 2535299Sgblack@eecs.umich.edu }; 2545299Sgblack@eecs.umich.edu 2555299Sgblack@eecs.umich.edu /** 2565299Sgblack@eecs.umich.edu * Bunch of things requires to setup "events" in gem5 2575299Sgblack@eecs.umich.edu * When event "respondEvent" occurs for example, the method 2585299Sgblack@eecs.umich.edu * processRespondEvent is called; no parameters are allowed 2595299Sgblack@eecs.umich.edu * in these methods 2605299Sgblack@eecs.umich.edu */ 2615299Sgblack@eecs.umich.edu void processNextReqEvent(); 2625299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl,&DRAMCtrl::processNextReqEvent> nextReqEvent; 2635299Sgblack@eecs.umich.edu 2645299Sgblack@eecs.umich.edu void processRespondEvent(); 2655299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl, &DRAMCtrl::processRespondEvent> respondEvent; 2665299Sgblack@eecs.umich.edu 2675299Sgblack@eecs.umich.edu void processActivateEvent(); 2685299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl, &DRAMCtrl::processActivateEvent> activateEvent; 2695299Sgblack@eecs.umich.edu 2705299Sgblack@eecs.umich.edu void processPrechargeEvent(); 2715299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl, &DRAMCtrl::processPrechargeEvent> prechargeEvent; 2725299Sgblack@eecs.umich.edu 2735299Sgblack@eecs.umich.edu void processRefreshEvent(); 2745299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl, &DRAMCtrl::processRefreshEvent> refreshEvent; 2755299Sgblack@eecs.umich.edu 2765299Sgblack@eecs.umich.edu void processPowerEvent(); 2775299Sgblack@eecs.umich.edu EventWrapper<DRAMCtrl,&DRAMCtrl::processPowerEvent> powerEvent; 2785299Sgblack@eecs.umich.edu 2795299Sgblack@eecs.umich.edu /** 2805299Sgblack@eecs.umich.edu * Check if the read queue has room for more entries 2815299Sgblack@eecs.umich.edu * 2825299Sgblack@eecs.umich.edu * @param pktCount The number of entries needed in the read queue 2835299Sgblack@eecs.umich.edu * @return true if read queue is full, false otherwise 2845299Sgblack@eecs.umich.edu */ 2855299Sgblack@eecs.umich.edu bool readQueueFull(unsigned int pktCount) const; 2865299Sgblack@eecs.umich.edu 2875299Sgblack@eecs.umich.edu /** 2885299Sgblack@eecs.umich.edu * Check if the write queue has room for more entries 2895299Sgblack@eecs.umich.edu * 2906220Sgblack@eecs.umich.edu * @param pktCount The number of entries needed in the write queue 2915299Sgblack@eecs.umich.edu * @return true if write queue is full, false otherwise 2925299Sgblack@eecs.umich.edu */ 2936220Sgblack@eecs.umich.edu bool writeQueueFull(unsigned int pktCount) const; 2945299Sgblack@eecs.umich.edu 2955299Sgblack@eecs.umich.edu /** 2966220Sgblack@eecs.umich.edu * When a new read comes in, first check if the write q has a 2975299Sgblack@eecs.umich.edu * pending request to the same address.\ If not, decode the 2986220Sgblack@eecs.umich.edu * address to populate rank/bank/row, create one or mutliple 2995299Sgblack@eecs.umich.edu * "dram_pkt", and push them to the back of the read queue.\ 3005299Sgblack@eecs.umich.edu * If this is the only 3016220Sgblack@eecs.umich.edu * read request in the system, schedule an event to start 3025299Sgblack@eecs.umich.edu * servicing it. 3035299Sgblack@eecs.umich.edu * 3046220Sgblack@eecs.umich.edu * @param pkt The request packet from the outside world 3055299Sgblack@eecs.umich.edu * @param pktCount The number of DRAM bursts the pkt 3066220Sgblack@eecs.umich.edu * translate to. If pkt size is larger then one full burst, 3075299Sgblack@eecs.umich.edu * then pktCount is greater than one. 3085299Sgblack@eecs.umich.edu */ 3096220Sgblack@eecs.umich.edu void addToReadQueue(PacketPtr pkt, unsigned int pktCount); 3106220Sgblack@eecs.umich.edu 3116220Sgblack@eecs.umich.edu /** 3126220Sgblack@eecs.umich.edu * Decode the incoming pkt, create a dram_pkt and push to the 3136220Sgblack@eecs.umich.edu * back of the write queue. \If the write q length is more than 3146220Sgblack@eecs.umich.edu * the threshold specified by the user, ie the queue is beginning 3156220Sgblack@eecs.umich.edu * to get full, stop reads, and start draining writes. 3166220Sgblack@eecs.umich.edu * 3176220Sgblack@eecs.umich.edu * @param pkt The request packet from the outside world 3185299Sgblack@eecs.umich.edu * @param pktCount The number of DRAM bursts the pkt 3195299Sgblack@eecs.umich.edu * translate to. If pkt size is larger then one full burst, 3205299Sgblack@eecs.umich.edu * then pktCount is greater than one. 3216220Sgblack@eecs.umich.edu */ 3225299Sgblack@eecs.umich.edu void addToWriteQueue(PacketPtr pkt, unsigned int pktCount); 3237720Sgblack@eecs.umich.edu 3245299Sgblack@eecs.umich.edu /** 3255299Sgblack@eecs.umich.edu * Actually do the DRAM access - figure out the latency it 3265334Sgblack@eecs.umich.edu * will take to service the req based on bank state, channel state etc 3275615Sgblack@eecs.umich.edu * and then update those states to account for this request.\ Based 3285625Sgblack@eecs.umich.edu * on this, update the packet's "readyTime" and move it to the 3295615Sgblack@eecs.umich.edu * response q from where it will eventually go back to the outside 3305334Sgblack@eecs.umich.edu * world. 3315625Sgblack@eecs.umich.edu * 3325625Sgblack@eecs.umich.edu * @param pkt The DRAM packet created from the outside world pkt 3335625Sgblack@eecs.umich.edu */ 3345625Sgblack@eecs.umich.edu void doDRAMAccess(DRAMPacket* dram_pkt); 3355625Sgblack@eecs.umich.edu 3365625Sgblack@eecs.umich.edu /** 3375625Sgblack@eecs.umich.edu * When a packet reaches its "readyTime" in the response Q, 3385299Sgblack@eecs.umich.edu * use the "access()" method in AbstractMemory to actually 3395299Sgblack@eecs.umich.edu * create the response packet, and send it back to the outside 3405334Sgblack@eecs.umich.edu * world requestor. 3415615Sgblack@eecs.umich.edu * 3425615Sgblack@eecs.umich.edu * @param pkt The packet from the outside world 3435334Sgblack@eecs.umich.edu * @param static_latency Static latency to add before sending the packet 3445334Sgblack@eecs.umich.edu */ 3455334Sgblack@eecs.umich.edu void accessAndRespond(PacketPtr pkt, Tick static_latency); 3465334Sgblack@eecs.umich.edu 3475334Sgblack@eecs.umich.edu /** 3485334Sgblack@eecs.umich.edu * Address decoder to figure out physical mapping onto ranks, 3495615Sgblack@eecs.umich.edu * banks, and rows. This function is called multiple times on the same 3505615Sgblack@eecs.umich.edu * system packet if the pakcet is larger than burst of the memory. The 3515615Sgblack@eecs.umich.edu * dramPktAddr is used for the offset within the packet. 3525334Sgblack@eecs.umich.edu * 3535615Sgblack@eecs.umich.edu * @param pkt The packet from the outside world 3545615Sgblack@eecs.umich.edu * @param dramPktAddr The starting address of the DRAM packet 3555615Sgblack@eecs.umich.edu * @param size The size of the DRAM packet in bytes 3565615Sgblack@eecs.umich.edu * @param isRead Is the request for a read or a write to DRAM 3575615Sgblack@eecs.umich.edu * @return A DRAMPacket pointer with the decoded information 3585615Sgblack@eecs.umich.edu */ 3595334Sgblack@eecs.umich.edu DRAMPacket* decodeAddr(PacketPtr pkt, Addr dramPktAddr, unsigned int size, 3605334Sgblack@eecs.umich.edu bool isRead); 3615625Sgblack@eecs.umich.edu 3625625Sgblack@eecs.umich.edu /** 3635625Sgblack@eecs.umich.edu * The memory schduler/arbiter - picks which request needs to 3645625Sgblack@eecs.umich.edu * go next, based on the specified policy such as FCFS or FR-FCFS 3655625Sgblack@eecs.umich.edu * and moves it to the head of the queue. 3665625Sgblack@eecs.umich.edu */ 3675625Sgblack@eecs.umich.edu void chooseNext(std::deque<DRAMPacket*>& queue); 3685625Sgblack@eecs.umich.edu 3695625Sgblack@eecs.umich.edu /** 3705625Sgblack@eecs.umich.edu * Move the request at the head of the read queue to the response 3715625Sgblack@eecs.umich.edu * queue, sorting by readyTime.\ If it is the only packet in the 3725625Sgblack@eecs.umich.edu * response queue, schedule a respond event to send it back to the 3735625Sgblack@eecs.umich.edu * outside world 3745625Sgblack@eecs.umich.edu */ 3755625Sgblack@eecs.umich.edu void moveToRespQ(); 3765625Sgblack@eecs.umich.edu 3775625Sgblack@eecs.umich.edu /** 3785625Sgblack@eecs.umich.edu * For FR-FCFS policy reorder the read/write queue depending on row buffer 3795625Sgblack@eecs.umich.edu * hits and earliest banks available in DRAM 3805625Sgblack@eecs.umich.edu */ 3815625Sgblack@eecs.umich.edu void reorderQueue(std::deque<DRAMPacket*>& queue); 3825625Sgblack@eecs.umich.edu 3835625Sgblack@eecs.umich.edu /** 3845625Sgblack@eecs.umich.edu * Find which are the earliest banks ready to issue an activate 3855625Sgblack@eecs.umich.edu * for the enqueued requests. Assumes maximum of 64 banks per DIMM 3865625Sgblack@eecs.umich.edu * 3875625Sgblack@eecs.umich.edu * @param Queued requests to consider 3885625Sgblack@eecs.umich.edu * @return One-hot encoded mask of bank indices 3895625Sgblack@eecs.umich.edu */ 3905334Sgblack@eecs.umich.edu uint64_t minBankActAt(const std::deque<DRAMPacket*>& queue) const; 3915132Sgblack@eecs.umich.edu 3925132Sgblack@eecs.umich.edu /** 3935334Sgblack@eecs.umich.edu * Keep track of when row activations happen, in order to enforce 3945132Sgblack@eecs.umich.edu * the maximum number of activations in the activation window. The 3955132Sgblack@eecs.umich.edu * method updates the time that the banks become available based 3965132Sgblack@eecs.umich.edu * on the current limits. 3975132Sgblack@eecs.umich.edu * 3985132Sgblack@eecs.umich.edu * @param act_tick Time when the activation takes place 3995132Sgblack@eecs.umich.edu * @param rank Index of the rank 4005132Sgblack@eecs.umich.edu * @param bank Index of the bank 4015132Sgblack@eecs.umich.edu * @param row Index of the row 4025132Sgblack@eecs.umich.edu * @param bank_ref Reference to the bank 4035132Sgblack@eecs.umich.edu */ 4045132Sgblack@eecs.umich.edu void activateBank(Tick act_tick, uint8_t rank, uint8_t bank, 4055132Sgblack@eecs.umich.edu uint16_t row, Bank& bank_ref); 4065132Sgblack@eecs.umich.edu 4075132Sgblack@eecs.umich.edu /** 4085132Sgblack@eecs.umich.edu * Precharge a given bank and also update when the precharge is 4095132Sgblack@eecs.umich.edu * done. This will also deal with any stats related to the 4105132Sgblack@eecs.umich.edu * accesses to the open page. 4115132Sgblack@eecs.umich.edu * 4125132Sgblack@eecs.umich.edu * @param bank The bank to precharge 4135132Sgblack@eecs.umich.edu * @param pre_at Time when the precharge takes place 414 */ 415 void prechargeBank(Bank& bank, Tick pre_at); 416 417 void printParams() const; 418 419 /** 420 * Used for debugging to observe the contents of the queues. 421 */ 422 void printQs() const; 423 424 /** 425 * The controller's main read and write queues 426 */ 427 std::deque<DRAMPacket*> readQueue; 428 std::deque<DRAMPacket*> writeQueue; 429 430 /** 431 * Response queue where read packets wait after we're done working 432 * with them, but it's not time to send the response yet. The 433 * responses are stored seperately mostly to keep the code clean 434 * and help with events scheduling. For all logical purposes such 435 * as sizing the read queue, this and the main read queue need to 436 * be added together. 437 */ 438 std::deque<DRAMPacket*> respQueue; 439 440 /** 441 * If we need to drain, keep the drain manager around until we're 442 * done here. 443 */ 444 DrainManager *drainManager; 445 446 /** 447 * Multi-dimensional vector of banks, first dimension is ranks, 448 * second is bank 449 */ 450 std::vector<std::vector<Bank> > banks; 451 452 /** 453 * The following are basic design parameters of the memory 454 * controller, and are initialized based on parameter values. 455 * The rowsPerBank is determined based on the capacity, number of 456 * ranks and banks, the burst size, and the row buffer size. 457 */ 458 const uint32_t deviceBusWidth; 459 const uint32_t burstLength; 460 const uint32_t deviceRowBufferSize; 461 const uint32_t devicesPerRank; 462 const uint32_t burstSize; 463 const uint32_t rowBufferSize; 464 const uint32_t columnsPerRowBuffer; 465 const uint32_t ranksPerChannel; 466 const uint32_t banksPerRank; 467 const uint32_t channels; 468 uint32_t rowsPerBank; 469 const uint32_t readBufferSize; 470 const uint32_t writeBufferSize; 471 const uint32_t writeHighThreshold; 472 const uint32_t writeLowThreshold; 473 const uint32_t minWritesPerSwitch; 474 uint32_t writesThisTime; 475 uint32_t readsThisTime; 476 477 /** 478 * Basic memory timing parameters initialized based on parameter 479 * values. 480 */ 481 const Tick tWTR; 482 const Tick tRTW; 483 const Tick tBURST; 484 const Tick tRCD; 485 const Tick tCL; 486 const Tick tRP; 487 const Tick tRAS; 488 const Tick tWR; 489 const Tick tRTP; 490 const Tick tRFC; 491 const Tick tREFI; 492 const Tick tRRD; 493 const Tick tXAW; 494 const uint32_t activationLimit; 495 496 /** 497 * Memory controller configuration initialized based on parameter 498 * values. 499 */ 500 Enums::MemSched memSchedPolicy; 501 Enums::AddrMap addrMapping; 502 Enums::PageManage pageMgmt; 503 504 /** 505 * Max column accesses (read and write) per row, before forefully 506 * closing it. 507 */ 508 const uint32_t maxAccessesPerRow; 509 510 /** 511 * Pipeline latency of the controller frontend. The frontend 512 * contribution is added to writes (that complete when they are in 513 * the write buffer) and reads that are serviced the write buffer. 514 */ 515 const Tick frontendLatency; 516 517 /** 518 * Pipeline latency of the backend and PHY. Along with the 519 * frontend contribution, this latency is added to reads serviced 520 * by the DRAM. 521 */ 522 const Tick backendLatency; 523 524 /** 525 * Till when has the main data bus been spoken for already? 526 */ 527 Tick busBusyUntil; 528 529 /** 530 * Keep track of when a refresh is due. 531 */ 532 Tick refreshDueAt; 533 534 /** 535 * The refresh state is used to control the progress of the 536 * refresh scheduling. When normal operation is in progress the 537 * refresh state is idle. From there, it progresses to the refresh 538 * drain state once tREFI has passed. The refresh drain state 539 * captures the DRAM row active state, as it will stay there until 540 * all ongoing accesses complete. Thereafter all banks are 541 * precharged, and lastly, the DRAM is refreshed. 542 */ 543 enum RefreshState { 544 REF_IDLE = 0, 545 REF_DRAIN, 546 REF_PRE, 547 REF_RUN 548 }; 549 550 RefreshState refreshState; 551 552 /** 553 * The power state captures the different operational states of 554 * the DRAM and interacts with the bus read/write state machine, 555 * and the refresh state machine. In the idle state all banks are 556 * precharged. From there we either go to an auto refresh (as 557 * determined by the refresh state machine), or to a precharge 558 * power down mode. From idle the memory can also go to the active 559 * state (with one or more banks active), and in turn from there 560 * to active power down. At the moment we do not capture the deep 561 * power down and self-refresh state. 562 */ 563 enum PowerState { 564 PWR_IDLE = 0, 565 PWR_REF, 566 PWR_PRE_PDN, 567 PWR_ACT, 568 PWR_ACT_PDN 569 }; 570 571 /** 572 * Since we are taking decisions out of order, we need to keep 573 * track of what power transition is happening at what time, such 574 * that we can go back in time and change history. For example, if 575 * we precharge all banks and schedule going to the idle state, we 576 * might at a later point decide to activate a bank before the 577 * transition to idle would have taken place. 578 */ 579 PowerState pwrStateTrans; 580 581 /** 582 * Current power state. 583 */ 584 PowerState pwrState; 585 586 /** 587 * Schedule a power state transition in the future, and 588 * potentially override an already scheduled transition. 589 * 590 * @param pwr_state Power state to transition to 591 * @param tick Tick when transition should take place 592 */ 593 void schedulePowerEvent(PowerState pwr_state, Tick tick); 594 595 Tick prevArrival; 596 597 /** 598 * The soonest you have to start thinking about the next request 599 * is the longest access time that can occur before 600 * busBusyUntil. Assuming you need to precharge, open a new row, 601 * and access, it is tRP + tRCD + tCL. 602 */ 603 Tick nextReqTime; 604 605 // All statistics that the model needs to capture 606 Stats::Scalar readReqs; 607 Stats::Scalar writeReqs; 608 Stats::Scalar readBursts; 609 Stats::Scalar writeBursts; 610 Stats::Scalar bytesReadDRAM; 611 Stats::Scalar bytesReadWrQ; 612 Stats::Scalar bytesWritten; 613 Stats::Scalar bytesReadSys; 614 Stats::Scalar bytesWrittenSys; 615 Stats::Scalar servicedByWrQ; 616 Stats::Scalar mergedWrBursts; 617 Stats::Scalar neitherReadNorWrite; 618 Stats::Vector perBankRdBursts; 619 Stats::Vector perBankWrBursts; 620 Stats::Scalar numRdRetry; 621 Stats::Scalar numWrRetry; 622 Stats::Scalar totGap; 623 Stats::Vector readPktSize; 624 Stats::Vector writePktSize; 625 Stats::Vector rdQLenPdf; 626 Stats::Vector wrQLenPdf; 627 Stats::Histogram bytesPerActivate; 628 Stats::Histogram rdPerTurnAround; 629 Stats::Histogram wrPerTurnAround; 630 631 // Latencies summed over all requests 632 Stats::Scalar totQLat; 633 Stats::Scalar totMemAccLat; 634 Stats::Scalar totBusLat; 635 636 // Average latencies per request 637 Stats::Formula avgQLat; 638 Stats::Formula avgBusLat; 639 Stats::Formula avgMemAccLat; 640 641 // Average bandwidth 642 Stats::Formula avgRdBW; 643 Stats::Formula avgWrBW; 644 Stats::Formula avgRdBWSys; 645 Stats::Formula avgWrBWSys; 646 Stats::Formula peakBW; 647 Stats::Formula busUtil; 648 Stats::Formula busUtilRead; 649 Stats::Formula busUtilWrite; 650 651 // Average queue lengths 652 Stats::Average avgRdQLen; 653 Stats::Average avgWrQLen; 654 655 // Row hit count and rate 656 Stats::Scalar readRowHits; 657 Stats::Scalar writeRowHits; 658 Stats::Formula readRowHitRate; 659 Stats::Formula writeRowHitRate; 660 Stats::Formula avgGap; 661 662 // DRAM Power Calculation 663 Stats::Formula pageHitRate; 664 Stats::Vector pwrStateTime; 665 666 // Track when we transitioned to the current power state 667 Tick pwrStateTick; 668 669 // To track number of banks which are currently active 670 unsigned int numBanksActive; 671 672 /** @todo this is a temporary workaround until the 4-phase code is 673 * committed. upstream caches needs this packet until true is returned, so 674 * hold onto it for deletion until a subsequent call 675 */ 676 std::vector<PacketPtr> pendingDelete; 677 678 public: 679 680 void regStats(); 681 682 DRAMCtrl(const DRAMCtrlParams* p); 683 684 unsigned int drain(DrainManager* dm); 685 686 virtual BaseSlavePort& getSlavePort(const std::string& if_name, 687 PortID idx = InvalidPortID); 688 689 virtual void init(); 690 virtual void startup(); 691 692 protected: 693 694 Tick recvAtomic(PacketPtr pkt); 695 void recvFunctional(PacketPtr pkt); 696 bool recvTimingReq(PacketPtr pkt); 697 698}; 699 700#endif //__MEM_DRAM_CTRL_HH__ 701