| /* |
| * Copyright (c) 2012-2020 ARM Limited |
| * All rights reserved |
| * |
| * The license below extends only to copyright in the software and shall |
| * not be construed as granting a license to any other intellectual |
| * property including but not limited to intellectual property relating |
| * to a hardware implementation of the functionality of the software |
| * licensed hereunder. You may use the software subject to the license |
| * terms below provided that you ensure that this notice is replicated |
| * unmodified and in its entirety in all distributions of the software, |
| * modified or unmodified, in source code or in binary form. |
| * |
| * Copyright (c) 2013 Amin Farmahini-Farahani |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer; |
| * redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution; |
| * neither the name of the copyright holders nor the names of its |
| * contributors may be used to endorse or promote products derived from |
| * this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /** |
| * @file |
| * NVMInterface declaration |
| */ |
| |
| #ifndef __NVM_INTERFACE_HH__ |
| #define __NVM_INTERFACE_HH__ |
| |
| #include "mem/mem_interface.hh" |
| #include "params/NVMInterface.hh" |
| |
| namespace gem5 |
| { |
| |
| namespace memory |
| { |
| |
| /** |
| * Interface to NVM devices with media specific parameters, |
| * statistics, and functions. |
| * The NVMInterface includes a class for individual ranks |
| * and per rank functions. |
| */ |
| class NVMInterface : public MemInterface |
| { |
| private: |
| /** |
| * NVM rank class simply includes a vector of banks. |
| */ |
| class Rank : public EventManager |
| { |
| public: |
| |
| /** |
| * Current Rank index |
| */ |
| uint8_t rank; |
| |
| /** |
| * Vector of NVM banks. Each rank is made of several banks |
| * that can be accessed in parallel. |
| */ |
| std::vector<Bank> banks; |
| |
| Rank(const NVMInterfaceParams &_p, int _rank, |
| NVMInterface& _nvm); |
| }; |
| |
| /** |
| * NVM specific device and channel characteristics |
| */ |
| const uint32_t maxPendingWrites; |
| const uint32_t maxPendingReads; |
| const bool twoCycleRdWr; |
| |
| /** |
| * NVM specific timing requirements |
| */ |
| const Tick tREAD; |
| const Tick tWRITE; |
| const Tick tSEND; |
| |
| struct NVMStats : public statistics::Group |
| { |
| NVMStats(NVMInterface &nvm); |
| |
| void regStats() override; |
| |
| NVMInterface &nvm; |
| |
| /** NVM stats */ |
| statistics::Scalar readBursts; |
| statistics::Scalar writeBursts; |
| |
| statistics::Vector perBankRdBursts; |
| statistics::Vector perBankWrBursts; |
| |
| // Latencies summed over all requests |
| statistics::Scalar totQLat; |
| statistics::Scalar totBusLat; |
| statistics::Scalar totMemAccLat; |
| |
| // Average latencies per request |
| statistics::Formula avgQLat; |
| statistics::Formula avgBusLat; |
| statistics::Formula avgMemAccLat; |
| |
| statistics::Scalar bytesRead; |
| statistics::Scalar bytesWritten; |
| |
| // Average bandwidth |
| statistics::Formula avgRdBW; |
| statistics::Formula avgWrBW; |
| statistics::Formula peakBW; |
| statistics::Formula busUtil; |
| statistics::Formula busUtilRead; |
| statistics::Formula busUtilWrite; |
| |
| /** NVM stats */ |
| statistics::Histogram pendingReads; |
| statistics::Histogram pendingWrites; |
| statistics::Histogram bytesPerBank; |
| }; |
| NVMStats stats; |
| |
| void processWriteRespondEvent(); |
| EventFunctionWrapper writeRespondEvent; |
| |
| void processReadReadyEvent(); |
| EventFunctionWrapper readReadyEvent; |
| |
| /** |
| * Vector of nvm ranks |
| */ |
| std::vector<Rank*> ranks; |
| |
| /** |
| * Holding queue for non-deterministic write commands, which |
| * maintains writes that have been issued but have not completed |
| * Stored seperately mostly to keep the code clean and help with |
| * events scheduling. |
| * This mimics a buffer on the media controller and therefore is |
| * not added to the main write queue for sizing |
| */ |
| std::list<Tick> writeRespQueue; |
| |
| std::deque<Tick> readReadyQueue; |
| |
| /** |
| * Check if the write response queue is empty |
| * |
| * @param Return true if empty |
| */ |
| bool writeRespQueueEmpty() const { return writeRespQueue.empty(); } |
| |
| /** |
| * Till when must we wait before issuing next read command? |
| */ |
| Tick nextReadAt; |
| |
| // keep track of reads that have issued for which data is either |
| // not yet ready or has not yet been transferred to the ctrl |
| uint16_t numPendingReads; |
| uint16_t numReadDataReady; |
| |
| public: |
| // keep track of the number of reads that have yet to be issued |
| uint16_t numReadsToIssue; |
| |
| /** |
| * Initialize the NVM interface and verify parameters |
| */ |
| void init() override; |
| |
| /** |
| * Setup the rank based on packet received |
| * |
| * @param integer value of rank to be setup. used to index ranks vector |
| * @param are we setting up rank for read or write packet? |
| */ |
| void setupRank(const uint8_t rank, const bool is_read) override; |
| |
| MemPacket* decodePacket(const PacketPtr pkt, Addr pkt_addr, |
| unsigned int size, bool is_read, |
| uint8_t pseudo_channel = 0) override; |
| |
| /** |
| * Check drain state of NVM interface |
| * |
| * @return true if write response queue is empty |
| * |
| */ |
| bool allRanksDrained() const override { return writeRespQueueEmpty(); } |
| |
| /* |
| * @return time to offset next command |
| */ |
| Tick commandOffset() const override { return tBURST; } |
| |
| /** |
| * Check if a burst operation can be issued to the NVM |
| * |
| * @param Return true if RD/WR can issue |
| * for reads, also verfy that ready count |
| * has been updated to a non-zero value to |
| * account for race conditions between events |
| */ |
| bool burstReady(MemPacket* pkt) const override; |
| |
| /** |
| * This function checks if ranks are busy. |
| * This state is true when either: |
| * 1) There is no command with read data ready to transmit or |
| * 2) The NVM inteface has reached the maximum number of outstanding |
| * writes commands. |
| * @param read_queue_empty There are no read queued |
| * @param all_writes_nvm All writes in queue are for NVM interface |
| * @return true of NVM is busy |
| * |
| */ |
| bool isBusy(bool read_queue_empty, bool all_writes_nvm) override; |
| /** |
| * For FR-FCFS policy, find first NVM command that can issue |
| * default to first command to prepped region |
| * |
| * @param queue Queued requests to consider |
| * @param min_col_at Minimum tick for 'seamless' issue |
| * @return an iterator to the selected packet, else queue.end() |
| * @return the tick when the packet selected will issue |
| */ |
| std::pair<MemPacketQueue::iterator, Tick> |
| chooseNextFRFCFS(MemPacketQueue& queue, Tick min_col_at) const override; |
| |
| /** |
| * Add rank to rank delay to bus timing to all NVM banks in alli ranks |
| * when access to an alternate interface is issued |
| * |
| * param cmd_at Time of current command used as starting point for |
| * addition of rank-to-rank delay |
| */ |
| void addRankToRankDelay(Tick cmd_at) override; |
| |
| /** |
| * Following two functions are not required for nvm interface |
| */ |
| void respondEvent(uint8_t rank) override { }; |
| |
| void checkRefreshState(uint8_t rank) override { }; |
| |
| /** |
| * Select read command to issue asynchronously |
| */ |
| void chooseRead(MemPacketQueue& queue) override; |
| |
| /* |
| * Function to calulate unloaded access latency |
| */ |
| Tick accessLatency() const override { return (tREAD + tSEND); } |
| |
| /** |
| * Check if the write response queue has reached defined threshold |
| * |
| * @param Return true if full |
| */ |
| bool |
| writeRespQueueFull() const override |
| { |
| return writeRespQueue.size() == maxPendingWrites; |
| } |
| |
| bool |
| readsWaitingToIssue() const override |
| { |
| return ((numReadsToIssue != 0) && |
| (numPendingReads < maxPendingReads)); |
| } |
| |
| /** |
| * Actually do the burst and update stats. |
| * |
| * @param pkt The packet created from the outside world pkt |
| * @param next_burst_at Minimum bus timing requirement from controller |
| * @return pair, tick when current burst is issued and |
| * tick when next burst can issue |
| */ |
| std::pair<Tick, Tick> |
| doBurstAccess(MemPacket* pkt, Tick next_burst_at, |
| const std::vector<MemPacketQueue>& queue) override; |
| |
| /** |
| * The next three functions are DRAM-specific and will be ignored by NVM. |
| */ |
| void drainRanks() override { } |
| void suspend() override { } |
| void startup() override { } |
| |
| NVMInterface(const NVMInterfaceParams &_p); |
| }; |
| |
| } // namespace memory |
| } // namespace gem5 |
| |
| #endif //__NVM_INTERFACE_HH__ |