gem5/src/mem/ruby/structures/RubyMemoryControl.hh
David Hashe b6b972da99 ruby: rename System.{hh,cc} to RubySystem.{hh,cc}
The eventual aim of this change is to pass RubySystem pointers through to
objects generated from the SLICC protocol code.

Because some of these objects need to dereference their RubySystem pointers,
they need access to the System.hh header file.

In src/mem/ruby/SConscript, the MakeInclude function creates single-line header
files in the build directory that do nothing except include the corresponding
header file from the source tree.

However, SLICC also generates a list of header files from its symbol table, and
writes it to mem/protocol/Types.hh in the build directory. This code assumes
that the header file name is the same as the class name.

The end result of this is the many of the generated slicc files try to include
RubySystem.hh, when the file they really need is System.hh. The path of least
resistence is just to rename System.hh to RubySystem.hh.

--HG--
rename : src/mem/ruby/system/System.cc => src/mem/ruby/system/RubySystem.cc
rename : src/mem/ruby/system/System.hh => src/mem/ruby/system/RubySystem.hh
2015-09-16 12:03:03 -04:00

205 lines
6.7 KiB
C++

/*
* Copyright (c) 1999-2008 Mark D. Hill and David A. Wood
* Copyright (c) 2012 Advanced Micro Devices, Inc.
* 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.
*/
#ifndef __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__
#define __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__
#include <iostream>
#include <list>
#include <string>
#include "mem/abstract_mem.hh"
#include "mem/protocol/MemoryMsg.hh"
#include "mem/ruby/common/Address.hh"
#include "mem/ruby/profiler/MemCntrlProfiler.hh"
#include "mem/ruby/structures/MemoryNode.hh"
#include "mem/ruby/system/RubySystem.hh"
#include "params/RubyMemoryControl.hh"
// This constant is part of the definition of tFAW; see
// the comments in header to RubyMemoryControl.cc
#define ACTIVATE_PER_TFAW 4
//////////////////////////////////////////////////////////////////////////////
class RubyMemoryControl : public AbstractMemory, public Consumer
{
public:
typedef RubyMemoryControlParams Params;
RubyMemoryControl(const Params *p);
void init();
void reset();
~RubyMemoryControl();
virtual BaseSlavePort& getSlavePort(const std::string& if_name,
PortID idx = InvalidPortID);
DrainState drain() M5_ATTR_OVERRIDE;
void wakeup();
void setDescription(const std::string& name) { m_description = name; };
std::string getDescription() { return m_description; };
// Called from the directory:
bool recvTimingReq(PacketPtr pkt);
void recvFunctional(PacketPtr pkt);
void enqueueMemRef(MemoryNode *memRef);
bool areNSlotsAvailable(int n) { return true; }; // infinite queue length
void print(std::ostream& out) const;
void regStats();
const int getBank(const Addr addr) const;
const int getRank(const Addr addr) const;
// not used in Ruby memory controller
const int getChannel(const Addr addr) const;
const int getRow(const Addr addr) const;
//added by SS
int getBanksPerRank() { return m_banks_per_rank; };
int getRanksPerDimm() { return m_ranks_per_dimm; };
int getDimmsPerChannel() { return m_dimms_per_channel; }
bool functionalRead(Packet *pkt);
uint32_t functionalWrite(Packet *pkt);
private:
void enqueueToDirectory(MemoryNode *req, Cycles latency);
const int getRank(int bank) const;
bool queueReady(int bank);
void issueRequest(int bank);
bool issueRefresh(int bank);
void markTfaw(int rank);
void executeCycle();
// Private copy constructor and assignment operator
RubyMemoryControl (const RubyMemoryControl& obj);
RubyMemoryControl& operator=(const RubyMemoryControl& obj);
private:
// For now, make use of a queued slave port to avoid dealing with
// flow control for the responses being sent back
class MemoryPort : public QueuedSlavePort
{
RespPacketQueue queue;
RubyMemoryControl& memory;
public:
MemoryPort(const std::string& name, RubyMemoryControl& _memory);
protected:
Tick recvAtomic(PacketPtr pkt);
void recvFunctional(PacketPtr pkt);
bool recvTimingReq(PacketPtr);
virtual AddrRangeList getAddrRanges() const;
};
/**
* Our incoming port, for a multi-ported controller add a crossbar
* in front of it
*/
MemoryPort port;
// data members
std::string m_description;
int m_msg_counter;
int m_banks_per_rank;
int m_ranks_per_dimm;
int m_dimms_per_channel;
int m_bank_bit_0;
int m_rank_bit_0;
int m_dimm_bit_0;
unsigned int m_bank_queue_size;
int m_bank_busy_time;
int m_rank_rank_delay;
int m_read_write_delay;
int m_basic_bus_busy_time;
Cycles m_mem_ctl_latency;
int m_refresh_period;
int m_mem_random_arbitrate;
int m_tFaw;
Cycles m_mem_fixed_delay;
int m_total_banks;
int m_total_ranks;
int m_refresh_period_system;
// queues where memory requests live
std::list<MemoryNode *> m_response_queue;
std::list<MemoryNode *> m_input_queue;
std::list<MemoryNode *>* m_bankQueues;
// Each entry indicates number of address-bus cycles until bank
// is reschedulable:
int *m_bankBusyCounter;
int *m_oldRequest;
uint64_t *m_tfaw_shift;
int *m_tfaw_count;
// Each of these indicates number of address-bus cycles until
// we can issue a new request of the corresponding type:
int m_busBusyCounter_Write;
int m_busBusyCounter_ReadNewRank;
int m_busBusyCounter_Basic;
int m_busBusy_WhichRank; // which rank last granted
int m_roundRobin; // which bank queue was last granted
int m_refresh_count; // cycles until next refresh
int m_need_refresh; // set whenever m_refresh_count goes to zero
int m_refresh_bank; // which bank to refresh next
int m_ageCounter; // age of old requests; to detect starvation
int m_idleCount; // watchdog timer for shutting down
MemCntrlProfiler *m_profiler_ptr;
class MemCntrlEvent : public Event
{
public:
MemCntrlEvent(RubyMemoryControl *_mem_cntrl)
{
mem_cntrl = _mem_cntrl;
}
private:
void process() { mem_cntrl->wakeup(); }
RubyMemoryControl* mem_cntrl;
};
MemCntrlEvent m_event;
};
std::ostream& operator<<(std::ostream& out, const RubyMemoryControl& obj);
#endif // __MEM_RUBY_STRUCTURES_MEMORY_CONTROL_HH__