diff --git a/src/mem/gems_common/std-includes.hh b/src/mem/gems_common/std-includes.hh index 619214f1dc..d6062337fd 100644 --- a/src/mem/gems_common/std-includes.hh +++ b/src/mem/gems_common/std-includes.hh @@ -26,6 +26,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * $Id: std-includes.hh,v 3.7 2003/02/24 21:05:24 xu Exp $ + */ + #ifndef INCLUDES_H #define INCLUDES_H diff --git a/src/mem/gems_common/util.cc b/src/mem/gems_common/util.cc index a64da15a69..403be383f5 100644 --- a/src/mem/gems_common/util.cc +++ b/src/mem/gems_common/util.cc @@ -30,8 +30,7 @@ * $Id$ */ -#include - +#include "assert.hh" #include "mem/gems_common/util.hh" // Split a string into a head and tail strings on the specified @@ -43,7 +42,7 @@ string string_split(string& str, char split_character) string head = ""; string tail = ""; - unsigned counter = 0; + uint counter = 0; while(counter < str.size()) { if (str[counter] == split_character) { counter++; @@ -91,6 +90,19 @@ float string_to_float(string& str) return ret; } +bool string_to_bool(const string & str) +{ + string lower(str); + for (size_t i=0;i0); Time current_time = g_eventQueue_ptr->getTime(); Time arrival_time = 0; - if (!RANDOMIZATION || (m_randomization == false)) { + if (!RubySystem::getRandomization() || (m_randomization == false)) { // No randomization arrival_time = current_time + delta; @@ -294,7 +296,7 @@ void MessageBuffer::pop() { DEBUG_MSG(QUEUE_COMP,MedPrio,"pop from " + m_name); assert(isReady()); - m_prio_heap.extractMin(); + Time ready_time = m_prio_heap.extractMin().m_time; // record previous size and time so the current buffer size isn't adjusted until next cycle if (m_time_last_time_pop < g_eventQueue_ptr->getTime()) { m_size_at_cycle_start = m_size; @@ -321,13 +323,13 @@ void MessageBuffer::clear() void MessageBuffer::recycle() { - // const int RECYCLE_LATENCY = 3; + // const int RubyConfig::getRecycleLatency() = 3; DEBUG_MSG(QUEUE_COMP,MedPrio,"recycling " + m_name); assert(isReady()); MessageBufferNode node = m_prio_heap.extractMin(); - node.m_time = g_eventQueue_ptr->getTime() + RECYCLE_LATENCY; + node.m_time = g_eventQueue_ptr->getTime() + m_recycle_latency; m_prio_heap.insert(node); - g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + RECYCLE_LATENCY); + g_eventQueue_ptr->scheduleEventAbsolute(m_consumer_ptr, g_eventQueue_ptr->getTime() + m_recycle_latency); } int MessageBuffer::setAndReturnDelayCycles(MsgPtr& message) diff --git a/src/mem/ruby/buffers/MessageBuffer.hh b/src/mem/ruby/buffers/MessageBuffer.hh index b58203a934..3ca6790d06 100644 --- a/src/mem/ruby/buffers/MessageBuffer.hh +++ b/src/mem/ruby/buffers/MessageBuffer.hh @@ -60,6 +60,7 @@ public: // Public Methods static void printConfig(ostream& out) {} + void setRecycleLatency(int recycle_latency) { m_recycle_latency = recycle_latency; } // TRUE if head of queue timestamp <= SystemTime bool isReady() const { @@ -105,6 +106,9 @@ public: void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } private: + //added by SS + int m_recycle_latency; + // Private Methods int setAndReturnDelayCycles(MsgPtr& message); diff --git a/src/mem/ruby/common/Address.hh b/src/mem/ruby/common/Address.hh index d72fbf38ae..b6899d1acc 100644 --- a/src/mem/ruby/common/Address.hh +++ b/src/mem/ruby/common/Address.hh @@ -1,3 +1,4 @@ + /* * Copyright (c) 1999 Mark D. Hill and David A. Wood * All rights reserved. @@ -26,12 +27,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * $Id$ + */ + #ifndef ADDRESS_H #define ADDRESS_H #include #include "mem/ruby/common/Global.hh" -#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/system/System.hh" #include "mem/ruby/system/NodeID.hh" #include "mem/ruby/system/MachineID.hh" @@ -63,17 +68,16 @@ public: physical_address_t maskHighOrderBits(int number) const; physical_address_t shiftLowOrderBits(int number) const; physical_address_t getLineAddress() const - { return bitSelect(RubyConfig::dataBlockBits(), ADDRESS_WIDTH); } + { return bitSelect(RubySystem::getBlockSizeBits(), ADDRESS_WIDTH); } physical_address_t getOffset() const - { return bitSelect(0, RubyConfig::dataBlockBits()-1); } + { return bitSelect(0, RubySystem::getBlockSizeBits()-1); } - void makeLineAddress() { m_address = maskLowOrderBits(RubyConfig::dataBlockBits()); } + void makeLineAddress() { m_address = maskLowOrderBits(RubySystem::getBlockSizeBits()); } // returns the next stride address based on line address void makeNextStrideAddress( int stride) { - m_address = maskLowOrderBits(RubyConfig::dataBlockBits()) - + RubyConfig::dataBlockBytes()*stride; + m_address = maskLowOrderBits(RubySystem::getBlockSizeBits()) + + RubySystem::getBlockSizeBytes()*stride; } - void makePageAddress() { m_address = maskLowOrderBits(RubyConfig::pageSizeBits()); } int getBankSetNum() const; int getBankSetDist() const; @@ -103,6 +107,7 @@ private: inline Address line_address(const Address& addr) { Address temp(addr); temp.makeLineAddress(); return temp; } +/* inline Address next_stride_address(const Address& addr, int stride) { Address temp = addr; @@ -110,9 +115,7 @@ Address next_stride_address(const Address& addr, int stride) { temp.setAddress(temp.maskHighOrderBits(ADDRESS_WIDTH-RubyConfig::memorySizeBits())); // surpress wrap-around problem return temp; } - -inline -Address page_address(const Address& addr) { Address temp(addr); temp.makePageAddress(); return temp; } +*/ // Output operator declaration ostream& operator<<(ostream& out, const Address& obj); @@ -202,17 +205,19 @@ physical_address_t Address::shiftLowOrderBits(int number) const inline integer_t Address::memoryModuleIndex() const { - integer_t index = bitSelect(RubyConfig::dataBlockBits()+RubyConfig::memoryBits(), ADDRESS_WIDTH); + integer_t index = bitSelect(RubySystem::getBlockSizeBits()+RubySystem::getMemorySizeBits(), ADDRESS_WIDTH); assert (index >= 0); + /* if (index >= RubyConfig::memoryModuleBlocks()) { - cerr << " memoryBits: " << RubyConfig::memoryBits() << " memorySizeBits: " << RubyConfig::memorySizeBits() - << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush + cerr << " memoryBits: " << RubySystem::getMemorySizeBits() << " memorySizeBits: " << RubySystem::getMemorySizeBits() + << " Address: " << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]" << flush << "error: limit exceeded. " << - " dataBlockBits: " << RubyConfig::dataBlockBits() << + " getDataBlockBits: " << RubySystem::getBlockSizeBits() << " memoryModuleBlocks: " << RubyConfig::memoryModuleBlocks() << " index: " << index << endl; } assert (index < RubyConfig::memoryModuleBlocks()); + */ return index; // Index indexHighPortion = address.bitSelect(MEMORY_SIZE_BITS-1, PAGE_SIZE_BITS+NUMBER_OF_MEMORY_MODULE_BITS); @@ -239,7 +244,7 @@ ADDRESS_WIDTH MEMORY_SIZE_BITS PAGE_SIZE_BITS DATA_BLOCK_BITS inline void Address::print(ostream& out) const { - out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush; + out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubySystem::getBlockSizeBits()) << dec << "]" << flush; } class Address; diff --git a/src/mem/ruby/common/Consumer.hh b/src/mem/ruby/common/Consumer.hh index 34cd7864c2..4a14ca20fc 100644 --- a/src/mem/ruby/common/Consumer.hh +++ b/src/mem/ruby/common/Consumer.hh @@ -53,7 +53,8 @@ public: virtual ~Consumer() { } // Public Methods - pure virtual methods - void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }} + // void triggerWakeup() { Time time = g_eventQueue_ptr->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }} + void triggerWakeup(RubyEventQueue * eventQueue) { Time time = eventQueue->getTime(); if (m_last_wakeup != time) { wakeup(); m_last_wakeup = time; }} virtual void wakeup() = 0; virtual void print(ostream& out) const = 0; const Time& getLastScheduledWakeup() const { return m_last_scheduled_wakeup; } diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc index ce72bc7f46..5e6b8338e4 100644 --- a/src/mem/ruby/common/DataBlock.cc +++ b/src/mem/ruby/common/DataBlock.cc @@ -1,91 +1,16 @@ -/* - * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood - * 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. - */ - -/* - * $Id$ - */ - #include "mem/ruby/common/DataBlock.hh" -DataBlock::DataBlock() +DataBlock & +DataBlock::operator=(const DataBlock & obj) { - if (DATA_BLOCK || XACT_MEMORY) { - m_data.setSize(RubyConfig::dataBlockBytes()); - } - clear(); -} - -DataBlock::~DataBlock() -{ - -} - -void DataBlock::clear() -{ - int size = m_data.size(); - for (int i = 0; i < size; i++) { - m_data[i] = 0; - } -} - -bool DataBlock::equal(const DataBlock& obj) const -{ - bool value = true; - int size = m_data.size(); - for (int i = 0; i < size; i++) { - value = value && (m_data[i] == obj.m_data[i]); - } - return value; -} - -void DataBlock::print(ostream& out) const -{ - int size = m_data.size(); - for (int i = 0; i < size; i+=4) { - out << hex << *((uint32*)(&(m_data[i]))) << " "; - } - out << dec << "]" << flush; -} - -uint8 DataBlock::getByte(int whichByte) const -{ - if (DATA_BLOCK || XACT_MEMORY) { - return m_data[whichByte]; + if (this == &obj) { + // assert(false); } else { - return 0; + if (!m_alloc) + m_data = new uint8[RubySystem::getBlockSizeBytes()]; + memcpy(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); + m_alloc = true; } + return *this; } - -void DataBlock::setByte(int whichByte, uint8 data) -{ - if (DATA_BLOCK || XACT_MEMORY) { - m_data[whichByte] = data; - } -} - diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 8711cb7404..2a0811f765 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -31,29 +31,41 @@ #define DATABLOCK_H #include "mem/ruby/common/Global.hh" -#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/system/System.hh" #include "mem/gems_common/Vector.hh" class DataBlock { -public: + public: // Constructors - DataBlock(); + DataBlock() {alloc();} + DataBlock(const DataBlock & cp) { + m_data = new uint8[RubySystem::getBlockSizeBytes()]; + memcpy(m_data, cp.m_data, RubySystem::getBlockSizeBytes()); + m_alloc = true; + } // Destructor - ~DataBlock(); + ~DataBlock() { if(m_alloc) delete [] m_data;} + + DataBlock& operator=(const DataBlock& obj); // Public Methods + void assign(uint8* data); + void clear(); uint8 getByte(int whichByte) const; + const uint8* getData(int offset, int len) const; void setByte(int whichByte, uint8 data); + void setData(uint8* data, int offset, int len); + void copyPartial(const DataBlock & dblk, int offset, int len); bool equal(const DataBlock& obj) const; void print(ostream& out) const; private: - // Private Methods - + void alloc(); // Data Members (m_ prefix) - Vector m_data; + uint8* m_data; + bool m_alloc; }; // Output operator declaration @@ -61,6 +73,78 @@ ostream& operator<<(ostream& out, const DataBlock& obj); bool operator==(const DataBlock& obj1, const DataBlock& obj2); +// inline functions for speed + +inline +void DataBlock::assign(uint8* data) +{ + delete [] m_data; + m_data = data; + m_alloc = false; +} + +inline +void DataBlock::alloc() +{ + m_data = new uint8[RubySystem::getBlockSizeBytes()]; + m_alloc = true; + clear(); +} + +inline +void DataBlock::clear() +{ + memset(m_data, 0, RubySystem::getBlockSizeBytes()); +} + +inline +bool DataBlock::equal(const DataBlock& obj) const +{ + return !memcmp(m_data, obj.m_data, RubySystem::getBlockSizeBytes()); +} + +inline +void DataBlock::print(ostream& out) const +{ + int size = RubySystem::getBlockSizeBytes(); + out << "[ "; + for (int i = 0; i < size; i+=4) { + out << hex << *((uint32*)(&(m_data[i]))) << " "; + } + out << dec << "]" << flush; +} + +inline +uint8 DataBlock::getByte(int whichByte) const +{ + return m_data[whichByte]; +} + +inline +const uint8* DataBlock::getData(int offset, int len) const +{ + assert(offset + len <= RubySystem::getBlockSizeBytes()); + return &m_data[offset]; +} + +inline +void DataBlock::setByte(int whichByte, uint8 data) +{ + m_data[whichByte] = data; +} + +inline +void DataBlock::setData(uint8* data, int offset, int len) +{ + assert(offset + len <= RubySystem::getBlockSizeBytes()); + memcpy(&m_data[offset], data, len); +} + +inline +void DataBlock::copyPartial(const DataBlock & dblk, int offset, int len) +{ + setData(&dblk.m_data[offset], offset, len); +} // ******************* Definitions ******************* diff --git a/src/mem/ruby/common/Debug.cc b/src/mem/ruby/common/Debug.cc index 02f4069ee8..c1a6e16d07 100644 --- a/src/mem/ruby/common/Debug.cc +++ b/src/mem/ruby/common/Debug.cc @@ -38,36 +38,28 @@ #include "mem/ruby/common/Global.hh" #include "mem/ruby/common/Debug.hh" #include "mem/ruby/eventqueue/RubyEventQueue.hh" +#include "mem/gems_common/util.hh" class Debug; extern Debug* g_debug_ptr; std::ostream * debug_cout_ptr; -struct DebugComponentData -{ - const char *desc; - const char ch; -}; +bool Debug::m_protocol_trace = false; // component character list -DebugComponentData debugComponents[] = +const char DEFINE_COMP_CHAR[] = { - {"System", 's' }, - {"Node", 'N' }, - {"Queue", 'q' }, - {"Event Queue", 'e' }, - {"Network", 'n' }, - {"Sequencer", 'S' }, - {"Tester", 't' }, - {"Generated", 'g' }, - {"SLICC", 'l' }, - {"Network Queues", 'Q' }, - {"Time", 'T' }, - {"Network Internals", 'i' }, - {"Store Buffer", 'b' }, - {"Cache", 'c' }, - {"Predictor", 'p' }, - {"Allocator", 'a' }, +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) character, +#include "Debug.def" +}; + +// component description list +const char* DEFINE_COMP_DESCRIPTION[] = +{ +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) description, +#include "Debug.def" }; extern "C" void changeDebugVerbosity(VerbosityLevel vb); @@ -83,6 +75,32 @@ void changeDebugFilter(int filter) g_debug_ptr->setFilter(filter); } +Debug::Debug() +{ + m_verbosityLevel = No_Verb; + m_starting_cycle = ~0; + clearFilter(); + debug_cout_ptr = &cout; +} + +Debug::Debug( const string & name, const vector & argv ) +{ + for (size_t i=0;i #include -#include "config/ruby_debug.hh" -#include "mem/ruby/common/Global.hh" - extern std::ostream * debug_cout_ptr; // component enumeration enum DebugComponents { - SYSTEM_COMP, - NODE_COMP, - QUEUE_COMP, - EVENTQUEUE_COMP, - NETWORK_COMP, - SEQUENCER_COMP, - TESTER_COMP, - GENERATED_COMP, - SLICC_COMP, - NETWORKQUEUE_COMP, - TIME_COMP, - NETWORK_INTERNALS_COMP, - STOREBUFFER_COMP, - CACHE_COMP, - PREDICTOR_COMP, - ALLOCATOR_COMP, - NUMBER_OF_COMPS +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) component, +#include "Debug.def" + NUMBER_OF_COMPS }; enum PriorityLevel {HighPrio, MedPrio, LowPrio}; @@ -70,6 +54,8 @@ enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb}; class Debug { public: // Constructors + Debug(); + Debug( const string & name, const vector & argv ); Debug( const char *filterString, const char *verboseString, Time filterStartTime, const char *filename ); @@ -77,6 +63,7 @@ public: ~Debug(); // Public Methods + static bool getProtocolTrace() { return m_protocol_trace; } bool validDebug(int module, PriorityLevel priority); void printVerbosity(ostream& out) const; void setVerbosity(VerbosityLevel vb); @@ -108,6 +95,7 @@ private: Debug& operator=(const Debug& obj); // Data Members (m_ prefix) + static bool m_protocol_trace; VerbosityLevel m_verbosityLevel; int m_filter; Time m_starting_cycle; @@ -155,7 +143,7 @@ const bool ASSERT_FLAG = true; << __PRETTY_FUNCTION__ << " in "\ << __FILE__ << ":"\ << __LINE__ << endl << flush;\ - if(isatty(STDERR_FILENO)) {\ + if(isatty(STDIN_FILENO)) {\ cerr << "At this point you might want to attach a debug to ";\ cerr << "the running and get to the" << endl;\ cerr << "crash site; otherwise press enter to continue" << endl;\ @@ -176,7 +164,7 @@ const bool ASSERT_FLAG = true; << __PRETTY_FUNCTION__ << " in "\ << __FILE__ << ":"\ << __LINE__ << endl << flush;\ - if(isatty(STDERR_FILENO)) {\ + if(isatty(STDIN_FILENO)) {\ cerr << "press enter to continue" << endl;\ cerr << "PID: " << getpid();\ cerr << endl << flush; \ @@ -303,5 +291,5 @@ const bool ASSERT_FLAG = true; }\ } -#endif // __MEM_RUBY_DEBUG_HH__ +#endif //DEBUG_H diff --git a/src/mem/ruby/common/Driver.hh b/src/mem/ruby/common/Driver.hh index 38bdbbf911..db8279fa54 100644 --- a/src/mem/ruby/common/Driver.hh +++ b/src/mem/ruby/common/Driver.hh @@ -27,6 +27,13 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +/* + * $Id$ + * + * Description: + * + */ + #ifndef DRIVER_H #define DRIVER_H @@ -34,7 +41,6 @@ #include "mem/ruby/common/Consumer.hh" #include "mem/ruby/system/NodeID.hh" #include "mem/protocol/CacheRequestType.hh" -#include "mem/packet.hh" class RubySystem; class SubBlock; @@ -52,10 +58,15 @@ public: // Public Methods virtual void get_network_config() {} - virtual void hitCallback(Packet* pkt) = 0; + virtual void dmaHitCallback() = 0; + virtual void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) = 0; // Called by sequencer + virtual void conflictCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { assert(0) }; // Called by sequencer virtual integer_t getInstructionCount(int procID) const { return 1; } virtual integer_t getCycleCount(int procID) const { return 1; } - + virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);} + virtual int inTransaction(int procID, int thread ) const{ + cout << "Driver.hh inTransaction " << endl; +return false; } //called by Sequencer virtual void printDebug(){} //called by Sequencer virtual void printStats(ostream& out) const = 0; @@ -63,6 +74,8 @@ public: virtual void printConfig(ostream& out) const = 0; + //virtual void abortCallback(NodeID proc){} + virtual integer_t readPhysicalMemory(int procID, physical_address_t address, int len ){ ASSERT(0); return 0; } diff --git a/src/mem/ruby/common/Global.hh b/src/mem/ruby/common/Global.hh index 205b2bcb20..591ffed1ea 100644 --- a/src/mem/ruby/common/Global.hh +++ b/src/mem/ruby/common/Global.hh @@ -32,9 +32,10 @@ * * */ -#ifndef __MEM_RUBY_GLOBAL_HH__ -#define __MEM_RUBY_GLOBAL_HH__ +#ifndef GLOBAL_H +#define GLOBAL_H +/* #ifdef SINGLE_LEVEL_CACHE const bool TWO_LEVEL_CACHE = false; #define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // currently all protocols require L1s == nodes @@ -60,24 +61,11 @@ const bool TWO_LEVEL_CACHE = true; #define DIRECTORY_MEMBER_VARIABLE m_Directory_directory_vec[m_version] #define TBE_TABLE_MEMBER_VARIABLE m_L1Cache_TBEs_vec[m_version] -typedef unsigned char uint8; -typedef unsigned int uint32; -typedef unsigned long long uint64; +*/ -typedef signed char int8; -typedef int int32; -typedef long long int64; - -typedef long long integer_t; -typedef unsigned long long uinteger_t; - -typedef int64 Time; -typedef uint64 physical_address_t; -typedef uint64 la_t; -typedef uint64 pa_t; -typedef integer_t simtime_t; // external includes for all classes +#include "mem/ruby/common/TypeDefines.hh" #include "mem/gems_common/std-includes.hh" #include "mem/ruby/common/Debug.hh" @@ -85,6 +73,7 @@ typedef integer_t simtime_t; typedef Time LogicalTime; typedef int64 Index; // what the address bit ripper returns typedef int word; // one word of a cache line +typedef unsigned int uint; typedef int SwitchID; typedef int LinkID; @@ -105,5 +94,5 @@ extern inline int max_tokens() } -#endif // __MEM_RUBY_GLOBAL_HH__ +#endif //GLOBAL_H diff --git a/src/mem/ruby/common/Set.cc b/src/mem/ruby/common/Set.cc index 4cb40a2465..6f01c4043e 100644 --- a/src/mem/ruby/common/Set.cc +++ b/src/mem/ruby/common/Set.cc @@ -40,6 +40,7 @@ // set sizes #include "mem/ruby/common/Set.hh" +#include "mem/ruby/system/System.hh" #include "mem/ruby/config/RubyConfig.hh" #if __amd64__ || __LP64__ @@ -51,7 +52,7 @@ Set::Set() { m_p_nArray = NULL; - setSize(RubyConfig::numberOfProcessors()); + setSize(RubySystem::getNumberOfSequencers()); } // copy constructor @@ -511,7 +512,7 @@ void Set::setSize(int size) #endif // __32BITS__ // decide whether to use dynamic or static alloction - if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubyConfig.h + if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubyConfig.hh // its OK to use the static allocation, and it will // probably be faster (as m_nArrayLen is already in the // cache and they will probably share the same cache line) @@ -560,7 +561,7 @@ void Set::print(ostream& out) const return; } char buff[24]; - out << "[Set 0x "; + out << "[Set (" << m_nSize << ") 0x "; for (int i=m_nArrayLen-1; i>=0; i--) { #ifdef __32BITS__ sprintf(buff,"%08X ",m_p_nArray[i]); diff --git a/src/mem/ruby/common/SubBlock.cc b/src/mem/ruby/common/SubBlock.cc index 568d3106a1..de40e3f7de 100644 --- a/src/mem/ruby/common/SubBlock.cc +++ b/src/mem/ruby/common/SubBlock.cc @@ -42,16 +42,6 @@ SubBlock::SubBlock(const Address& addr, int size) } } -SubBlock::SubBlock(const Address& addr, const Address& logicalAddress, int size) -{ - m_address = addr; - m_logicalAddress = logicalAddress; - setSize(size); - for(int i=0; i= m_address.getAddress()) && (addr.getAddress() < (m_address.getAddress()+getSize()))); } - // uint8 getByte(const Address& addr) { return m_data[addr.getAddress() - m_address.getAddress()]; } void internalMergeTo(DataBlock& data) const; void internalMergeFrom(const DataBlock& data); // Data Members (m_ prefix) Address m_address; - Address m_logicalAddress; - Vector m_data; + Vector m_data; }; // Output operator declaration diff --git a/src/mem/ruby/common/TypeDefines.hh b/src/mem/ruby/common/TypeDefines.hh new file mode 100644 index 0000000000..97b3cd8a4a --- /dev/null +++ b/src/mem/ruby/common/TypeDefines.hh @@ -0,0 +1,23 @@ + +#ifndef TYPEDEFINES_H +#define TYPEDEFINES_H + + +typedef unsigned char uint8; +typedef unsigned int uint32; +typedef unsigned long long uint64; + +typedef signed char int8; +typedef int int32; +typedef long long int64; + +typedef long long integer_t; +typedef unsigned long long uinteger_t; + +typedef int64 Time; +typedef uint64 physical_address_t; +typedef uint64 la_t; +typedef uint64 pa_t; +typedef integer_t simtime_t; + +#endif diff --git a/src/mem/ruby/config/MI_example-homogeneous.rb b/src/mem/ruby/config/MI_example-homogeneous.rb new file mode 100644 index 0000000000..8c2eef0091 --- /dev/null +++ b/src/mem/ruby/config/MI_example-homogeneous.rb @@ -0,0 +1,64 @@ +#!/usr/bin/ruby +# +# Creates a homogeneous CMP system with a single unified cache per +# core and a crossbar network. Uses the default parameters listed +# below, which can be overridden if a wrapper script sets the hash +# libruby_args. +# + +require "cfg.rb" + +# default values + +num_cores = 16 +L1_CACHE_SIZE_KB = 32 +L1_CACHE_ASSOC = 8 +L1_CACHE_LATENCY = "auto" +num_memories = 2 +memory_size_mb = 1024 +NUM_DMA = 1 + +# check for overrides + +for i in 0..$*.size-1 do + if $*[i] == "-p" + num_cores = $*[i+1].to_i + i = i+1 + elsif $*[i] == "-m" + num_memories = $*[i+1].to_i + i = i+1 + elsif $*[i] == "-s" + memory_size_mb = $*[i+1].to_i + i = i + 1 + end +end + +net_ports = Array.new +iface_ports = Array.new + +num_cores.times { |n| + cache = SetAssociativeCache.new("l1u_"+n.to_s, L1_CACHE_SIZE_KB, L1_CACHE_LATENCY, L1_CACHE_ASSOC, "PSEUDO_LRU") + sequencer = Sequencer.new("Sequencer_"+n.to_s, cache, cache) + iface_ports << sequencer + net_ports << MI_example_CacheController.new("L1CacheController_"+n.to_s, + "L1Cache", + [cache], + sequencer) +} +num_memories.times { |n| + directory = DirectoryMemory.new("DirectoryMemory_"+n.to_s, memory_size_mb/num_memories) + memory_control = MemoryControl.new("MemoryControl_"+n.to_s) + net_ports << MI_example_DirectoryController.new("DirectoryController_"+n.to_s, + "Directory", + directory, memory_control) +} +NUM_DMA.times { |n| + dma_sequencer = DMASequencer.new("DMASequencer_"+n.to_s) + iface_ports << dma_sequencer + net_ports << DMAController.new("DMAController_"+n.to_s, "DMA", dma_sequencer) +} + +topology = CrossbarTopology.new("theTopology", net_ports) +on_chip_net = Network.new("theNetwork", topology) + +RubySystem.init(iface_ports, on_chip_net) diff --git a/src/mem/ruby/config/RubyConfig.cc b/src/mem/ruby/config/RubyConfig.cc index fe58a74d3b..987a3d81de 100644 --- a/src/mem/ruby/config/RubyConfig.cc +++ b/src/mem/ruby/config/RubyConfig.cc @@ -36,135 +36,191 @@ * */ -#include "config/ruby_debug.hh" #include "mem/ruby/config/RubyConfig.hh" -#include "mem/protocol/protocol_name.hh" +//#include "mem/protocol/protocol_name.hh" #include "mem/gems_common/util.hh" -#include "mem/protocol/Protocol.hh" + +#define CONFIG_DEF_FILE "mem/ruby/config/config.hh" + +#define ERROR_MSG(MESSAGE)\ +{\ + cerr << "Fatal Error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + abort();\ +} + +// declare all configuration variables +#define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + bool RubyConfig::m_##NAME = DEFAULT_VALUE; +#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + const char* RubyConfig::m_##NAME = DEFAULT_VALUE; +#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + uint64 RubyConfig::m_##NAME = DEFAULT_VALUE; +#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + int RubyConfig::m_##NAME = DEFAULT_VALUE; +#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + TYPE* RubyConfig::m_##NAME = NULL; +#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + TYPE** RubyConfig::m_##NAME = NULL; +#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + TYPE*** RubyConfig::m_##NAME = NULL; +#include CONFIG_DEF_FILE +#undef PARAM_BOOL +#undef PARAM_STRING +#undef PARAM_ULONG +#undef PARAM +#undef PARAM_ARRAY +#undef PARAM_ARRAY2D +#undef PARAM_ARRAY3D #define CHECK_POWER_OF_2(N) { if (!is_power_of_2(N)) { ERROR_MSG(#N " must be a power of 2."); }} #define CHECK_ZERO(N) { if (N != 0) { ERROR_MSG(#N " must be zero at initialization."); }} #define CHECK_NON_ZERO(N) { if (N == 0) { ERROR_MSG(#N " must be non-zero."); }} +uint32 RubyConfig::m_data_block_mask; + +void RubyConfig::reset() +{ + #define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + m_##NAME = DEFAULT_VALUE; +#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + m_##NAME = DEFAULT_VALUE; +#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + m_##NAME = DEFAULT_VALUE; +#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + m_##NAME = DEFAULT_VALUE; +#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + m_##NAME = new TYPE[DEFAULT_ARRAY_SIZE]; \ + for (int i=0; i= g_PROCS_PER_CHIP); // obviously can't have less processors than procs/chip - g_NUM_CHIPS = g_NUM_PROCESSORS/g_PROCS_PER_CHIP; - ASSERT(g_NUM_L2_BANKS >= g_NUM_CHIPS); // cannot have a single L2cache across multiple chips + assert(m_NUM_PROCESSORS >= m_ProcsPerChip); // obviously can't have less processors than procs/chip + m_NUM_CHIPS = m_NUM_PROCESSORS/m_ProcsPerChip; + assert(m_NUM_L2_BANKS >= m_NUM_CHIPS); // cannot have a single L2cache across multiple chips - g_NUM_L2_BANKS_PER_CHIP = g_NUM_L2_BANKS/g_NUM_CHIPS; + m_NUM_L2_BANKS_PER_CHIP = m_NUM_L2_BANKS/m_NUM_CHIPS; - ASSERT(L2_CACHE_NUM_SETS_BITS > log_int(g_NUM_L2_BANKS_PER_CHIP)); // cannot have less than one set per bank - L2_CACHE_NUM_SETS_BITS = L2_CACHE_NUM_SETS_BITS - log_int(g_NUM_L2_BANKS_PER_CHIP); - - if (g_NUM_CHIPS > g_NUM_MEMORIES) { - g_NUM_MEMORIES_PER_CHIP = 1; // some chips have a memory, others don't + if (m_NUM_CHIPS > m_NUM_MEMORIES) { + m_NUM_MEMORIES_PER_CHIP = 1; // some chips have a memory, others don't } else { - g_NUM_MEMORIES_PER_CHIP = g_NUM_MEMORIES/g_NUM_CHIPS; + m_NUM_MEMORIES_PER_CHIP = m_NUM_MEMORIES/m_NUM_CHIPS; } - g_NUM_CHIP_BITS = log_int(g_NUM_CHIPS); - g_MEMORY_SIZE_BITS = log_int(g_MEMORY_SIZE_BYTES); - g_DATA_BLOCK_BITS = log_int(g_DATA_BLOCK_BYTES); - g_PAGE_SIZE_BITS = log_int(g_PAGE_SIZE_BYTES); - g_NUM_PROCESSORS_BITS = log_int(g_NUM_PROCESSORS); - g_NUM_L2_BANKS_BITS = log_int(g_NUM_L2_BANKS); - g_NUM_L2_BANKS_PER_CHIP_BITS = log_int(g_NUM_L2_BANKS_PER_CHIP); - g_NUM_MEMORIES_BITS = log_int(g_NUM_MEMORIES); - g_PROCS_PER_CHIP_BITS = log_int(g_PROCS_PER_CHIP); + m_NUM_CHIP_BITS = log_int(m_NUM_CHIPS); + m_MEMORY_SIZE_BITS = log_int(m_MemorySizeBytes); - g_MEMORY_MODULE_BITS = g_MEMORY_SIZE_BITS - g_DATA_BLOCK_BITS - g_NUM_MEMORIES_BITS; - g_MEMORY_MODULE_BLOCKS = (int64(1) << g_MEMORY_MODULE_BITS); + m_data_block_mask = ~ (~0 << m_DATA_BLOCK_BITS); - if ((!Protocol::m_CMP) && (g_PROCS_PER_CHIP > 1)) { - ERROR_MSG("Non-CMP protocol should set g_PROCS_PER_CHIP to 1"); - } + m_NUM_PROCESSORS_BITS = log_int(m_NUM_PROCESSORS); + m_NUM_L2_BANKS_BITS = log_int(m_NUM_L2_BANKS); + m_NUM_L2_BANKS_PER_CHIP_BITS = log_int(m_NUM_L2_BANKS_PER_CHIP); + m_NUM_MEMORIES_BITS = log_int(m_NUM_MEMORIES); + m_PROCS_PER_CHIP_BITS = log_int(m_ProcsPerChip); + + m_MEMORY_MODULE_BITS = m_MEMORY_SIZE_BITS - m_DATA_BLOCK_BITS - m_NUM_MEMORIES_BITS; + m_MEMORY_MODULE_BLOCKS = (int64(1) << m_MEMORY_MODULE_BITS); + + */ // Randomize the execution - srandom(g_RANDOM_SEED); -} - -int RubyConfig::L1CacheNumToL2Base(NodeID L1CacheNum) -{ - return L1CacheNum/g_PROCS_PER_CHIP; + // srandom(m_RandomSeed); } static void print_parameters(ostream& out) { -#define PARAM(NAME) { out << #NAME << ": " << NAME << endl; } -#define PARAM_UINT(NAME) { out << #NAME << ": " << NAME << endl; } -#define PARAM_ULONG(NAME) { out << #NAME << ": " << NAME << endl; } -#define PARAM_BOOL(NAME) { out << #NAME << ": " << bool_to_string(NAME) << endl; } -#define PARAM_DOUBLE(NAME) { out << #NAME << ": " << NAME << endl; } -#define PARAM_STRING(NAME) { assert(NAME != NULL); out << #NAME << ": " << string(NAME) << endl; } -#define PARAM_ARRAY(PTYPE, NAME, ARRAY_SIZE) \ - { \ - out << #NAME << ": ("; \ - for (int i = 0; i < ARRAY_SIZE; i++) { \ - if (i != 0) { \ - out << ", "; \ - } \ - out << NAME[i]; \ - } \ - out << ")" << endl; \ - } \ +#define print_true(NAME) +#define print_false(NAME) \ + out << #NAME << ": " << RubyConfig::get##NAME () << endl - -#include "mem/ruby/config/config.hh" +#define PARAM(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_UINT(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_ULONG(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_BOOL(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_DOUBLE(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_STRING(NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR) { print_##CUSTOM_ACCESSOR(NAME); } +#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY" << endl; } +#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY2D" << endl; } +#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) { out << #NAME << ": ARRAY3D" << endl; } +#include CONFIG_VAR_FILENAME #undef PARAM #undef PARAM_UINT #undef PARAM_ULONG @@ -172,15 +228,17 @@ static void print_parameters(ostream& out) #undef PARAM_DOUBLE #undef PARAM_STRING #undef PARAM_ARRAY +#undef PARAM_ARRAY2D +#undef PARAM_ARRAY3D } void RubyConfig::printConfiguration(ostream& out) { out << "Ruby Configuration" << endl; out << "------------------" << endl; - out << "protocol: " << CURRENT_PROTOCOL << endl; + //out << "protocol: " << CURRENT_PROTOCOL << endl; out << "compiled_at: " << __TIME__ << ", " << __DATE__ << endl; - out << "RUBY_DEBUG: " << bool_to_string(RUBY_DEBUG) << endl; + // out << "RUBY_DEBUG: " << bool_to_string(RUBY_DEBUG) << endl; char buffer[100]; gethostname(buffer, 50); diff --git a/src/mem/ruby/config/RubyConfig.hh b/src/mem/ruby/config/RubyConfig.hh index 6de6bd1aa2..f2e3a0f13c 100644 --- a/src/mem/ruby/config/RubyConfig.hh +++ b/src/mem/ruby/config/RubyConfig.hh @@ -40,12 +40,13 @@ #ifndef RUBYCONFIG_H #define RUBYCONFIG_H -#include "mem/ruby/common/Global.hh" -#include "mem/gems_common/ioutil/vardecl.hh" -#include "mem/ruby/system/NodeID.hh" +#include +#include +#include +#include -#define MEMORY_LATENCY RubyConfig::memoryResponseLatency() -#define ABORT_DELAY m_chip_ptr->getTransactionManager(m_version)->getAbortDelay() +#include "mem/ruby/common/TypeDefines.hh" +#define CONFIG_VAR_FILENAME "mem/ruby/config/config.hh" // Set paramterization /* @@ -61,96 +62,169 @@ */ const int NUMBER_WORDS_PER_SET = 4; +using namespace std; + class RubyConfig { public: // CACHE BLOCK CONFIG VARIBLES - static int dataBlockBits() { return g_DATA_BLOCK_BITS; } - static int dataBlockBytes() { return g_DATA_BLOCK_BYTES; } + static uint32 dataBlockMask() { return m_data_block_mask; } + + static int numberOfDMA() { return 1; } + static int numberOfDMAPerChip() { return 1; } + static int DMATransitionsPerCycle() { return 1; } // SUPPORTED PHYSICAL MEMORY CONFIG VARIABLES - static int pageSizeBits() { return g_PAGE_SIZE_BITS; } - static int pageSizeBytes() { return g_PAGE_SIZE_BYTES; } - static int memorySizeBits() { return g_MEMORY_SIZE_BITS; } - static int64 memorySizeBytes() { return g_MEMORY_SIZE_BYTES; } - static int memoryModuleBits() { return g_MEMORY_MODULE_BITS; } - static int64 memoryModuleBlocks() { return g_MEMORY_MODULE_BLOCKS; } + // static int memoryModuleBits() { return m_MEMORY_MODULE_BITS; } + // static int64 memoryModuleBlocks() { return m_MEMORY_MODULE_BLOCKS; } - // returns number of SMT threads per physical processor - static int numberofSMTThreads() { return g_NUM_SMT_THREADS; } // defines the number of simics processors (power of 2) - static int numberOfProcessors() { return g_NUM_PROCESSORS; } - static int procsPerChipBits() { return g_PROCS_PER_CHIP_BITS; } - static int numberOfProcsPerChip() { return g_PROCS_PER_CHIP; } - static int numberOfChips() { return g_NUM_CHIPS; } + // static int numberOfProcessors() { return m_NUM_PROCESSORS; } + // static int procsPerChipBits() { return m_PROCS_PER_CHIP_BITS; } + // static int numberOfProcsPerChip() { return m_ProcsPerChip; } + // static int numberOfChips() { return m_NUM_CHIPS; } // MACHINE INSTANIATION CONFIG VARIABLES // ------------------------------------- // L1 CACHE MACHINES // defines the number of L1banks - idependent of ruby chips (power of 2) // NOTE - no protocols currently supports L1s != processors, just a placeholder - static int L1CacheBits() { return g_NUM_PROCESSORS_BITS; } - static int numberOfL1Cache() { return g_NUM_PROCESSORS; } - static int L1CachePerChipBits() { return procsPerChipBits() ; } // L1s != processors not currently supported - static int numberOfL1CachePerChip() { return numberOfProcsPerChip(); } // L1s != processors not currently supported - static int numberOfL1CachePerChip(NodeID myNodeID) { return numberOfL1CachePerChip(); } - static int L1CacheTransitionsPerCycle() { return L1CACHE_TRANSITIONS_PER_RUBY_CYCLE; } - - // L2 CACHE MACHINES - // defines the number of L2banks/L2Caches - idependent of ruby chips (power of 2) - static int L2CacheBits() { return g_NUM_L2_BANKS_BITS; } - static int numberOfL2Cache() { return g_NUM_L2_BANKS; } - static int L1CacheNumToL2Base(NodeID L1RubyNodeID); - static int L2CachePerChipBits() { return g_NUM_L2_BANKS_PER_CHIP_BITS; } - static int numberOfL2CachePerChip() { return g_NUM_L2_BANKS_PER_CHIP; } - static int numberOfL2CachePerChip(NodeID myNodeID) { return numberOfL2CachePerChip(); } - static int L2CacheTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; } // DIRECTORY/MEMORY MACHINES // defines the number of ruby memories - idependent of ruby chips (power of 2) - static int memoryBits() { return g_NUM_MEMORIES_BITS; } - static int numberOfDirectory() { return numberOfMemories(); } - static int numberOfMemories() { return g_NUM_MEMORIES; } - static int numberOfDirectoryPerChip() { return g_NUM_MEMORIES_PER_CHIP; } - static int numberOfDirectoryPerChip(NodeID myNodeID) { return g_NUM_MEMORIES_PER_CHIP; } - static int DirectoryTransitionsPerCycle() { return DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE; } - - // PERSISTENT ARBITER MACHINES - static int numberOfPersistentArbiter() { return numberOfMemories(); } - static int numberOfPersistentArbiterPerChip() {return numberOfDirectoryPerChip(); } - static int numberOfPersistentArbiterPerChip(NodeID myNodeID) {return numberOfDirectoryPerChip(myNodeID); } - static int PersistentArbiterTransitionsPerCycle() { return L2CACHE_TRANSITIONS_PER_RUBY_CYCLE; } + // static int memoryBits() { return m_NUM_MEMORIES_BITS; } + // static int numberOfDirectory() { return numberOfMemories(); } + // static int numberOfMemories() { return m_NUM_MEMORIES; } + // static int numberOfDirectoryPerChip() { return m_NUM_MEMORIES_PER_CHIP; } + // static int DirectoryTransitionsPerCycle() { return m_DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE; } // ---- END MACHINE SPECIFIC VARIABLES ---- // VARIABLE MEMORY RESPONSE LATENCY // *** NOTE *** This is where variation is added to the simulation // see Alameldeen et al. HPCA 2003 for further details - static int memoryResponseLatency() { return MEMORY_RESPONSE_LATENCY_MINUS_2+(random() % 5); } +// static int getMemoryLatency() { return m_MEMORY_RESPONSE_LATENCY_MINUS_2+(random() % 5); } + static void reset(); static void init(); - static void printConfiguration(ostream& out); + static void printConfiguration(std::ostream& out); // Memory Controller - static int memBusCycleMultiplier () { return MEM_BUS_CYCLE_MULTIPLIER; } - static int banksPerRank () { return BANKS_PER_RANK; } - static int ranksPerDimm () { return RANKS_PER_DIMM; } - static int dimmsPerChannel () { return DIMMS_PER_CHANNEL; } - static int bankBit0 () { return BANK_BIT_0; } - static int rankBit0 () { return RANK_BIT_0; } - static int dimmBit0 () { return DIMM_BIT_0; } - static int bankQueueSize () { return BANK_QUEUE_SIZE; } - static int bankBusyTime () { return BANK_BUSY_TIME; } - static int rankRankDelay () { return RANK_RANK_DELAY; } - static int readWriteDelay () { return READ_WRITE_DELAY; } - static int basicBusBusyTime () { return BASIC_BUS_BUSY_TIME; } - static int memCtlLatency () { return MEM_CTL_LATENCY; } - static int refreshPeriod () { return REFRESH_PERIOD; } - static int tFaw () { return TFAW; } - static int memRandomArbitrate () { return MEM_RANDOM_ARBITRATE; } - static int memFixedDelay () { return MEM_FIXED_DELAY; } + +// static int memBusCycleMultiplier () { return m_MEM_BUS_CYCLE_MULTIPLIER; } +/* static int banksPerRank () { return m_BANKS_PER_RANK; } + static int ranksPerDimm () { return m_RANKS_PER_DIMM; } + static int dimmsPerChannel () { return m_DIMMS_PER_CHANNEL; } + static int bankBit0 () { return m_BANK_BIT_0; } + static int rankBit0 () { return m_RANK_BIT_0; } + static int dimmBit0 () { return m_DIMM_BIT_0; } + static int bankQueueSize () { return m_BANK_QUEUE_SIZE; } + static int bankBusyTime () { return m_BankBusyTime; } + static int rankRankDelay () { return m_RANK_RANK_DELAY; } + static int readWriteDelay () { return m_READ_WRITE_DELAY; } + static int basicBusBusyTime () { return m_BASIC_BUS_BUSY_TIME; } + static int memCtlLatency () { return m_MEM_CTL_LATENCY; } + static int refreshPeriod () { return m_REFRESH_PERIOD; } + static int tFaw () { return m_TFAW; } + static int memRandomArbitrate () { return m_MEM_RANDOM_ARBITRATE; } + static int memFixedDelay () { return m_MEM_FIXED_DELAY; } +*/ + /* cache accessors */ + static int getCacheIDFromParams(int level, int num, string split_type) { + // TODO: this function + return 0; + } + +#define accessor_true( TYPE, NAME ) +#define accessor_false( TYPE, NAME ) \ + static TYPE get##NAME() { return m_##NAME; } \ + static void set##NAME(TYPE val) { m_##NAME = val; } + +#define array_accessor_true( TYPE, NAME, DEFAULT_ARRAY_SIZE ) +#define array_accessor_false( TYPE, NAME, DEFAULT_ARRAY_SIZE ) \ + static TYPE get##NAME(int idx) { \ + assert(m_##NAME != NULL); \ + return m_##NAME[idx]; \ + } \ + static void set##NAME(int idx, TYPE val) { \ + if(m_##NAME == NULL) { \ + assert(DEFAULT_ARRAY_SIZE > 0); \ + m_##NAME = new TYPE[DEFAULT_ARRAY_SIZE]; \ + } \ + m_##NAME[idx] = val; \ + } + +#define array2d_accessor_true( TYPE, NAME ) +#define array2d_accessor_false( TYPE, NAME ) \ + static TYPE get##NAME(int idx1, int idx2) { return m_##NAME[idx1][idx2]; } \ + static void set##NAME(int idx1, int idx2, TYPE val) { m_##NAME[idx1][idx2] = val; } + +#define array3d_accessor_true( TYPE, NAME ) +#define array3d_accessor_false( TYPE, NAME ) \ + static TYPE get##NAME(int idx1, int idx2, int idx3) { return m_##NAME[idx1][idx2][idx3]; } \ + static void set##NAME(int idx1, int idx2, int idx3, TYPE val) { m_##NAME[idx1][idx2][idx3] = val; } + +#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(int32,NAME) +#define PARAM_UINT( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(uint32,NAME) +#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(uint64,NAME) +#define PARAM_BOOL( NAME, DEFAULT_VALUE,CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(bool,NAME) +#define PARAM_DOUBLE( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(double,NAME) +#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + accessor_##CUSTOM_ACCESSOR(const char*,NAME) +#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + array_accessor_##CUSTOM_ACCESSOR(TYPE, NAME, DEFAULT_ARRAY_SIZE) +#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + array2d_accessor_##CUSTOM_ACCESSOR(TYPE, NAME) +#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + array3d_accessor_##CUSTOM_ACCESSOR(TYPE, NAME) +#include CONFIG_VAR_FILENAME +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY +#undef PARAM_ARRAY2D +#undef PARAM_ARRAY3D private: + static uint32 m_data_block_mask; + +#define PARAM( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static int32 m_##NAME; +#define PARAM_UINT( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static uint32 m_##NAME; +#define PARAM_ULONG( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static uint64 m_##NAME; +#define PARAM_BOOL( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static bool m_##NAME; +#define PARAM_DOUBLE( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static double m_##NAME; +#define PARAM_STRING( NAME, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static const char *m_##NAME; +#define PARAM_ARRAY( NAME, TYPE, DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static TYPE* m_##NAME; +#define PARAM_ARRAY2D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static TYPE** m_##NAME; +#define PARAM_ARRAY3D( NAME, TYPE, D1_DEFAULT_ARRAY_SIZE, D2_DEFAULT_ARRAY_SIZE, D3_DEFAULT_ARRAY_SIZE, DEFAULT_VALUE, CUSTOM_ACCESSOR ) \ + static TYPE*** m_##NAME; +#include CONFIG_VAR_FILENAME +#undef PARAM +#undef PARAM_UINT +#undef PARAM_ULONG +#undef PARAM_BOOL +#undef PARAM_DOUBLE +#undef PARAM_STRING +#undef PARAM_ARRAY +#undef PARAM_ARRAY2D +#undef PARAM_ARRAY3D + }; #endif //RUBYCONFIG_H diff --git a/src/mem/ruby/config/cfg.rb b/src/mem/ruby/config/cfg.rb new file mode 100644 index 0000000000..de8bcafd25 --- /dev/null +++ b/src/mem/ruby/config/cfg.rb @@ -0,0 +1,751 @@ +#!/usr/bin/ruby + +class AssertionFailure < RuntimeError +end + +class Boolean + def self.is_a?(obj) + return self.name == "Boolean" + end +end + +def assert(condition,message) + unless condition + raise AssertionFailure, "Assertion failed: #{message}" + end +end + +class LibRubyObject + @@all_objs = Array.new + attr_reader :obj_name + @@default_params = Hash.new + + def initialize(obj_name) + assert obj_name.is_a?(String), "Obj_Name must be a string" + @obj_name = obj_name + @@all_objs << self + @params = Hash.new + end + + def cppClassName() + raise NotImplementedException + end + + def self.param(param_name, type) + idx = self.name.to_sym + @@default_params[idx] = Hash.new if ! @@default_params.key?(idx) + @@default_params[idx][param_name] = nil + send :define_method, param_name do + @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name) + @params[param_name] + end + method_name = (param_name.to_s + "=").to_sym + send :define_method, method_name do |val| + if val.is_a?(FalseClass) || val.is_a?(TrueClass) + assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false" + else + assert val.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}" + end +# assert val.is_a?(type), "#{param_name} must be of type #{type}" + @params[param_name] = val + end + end + + def self.default_param(param_name, type, default) + idx = self.name.to_sym + @@default_params[idx] = Hash.new if ! @@default_params.key?(idx) + if default.is_a?(FalseClass) || default.is_a?(TrueClass) + assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false" + else + assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}" + end + @@default_params[idx][param_name] = default + send :define_method, param_name do + @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name) + @params[param_name] + end + method_name = (param_name.to_s + "=").to_sym + send :define_method, method_name do |val| + assert val.is_a?(type), "#{param_name} must be of type #{type}" + @params[param_name] = val + end + end + + def applyDefaults() + idx = self.class.name.to_sym + @@default_params[idx] = Hash.new if ! @@default_params.key?(idx) + @@default_params[idx].each { |key, val| + @params[key] = val if ! @params.key?(key) + } + end + + def argv() + str = "" + + applyDefaults + + @params.each { |key, val| + str += key.id2name + " " + if val.is_a?(LibRubyObject) + str += val.obj_name + " " + else + if val.is_a?(String) and val == "" + str += "null " + else + str += val.to_s + " " + end + end + } + return str + end + + def self.printConstructors() + @@all_objs.each { |obj| + print obj.cppClassName, " ", obj.obj_name, " ",obj.argv,"\n" + } + end + def self.all() + @@all_objs + end +end + +class IfacePort < LibRubyObject + def initialize(obj_name) + super(obj_name) + end + + def bochsConnType + raise NotImplementedException + end +end + +class NetPort < LibRubyObject + attr :mach_type + attr_reader :version + + @@type_cnt = Hash.new + @type_id + def initialize(obj_name, mach_type) + super(obj_name) + @mach_type = mach_type + @@type_cnt[mach_type] ||= 0 + @type_id = @@type_cnt[mach_type] + @@type_cnt[mach_type] += 1 + + idx = "NetPort".to_sym + @@default_params[idx] = Hash.new if ! @@default_params.key?(idx) + @@default_params[idx].each { |key, val| + @params[key] = val if ! @params.key?(key) + } + end + + def port_name + mach_type + end + def port_num + @type_id + end + def cppClassName + "NetPort" + end +end + +class MemoryVector < LibRubyObject + def initialize(obj_name) + super(obj_name) + end + + def cppClassName + "MemoryController" + end +end + +class Debug < LibRubyObject + def initialize *args + case args.size + when 1 + super(args[0]) + when 6 + init_params *args[1] + else + raise Exception + end + end + + def init_params (protocol_trace, filter_string, verbosity_string, start_time, output_filename) + @params[:protocol_trace] = protocol_trace + @params[:filter_string] = filter_string + @params[:verbosity_string] = verbosity_string + @params[:start_time] = start_time + @params[:output_filename] = output_filename + end + + def cppClassName + "Debug" + end +end + +class RubySystem + + @@params = Hash.new + @@network = nil + + def self.init(iface_ports, network) + @@iface_ports = iface_ports + @@network = network + end + + def self.default_param(param_name, type, default) + if default.is_a?(FalseClass) || default.is_a?(TrueClass) + assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false" + else + assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}" + end + @@params[param_name] = default + method_name = (param_name.to_s).to_sym + instance_eval <<-EOS + def #{method_name.to_s} + @@params[:#{param_name.to_s}] + end + EOS + instance_eval <<-EOS + def #{method_name.to_s}=(val) + @@params[:#{param_name.to_s}] = val + end + EOS + end + + def self.generateConfig() + # get current time for random seed if set to "rand" + if @@params[:random_seed] == "rand" + t = Time.now + @@params[:random_seed] = t.usec.to_i + end + if ! @@params[:random_seed].is_a?(Integer) + raise TypeException + end + print "System sys0 ",argv,"\n" + LibRubyObject.all.each { |obj| + if obj.is_a?(SetAssociativeCache) + obj.calculateLatency + end + } + LibRubyObject.printConstructors + end + + def self.printIfacePorts() + @@iface_ports.each { |port| + print port.obj_name, " " + } + puts + end + + def self.getBochsConnections() + ports = Hash.new + @@iface_ports.each { |port| + ports[port.obj_name] = port.bochsConnType + } + return ports + end + + def self.getMemorySizeMB() + DirectoryMemory.memorySizeMB + end + + # override the default accessors (generated by default_param) for random_seed + def self.random_seed=(seed) + assert (val.is_a?(Integer) or val == "rand"), "RubySystem.random_seed takes either an integer value or the string \"rand\"" + @@params[:random_seed] = seed + end + +private + + def self.argv() + str = "" + @@params.each { |key, val| + str += key.id2name + " " + str += val.to_s + " " + } + return str + end + + def self.writeConfig() + @@network.printTopology + end + +end + +#require "defaults.rb" + + + +class CacheController < NetPort + @@total_cache_controllers = 0 + attr :caches + attr :sequencer + def initialize(obj_name, mach_type, caches, sequencer) + super(obj_name, mach_type) + @caches = caches + @caches.each { |cache| + cache.controller = self + } + + @sequencer = sequencer + @sequencer.controller = self + + @version = @@total_cache_controllers + @@total_cache_controllers += 1 + @sequencer.version = @version + buffer_size() + end + + def argv() + vec = "version "+@version.to_s + @caches.each { |cache| + vec += " cache " + cache.obj_name + } + vec += " sequencer "+@sequencer.obj_name + vec += " transitions_per_cycle "+@params[:transitions_per_cycle].to_s + vec += " buffer_size "+@params[:buffer_size].to_s + vec += " number_of_TBEs "+@params[:number_of_TBEs].to_s + + end + + def cppClassName() + "generated:"+@mach_type + end +end + +class DirectoryController < NetPort + @@total_directory_controllers = 0 + attr :directory + attr :memory_control + + def initialize(obj_name, mach_type, directory, memory_control) + super(obj_name, mach_type) + + @directory = directory + directory.controller = self + + @memory_control = memory_control + + @version = @@total_directory_controllers + @@total_directory_controllers += 1 + buffer_size() + end + + def argv() + "version "+@version.to_s+" directory_name "+@directory.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + " memory_controller_name "+@memory_control.obj_name + " recycle_latency "+@params[:recycle_latency].to_s + end + + def cppClassName() + "generated:"+@mach_type + end + +end + +class DMAController < NetPort + @@total_dma_controllers = 0 + attr :dma_sequencer + def initialize(obj_name, mach_type, dma_sequencer) + super(obj_name, mach_type) + @dma_sequencer = dma_sequencer + @version = @@total_dma_controllers + @@total_dma_controllers += 1 + dma_sequencer.controller = self + buffer_size + end + + def argv() + "version "+@version.to_s+" dma_sequencer "+@dma_sequencer.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + end + + def cppClassName() + "generated:"+@mach_type + end +end + +class Cache < LibRubyObject + attr :size_kb, :latency + attr_writer :controller + def initialize(obj_name, size_kb, latency) + super(obj_name) + assert size_kb.is_a?(Integer), "Cache size must be an integer" + @size_kb = size_kb + @latency = latency + end + + def args + "controller "+@controller.obj_name+" size_kb "+@size_kb.to_s+" latency "+@latency.to_s + end +end + +class SetAssociativeCache < Cache + attr :assoc, :replacement_policy + + # latency can be either an integer, a float, or the string "auto" + # when an integer, it represents the number of cycles for a hit + # when a float, it represents the cache access time in ns + # when set to "auto", libruby will attempt to find a realistic latency by running CACTI + def initialize(obj_name, size_kb, latency, assoc, replacement_policy) + super(obj_name, size_kb, latency) + @assoc = assoc + @replacement_policy = replacement_policy + end + + def calculateLatency() + if @latency == "auto" + cacti_args = Array.new() + cacti_args << (@size_kb*1024) << RubySystem.block_size_bytes << @assoc + cacti_args << 1 << 0 << 0 << 0 << 1 + cacti_args << RubySystem.tech_nm << RubySystem.block_size_bytes*8 + cacti_args << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 1 + cacti_args << 360 << 0 << 0 << 0 << 0 << 1 << 1 << 1 << 1 << 0 << 0 + cacti_args << 50 << 10 << 10 << 0 << 1 << 1 + + cacti_cmd = File.dirname(__FILE__) + "/cacti/cacti " + cacti_args.join(" ") + + IO.popen(cacti_cmd) { |pipe| + str1 = pipe.readline + str2 = pipe.readline + results = str2.split(", ") + if results.size != 61 + print "CACTI ERROR: CACTI produced unexpected output.\n" + print "Are you using the version shipped with libruby?\n" + raise Exception + end + latency_ns = results[5].to_f + if (latency_ns == "1e+39") + print "CACTI ERROR: CACTI was unable to realistically model the cache ",@obj_name,"\n" + print "Either change the cache parameters or manually set the latency values\n" + raise Exception + end + clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6)) + latency_cycles = (latency_ns / clk_period_ns).ceil + @latency = latency_cycles + } + elsif @latency.is_a?(Float) + clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6)) + latency_cycles = (@latency / clk_period_ns).ceil + @latency = latency_cycles + elsif ! @latency.is_a?(Integer) + raise Exception + end + end + + def argv() + args+" assoc "+@assoc.to_s+" replacement_policy "+@replacement_policy + end + + def cppClassName() + "SetAssociativeCache" + end +end + +class DirectoryMemory < LibRubyObject + attr :size_mb + attr_writer :controller + @@total_size_mb = 0 + + def initialize(obj_name, size_mb) + super(obj_name) + @size_mb = size_mb + @@total_size_mb += size_mb + end + + def argv() + "version "+@controller.version.to_s+" size_mb "+@size_mb.to_s+" controller "+@controller.obj_name + end + + def cppClassName() + "DirectoryMemory" + end + + def self.memorySizeMB() + @@total_size_mb + end +end + +#added by SS +class MemoryControl < LibRubyObject + attr :name + def initialize(obj_name) + super(obj_name) + @name = obj_name + end + + def argv() + vec = super() + vec += " mem_bus_cycle_multiplier "+mem_bus_cycle_multiplier.to_s + vec += " banks_per_rank "+banks_per_rank.to_s + vec += " ranks_per_dimm "+ranks_per_dimm.to_s + vec += " dimms_per_channel "+dimms_per_channel.to_s + vec += " bank_bit_0 "+bank_bit_0.to_s + vec += " rank_bit_0 "+rank_bit_0.to_s + vec += " dimm_bit_0 "+dimm_bit_0.to_s + vec += " bank_queue_size "+bank_queue_size.to_s + vec += " bank_busy_time "+bank_busy_time.to_s + vec += " rank_rank_delay "+rank_rank_delay.to_s + vec += " read_write_delay "+read_write_delay.to_s + vec += " basic_bus_busy_time "+basic_bus_busy_time.to_s + vec += " mem_ctl_latency "+mem_ctl_latency.to_s + vec += " refresh_period "+refresh_period.to_s + vec += " tFaw "+tFaw.to_s + vec += " mem_random_arbitrate "+mem_random_arbitrate.to_s + vec += " mem_fixed_delay "+mem_fixed_delay.to_s + vec += " memory_controller_name "+@name + + end + + + def cppClassName() + "MemoryControl" + end +end + + + +class Sequencer < IfacePort + + def cppClassName() + "Sequencer" + end + + param :controller, NetPort # must be set after initialization + param :icache, Cache + param :dcache, Cache + param :version, Integer + + def initialize(obj_name, icache, dcache) + super(obj_name) + self.icache=icache + self.dcache=dcache + end + + def bochsConnType() + return "cpu"+version.to_s + end + +end + + + +class DMASequencer < IfacePort + def initialize(obj_name) + super(obj_name) + @params = { + :controller => nil, + :version => nil + } + end + + def controller=(controller) + @params[:controller] = controller.obj_name + @params[:version] = controller.version + end + + def cppClassName() + "DMASequencer" + end + + def bochsConnType() + return "dma"+@params[:version].to_s + end +end + +class IntNode + @@num = 0 + def initialize() + + end +end + +class Network < LibRubyObject +end + +class Topology < LibRubyObject + attr :net_ports + param :network, Network + def initialize(name, net_ports) + super(name) + @net_ports = net_ports + end + + def cppClassName + "Topology" + end +end + +class Network < LibRubyObject + param :topology, Topology + def initialize(name, topo) + super(name) + @params[:topology] = topo + topo.network= self + end + + def argv() + vec = super() + + vec += " endpoint_bandwidth "+endpoint_bandwidth.to_s + vec += " adaptive_routing "+adaptive_routing.to_s + vec += " number_of_virtual_networks "+number_of_virtual_networks.to_s + vec += " fan_out_degree "+fan_out_degree.to_s + + vec += " buffer_size "+buffer_size.to_s + vec += " link_latency "+adaptive_routing.to_s + vec += " on_chip_latency "+on_chip_latency.to_s + + end + + def printTopology() + topology.printFile + end + def cppClassName() + "SimpleNetwork" + end + +end + +class PtToPtTopology < Topology + + param :connections,String + + def initialize(name, net_ports) + super(name, net_ports) + @params[:connections] = "" + @net_ports.each_index { |idx| + @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s) + @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s) + @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#") + } + @net_ports.each_index { |outer_idx| + @net_ports.each_index { |inner_idx| + if (outer_idx != inner_idx) + @params[:connections] << ("int_node:"+ outer_idx.to_s+ "%int_node:"+ inner_idx.to_s) + @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s) + @params[:connections] << ("%link_weight:"+1.to_s+"#") + end + } + } + # call the accessors of the parent class to initialize them + # need to find a better method!! + print_config + end + +end + +class CrossbarTopology < Topology + param :connections,String + + def initialize(name, net_ports) + super(name, net_ports) + @params[:connections] = "" + crossbar_node = @net_ports.size + @net_ports.each_index { |idx| + @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s) + @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s) + @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#") + } + @net_ports.each_index { |idx| + @params[:connections] << ("int_node:"+idx.to_s+"%int_node:"+crossbar_node.to_s) + @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s) + @params[:connections] << ("%link_weight:"+1.to_s+"#") + } + print_config + end +end + +#added by SS +class Tracer < LibRubyObject + def initialize(obj_name) + super(obj_name) + end + + def cppClassName() + "Tracer" + end + +end + +class Profiler < LibRubyObject + def initialize(obj_name) + super(obj_name) + end + + def cppClassName() + "Profiler" + end + +end + +class MI_example_CacheController < CacheController + def initialize(obj_name, mach_type, caches, sequencer) + super(obj_name, mach_type, caches, sequencer) + end + def argv() + vec = super() + vec += " issue_latency "+issue_latency.to_s + vec += " cache_response_latency "+cache_response_latency.to_s + end + +end + +class MI_example_DirectoryController < DirectoryController + def initialize(obj_name, mach_type, directory, memory_control) + super(obj_name, mach_type, directory, memory_control) + end + def argv() + vec = super() + vec += " to_mem_ctrl_latency "+to_mem_ctrl_latency.to_s + vec += " directory_latency "+directory_latency.to_s + vec += " memory_latency "+memory_latency.to_s + end + +end + +#added by SS +class GarnetNetwork < Network + def initialize(name, topo) + super(name, topo) + end + def argv() + vec = super() + vec += " flit_size "+flit_size.to_s + vec += " number_of_pipe_stages "+number_of_pipe_stages.to_s + vec += " vcs_per_class "+vcs_per_class.to_s + vec += " buffer_size "+buffer_size.to_s + vec += " using_network_testing "+using_network_testing.to_s + end + +end + +class GarnetFixedPipeline < GarnetNetwork + def initialize(name, net_ports) + super(name, net_ports) + end + + def argv() + super() + end + + def cppClassName() + "GarnetNetwork_d" + end +end + +class GarnetFlexiblePipeline < GarnetNetwork + def initialize(name, net_ports) + super(name, net_ports) + end + + def argv() + super() + end + + def cppClassName() + "GarnetNetwork" + end +end + +require "defaults.rb" diff --git a/src/mem/ruby/config/config.hh b/src/mem/ruby/config/config.hh index 3cad258a2c..ad91cd73de 100644 --- a/src/mem/ruby/config/config.hh +++ b/src/mem/ruby/config/config.hh @@ -1,74 +1,23 @@ -// -// This file has been modified by Kevin Moore and Dan Nussbaum of the -// Scalable Systems Research Group at Sun Microsystems Laboratories -// (http://research.sun.com/scalable/) to support the Adaptive -// Transactional Memory Test Platform (ATMTP). For information about -// ATMTP, see the GEMS website: http://www.cs.wisc.edu/gems/. -// -// Please send email to atmtp-interest@sun.com with feedback, questions, or -// to request future announcements about ATMTP. -// -// ---------------------------------------------------------------------- -// -// File modification date: 2008-02-23 -// -// ---------------------------------------------------------------------- -// -// ATMTP is distributed as part of the GEMS software toolset and is -// available for use and modification under the terms of version 2 of the -// GNU General Public License. The GNU General Public License is contained -// in the file $GEMS/LICENSE. -// -// Multifacet GEMS is free software; you can redistribute it and/or modify -// it under the terms of version 2 of the GNU General Public License as -// published by the Free Software Foundation. -// -// Multifacet GEMS is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. -// -// You should have received a copy of the GNU General Public License along -// with the Multifacet GEMS; if not, write to the Free Software Foundation, -// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA -// -// ---------------------------------------------------------------------- -// - -// see rubyconfig.defaults for some explanations - -PARAM( g_RANDOM_SEED ); - -// Maximum number of cycles a request is can be outstanding before the -// Sequencer of StoreBuffer declares we're in deadlock/livelock -PARAM( g_DEADLOCK_THRESHOLD ); -PARAM_BOOL( RANDOMIZATION ); -PARAM_BOOL( g_SYNTHETIC_DRIVER ); -PARAM_BOOL( g_DETERMINISTIC_DRIVER ); // FOR MOESI_CMP_token -PARAM_BOOL( g_FILTERING_ENABLED ); -PARAM_BOOL( g_DISTRIBUTED_PERSISTENT_ENABLED ); -PARAM_BOOL( g_DYNAMIC_TIMEOUT_ENABLED ); -PARAM( g_RETRY_THRESHOLD ); -PARAM( g_FIXED_TIMEOUT_LATENCY ); +//PARAM_BOOL( FilteringEnabled, false, false ); +//PARAM_BOOL( DistributedPersistentEnabled, true, false ); +//PARAM_BOOL( DynamicTimeoutEnabled, true, false ); +//PARAM( RetryThreshold, 1, false ); +//PARAM( FixedTimeoutLatency, 300, false ); -PARAM( g_trace_warmup_length ); -PARAM_DOUBLE( g_bash_bandwidth_adaptive_threshold ); +//PARAM( TraceWarmupLength, 1000000, false ); -PARAM( g_tester_length ); -PARAM( g_synthetic_locks ); -PARAM( g_deterministic_addrs ); -// Specified Generator: See SpecifiedGeneratorType in external.sm for valid values -PARAM_STRING( g_SpecifiedGenerator ); -PARAM( g_callback_counter ); -PARAM( g_NUM_COMPLETIONS_BEFORE_PASS ); +//PARAM( callback_counter, 0, false ); +//PARAM( NUM_COMPLETIONS_BEFORE_PASS, 0, false ); -PARAM( g_NUM_SMT_THREADS ); - -PARAM( g_think_time ); -PARAM( g_hold_time ); -PARAM( g_wait_time ); +//PARAM( tester_length, 0, false ); +//PARAM( synthetic_locks, 2048, false ); +//PARAM( think_time, 5, false ); +//PARAM( wait_time, 5, false ); +//PARAM( hold_time, 5, false ); +//PARAM( deterministic_addrs, 1, false ); +//PARAM_STRING( SpecifiedGenerator, "DetermInvGenerator", false ); // For debugging purposes, one can enable a trace of all the protocol // state machine changes. Unfortunately, the code to generate the @@ -80,243 +29,208 @@ PARAM( g_wait_time ); // "g_debug_ptr->setDebugTime(1)" to beging the following to set the // debug begin time // -// this use to be ruby/common/Global.h +// this use to be ruby/common/Global.hh -PARAM_BOOL( PROTOCOL_DEBUG_TRACE ); -// a string for filtering debugging output (for all g_debug vars see Debug.h) -PARAM_STRING( DEBUG_FILTER_STRING ); +//PARAM_BOOL( ProtocolDebugTrace, true, false ); +// a string for filtering debugging output (for all g_debug vars see Debug.hh) +//PARAM_STRING( DEBUG_FILTER_STRING, "", false ); // filters debugging messages based on priority (low, med, high) -PARAM_STRING( DEBUG_VERBOSITY_STRING ); +//PARAM_STRING( DEBUG_VERBOSITY_STRING, "", false ); // filters debugging messages based on a ruby time -PARAM_ULONG( DEBUG_START_TIME ); +//PARAM_ULONG( DEBUG_START_TIME, 0, false ); // sends debugging messages to a output filename -PARAM_STRING( DEBUG_OUTPUT_FILENAME ); +//PARAM_STRING( DEBUG_OUTPUT_FILENAME, "", false ); -// defines relative (integer) clock multipliers between ruby, opal, and simics -PARAM( SIMICS_RUBY_MULTIPLIER ); -PARAM( OPAL_RUBY_MULTIPLIER ); - -PARAM_BOOL( TRANSACTION_TRACE_ENABLED ); -PARAM_BOOL( USER_MODE_DATA_ONLY ); -PARAM_BOOL( PROFILE_HOT_LINES ); +//PARAM_BOOL( ProfileHotLines, false, false ); // PROFILE_ALL_INSTRUCTIONS is used if you want Ruby to profile all instructions executed // The following need to be true for this to work correctly: // 1. Disable istc and dstc for this simulation run // 2. Add the following line to the object "sim" in the checkpoint you run from: -// instruction_profile_line_size: 4 +// instruction_profile_line_size: 4 // This is used to have simics report back all instruction requests // For more details on how to find out how to interpret the output physical instruction // address, please read the document in the simics-howto directory -PARAM_BOOL( PROFILE_ALL_INSTRUCTIONS ); +//PARAM_BOOL( ProfileAllInstructions, false, false ); // Set the following variable to true if you want a complete trace of // PCs (physical address of program counters, with executing processor IDs) // to be printed to stdout. Make sure to direct the simics output to a file. // Otherwise, the run will take a really long time! // A long run may write a file that can exceed the OS limit on file length -PARAM_BOOL( PRINT_INSTRUCTION_TRACE ); -PARAM( g_DEBUG_CYCLE ); - -// Don't allow any datablocks to enter the STC -PARAM_BOOL( BLOCK_STC ); +//PARAM_BOOL( PRINT_INSTRUCTION_TRACE, false, false ); +//PARAM( DEBUG_CYCLE, 0, false ); // Make the entire memory system perfect -PARAM_BOOL( PERFECT_MEMORY_SYSTEM ); -PARAM( PERFECT_MEMORY_SYSTEM_LATENCY ); - -PARAM_BOOL( DATA_BLOCK ); // Define NO_DATA_BLOCK to make the DataBlock take zero space - -PARAM_BOOL( REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH ); +//PARAM_BOOL( PERFECT_MEMORY_SYSTEM, false, false ); +//PARAM( PERFECT_MEMORY_SYSTEM_LATENCY, 0, false ); // ********************************************* -// CACHE & MEMORY PARAMETERS +// SYSTEM PARAMETERS // ********************************************* +//PARAM( NumberOfChips, 1, false ); +//PARAM( NumberOfCores, 2, false ); +//PARAM_ARRAY( NumberOfCoresPerChip, int, m_NumberOfChips, 2, false); -PARAM( L1_CACHE_ASSOC ); -PARAM( L1_CACHE_NUM_SETS_BITS ); -PARAM( L2_CACHE_ASSOC ); -PARAM( L2_CACHE_NUM_SETS_BITS ); +// ********************************************* +// CACHE PARAMETERS +// ********************************************* -PARAM_ULONG( g_MEMORY_SIZE_BYTES ); -PARAM( g_DATA_BLOCK_BYTES ); -// The following page size parameter is used by the stride prefetcher -PARAM( g_PAGE_SIZE_BYTES ); -PARAM_STRING( g_REPLACEMENT_POLICY ); +//PARAM( NumberOfCaches, m_NumberOfCores, false ); +//PARAM( NumberOfCacheLevels, 1, false ); +/* this returns the number of discrete CacheMemories per level (i.e. a split L1 counts for 2) */ +//PARAM_ARRAY( NumberOfCachesPerLevel, int, m_NumberOfCacheLevels, m_NumberOfCores, false ); // this is the number of discrete caches if the level is private + // or the number of banks if the level is shared +//PARAM( CacheIDFromParams, 1, true ); // returns a unique CacheID from the parameters (level, num, split_type) +//PARAM_ARRAY( CacheLatency, int, m_NumberOfCaches, 1, false ); // returns the latency for cache, indexed by CacheID +//PARAM_ARRAY( CacheSplitType, string, m_NumberOfCaches, "unified", false ); // returns "data", "instruction", or "unified", indexed by CacheID +//PARAM_ARRAY( CacheType, string, m_NumberOfCaches, "SetAssociative", false ); // returns the type of a cache, indexed by CacheID +//PARAM_ARRAY( CacheAssoc, int, m_NumberOfCaches, 4, false ); // returns the cache associativity, indexed by CacheID +//PARAM_ARRAY( NumberOfCacheSets, int, m_NumberOfCaches, 256, false ); // returns the number of cache sets, indexed by CacheID +//PARAM_ARRAY( NumberOfCacheSetBits, int, m_NumberOfCaches, log_int(256), false ); // returns the number of cache set bits, indexed by CacheID +//PARAM_ARRAY( CacheReplacementPolicy, string, m_NumberOfCaches, "PSEUDO_LRU", false ); // other option is "LRU" -PARAM( g_NUM_PROCESSORS ); -PARAM( g_NUM_L2_BANKS ); -PARAM( g_NUM_MEMORIES ); -PARAM( g_PROCS_PER_CHIP ); +//PARAM( DataBlockBytes, 64, false ); +//PARAM( DataBlockBits, log_int(m_DataBlockBytes), false); + +// ******************************************** +// MEMORY PARAMETERS +// ******************************************** + +//PARAM_ARRAY( NumberOfControllersPerType, int, m_NumberOfCacheLevels+2, m_NumberOfCores, false); +//PARAM_ARRAY2D( NumberOfControllersPerTypePerChip, int, m_NumberOfCacheLevels+2, m_NumberOfChips, m_NumberOfCores, false); + +// ******************************************** +// DMA CONTROLLER PARAMETERS +// ******************************************** + +//PARAM( NumberOfDMA, 1, false ); +//PARAM_ARRAY( NumberOfDMAPerChip, int, m_NumberOfChips, 1, false); +//PARAM_ARRAY( ChipNumFromDMAVersion, int, m_NumberOfDMA, 0, false ); + +//PARAM_ULONG( MemorySizeBytes, 4294967296, false ); +//PARAM_ULONG( MemorySizeBits, 32, false); + +//PARAM( NUM_PROCESSORS, 0, false ); +//PARAM( NUM_L2_BANKS, 0, false ); +//PARAM( NUM_MEMORIES, 0, false ); +//PARAM( ProcsPerChip, 1, false ); // The following group of parameters are calculated. They must // _always_ be left at zero. -PARAM( g_NUM_CHIPS ); -PARAM( g_NUM_CHIP_BITS ); -PARAM( g_MEMORY_SIZE_BITS ); -PARAM( g_DATA_BLOCK_BITS ); -PARAM( g_PAGE_SIZE_BITS ); -PARAM( g_NUM_PROCESSORS_BITS ); -PARAM( g_PROCS_PER_CHIP_BITS ); -PARAM( g_NUM_L2_BANKS_BITS ); -PARAM( g_NUM_L2_BANKS_PER_CHIP_BITS ); -PARAM( g_NUM_L2_BANKS_PER_CHIP ); -PARAM( g_NUM_MEMORIES_BITS ); -PARAM( g_NUM_MEMORIES_PER_CHIP ); -PARAM( g_MEMORY_MODULE_BITS ); -PARAM_ULONG( g_MEMORY_MODULE_BLOCKS ); - -// determines the mapping between L2 banks and sets within L2 banks -PARAM_BOOL( MAP_L2BANKS_TO_LOWEST_BITS ); +//PARAM( NUM_CHIPS, 0, false ); +//PARAM( NUM_CHIP_BITS, 0, false ); +//PARAM( MEMORY_SIZE_BITS, 0, false ); +//PARAM( DATA_BLOCK_BITS, 0, false ); +//PARAM( PAGE_SIZE_BITS, 0, false ); +//PARAM( NUM_PROCESSORS_BITS, 0, false ); +//PARAM( PROCS_PER_CHIP_BITS, 0, false ); +//PARAM( NUM_L2_BANKS_BITS, 0, false ); +//PARAM( NUM_L2_BANKS_PER_CHIP_BITS, 0, false ); +//PARAM( NUM_L2_BANKS_PER_CHIP, 0, false ); +//PARAM( NUM_MEMORIES_BITS, 0, false ); +//PARAM( NUM_MEMORIES_PER_CHIP, 0, false ); +//PARAM( MEMORY_MODULE_BITS, 0, false ); +//PARAM_ULONG( MEMORY_MODULE_BLOCKS, 0, false ); // TIMING PARAMETERS -PARAM( DIRECTORY_CACHE_LATENCY ); +//PARAM( DIRECTORY_CACHE_LATENCY, 6, false ); -PARAM( NULL_LATENCY ); -PARAM( ISSUE_LATENCY ); -PARAM( CACHE_RESPONSE_LATENCY ); -PARAM( L2_RESPONSE_LATENCY ); -PARAM( L2_TAG_LATENCY ); -PARAM( L1_RESPONSE_LATENCY ); -PARAM( MEMORY_RESPONSE_LATENCY_MINUS_2 ); -PARAM( DIRECTORY_LATENCY ); -PARAM( NETWORK_LINK_LATENCY ); -PARAM( COPY_HEAD_LATENCY ); -PARAM( ON_CHIP_LINK_LATENCY ); -PARAM( RECYCLE_LATENCY ); -PARAM( L2_RECYCLE_LATENCY ); -PARAM( TIMER_LATENCY ); -PARAM( TBE_RESPONSE_LATENCY ); -PARAM_BOOL( PERIODIC_TIMER_WAKEUPS ); +//PARAM( NULL_LATENCY, 1, false ); +//PARAM( ISSUE_LATENCY, 2, false ); +//PARAM( CACHE_RESPONSE_LATENCY, 12, false ); +//PARAM( L2_RESPONSE_LATENCY, 6, false ); +//PARAM( L2_TAG_LATENCY, 6, false ); +//PARAM( L1_RESPONSE_LATENCY, 3, false ); -// constants used by TM protocols -PARAM_BOOL( PROFILE_EXCEPTIONS ); -PARAM_BOOL( PROFILE_XACT ); -PARAM_BOOL( PROFILE_NONXACT ); -PARAM_BOOL( XACT_DEBUG ); -PARAM ( XACT_DEBUG_LEVEL ); -PARAM_BOOL( XACT_MEMORY ); -PARAM_BOOL( XACT_ENABLE_TOURMALINE ); -PARAM( XACT_NUM_CURRENT ); -PARAM( XACT_LAST_UPDATE ); -PARAM_BOOL( XACT_ISOLATION_CHECK ); -PARAM_BOOL( PERFECT_FILTER ); -PARAM_STRING( READ_WRITE_FILTER ); -PARAM_BOOL( PERFECT_VIRTUAL_FILTER ); -PARAM_STRING( VIRTUAL_READ_WRITE_FILTER ); -PARAM_BOOL( PERFECT_SUMMARY_FILTER ); -PARAM_STRING( SUMMARY_READ_WRITE_FILTER ); -PARAM_BOOL( XACT_EAGER_CD ); -PARAM_BOOL( XACT_LAZY_VM ); -PARAM_STRING( XACT_CONFLICT_RES ); -PARAM_BOOL( XACT_VISUALIZER ); -PARAM( XACT_COMMIT_TOKEN_LATENCY ) ; -PARAM_BOOL( XACT_NO_BACKOFF ); -PARAM ( XACT_LOG_BUFFER_SIZE ); -PARAM ( XACT_STORE_PREDICTOR_HISTORY); -PARAM ( XACT_STORE_PREDICTOR_ENTRIES); -PARAM ( XACT_STORE_PREDICTOR_THRESHOLD); -PARAM ( XACT_FIRST_ACCESS_COST ); -PARAM ( XACT_FIRST_PAGE_ACCESS_COST ); -PARAM_BOOL( ENABLE_MAGIC_WAITING ); -PARAM_BOOL( ENABLE_WATCHPOINT ); -PARAM_BOOL( XACT_ENABLE_VIRTUALIZATION_LOGTM_SE ); +//PARAM( MEMORY_RESPONSE_LATENCY_MINUS_2, 158, false ); +//PARAM( DirectoryLatency, 6, false ); -// ATMTP -PARAM_BOOL( ATMTP_ENABLED ); -PARAM_BOOL( ATMTP_ABORT_ON_NON_XACT_INST ); -PARAM_BOOL( ATMTP_ALLOW_SAVE_RESTORE_IN_XACT ); -PARAM( ATMTP_XACT_MAX_STORES ); -PARAM( ATMTP_DEBUG_LEVEL ); +//PARAM( NetworkLinkLatency, 1, false ); +//PARAM( COPY_HEAD_LATENCY, 4, false ); +//PARAM( OnChipLinkLatency, 1, false ); +//PARAM( RecycleLatency, 10, false ); +//PARAM( L2_RECYCLE_LATENCY, 5, false ); +//PARAM( TIMER_LATENCY, 10000, false ); +//PARAM( TBE_RESPONSE_LATENCY, 1, false ); +//PARAM_BOOL( PERIODIC_TIMER_WAKEUPS, true, false ); // constants used by CMP protocols -PARAM( L1_REQUEST_LATENCY ); -PARAM( L2_REQUEST_LATENCY ); -PARAM_BOOL( SINGLE_ACCESS_L2_BANKS ); // hack to simulate multi-cycle L2 bank accesses +//PARAM( L1_REQUEST_LATENCY, 2, false ); +//PARAM( L2_REQUEST_LATENCY, 4, false ); +//PARAM_BOOL( SINGLE_ACCESS_L2_BANKS, true, false ); // hack to simulate multi-cycle L2 bank accesses // Ruby cycles between when a sequencer issues a miss it arrives at // the L1 cache controller -PARAM( SEQUENCER_TO_CONTROLLER_LATENCY ); +//PARAM( SequencerToControllerLatency, 4, false ); // Number of transitions each controller state machines can complete per cycle -PARAM( L1CACHE_TRANSITIONS_PER_RUBY_CYCLE ); -PARAM( L2CACHE_TRANSITIONS_PER_RUBY_CYCLE ); -PARAM( DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE ); - -// Maximum number of requests (including prefetches) outstanding from -// the sequencer (Note: this also include items buffered in the store -// buffer) -PARAM( g_SEQUENCER_OUTSTANDING_REQUESTS ); +//PARAM( L1CacheTransitionsPerCycle, 32, false ); +//PARAM( L2CACHE_TRANSITIONS_PER_RUBY_CYCLE, 32, false ); +//PARAM( DirectoryTransitionsPerCycle, 32, false ); +//PARAM( DMATransitionsPerCycle, 1, false ); // Number of TBEs available for demand misses, prefetches, and replacements -PARAM( NUMBER_OF_TBES ); -PARAM( NUMBER_OF_L1_TBES ); -PARAM( NUMBER_OF_L2_TBES ); +//PARAM( NumberOfTBEs, 128, false ); +//PARAM( NumberOfL1TBEs, 32, false ); +//PARAM( NumberOfL2TBEs, 32, false ); // NOTE: Finite buffering allows us to simulate a wormhole routed network // with idealized flow control. All message buffers within the network (i.e. // the switch's input and output buffers) are set to the size specified below // by the PROTOCOL_BUFFER_SIZE -PARAM_BOOL( FINITE_BUFFERING ); -PARAM( FINITE_BUFFER_SIZE ); // Zero is unbounded buffers +//PARAM_BOOL( FiniteBuffering, false, false ); +//PARAM( FiniteBufferSize, 3, false ); // Zero is unbounded buffers // Number of requests buffered between the sequencer and the L1 conroller // This can be more accurately simulated in Opal, therefore it's set to an // infinite number // Only effects the simualtion when FINITE_BUFFERING is enabled -PARAM( PROCESSOR_BUFFER_SIZE ); +//PARAM( ProcessorBufferSize, 10, false ); // The PROTOCOL_BUFFER_SIZE limits the size of all other buffers connecting to // Controllers. Controlls the number of request issued by the L2 HW Prefetcher -PARAM( PROTOCOL_BUFFER_SIZE ); - -// Enable the TSO (Total Store Order) memory model -PARAM_BOOL( TSO ); // Note: This also disables the "write" STCs +//PARAM( ProtocolBufferSize, 32, false ); // NETWORK PARAMETERS // Network Topology: See TopologyType in external.sm for valid values -PARAM_STRING( g_NETWORK_TOPOLOGY ); +//PARAM_STRING( NetworkTopology, "PT_TO_PT", false ); // Cache Design specifies file prefix for topology -PARAM_STRING( g_CACHE_DESIGN ); +//PARAM_STRING( CacheDesign, "NUCA", false ); -PARAM( g_endpoint_bandwidth ); -PARAM_BOOL( g_adaptive_routing ); -PARAM( NUMBER_OF_VIRTUAL_NETWORKS ); -PARAM( FAN_OUT_DEGREE ); -PARAM_BOOL( g_PRINT_TOPOLOGY ); - -// transactional memory -PARAM( XACT_LENGTH ); -PARAM( XACT_SIZE ); -PARAM( ABORT_RETRY_TIME ); +//PARAM( EndpointBandwidth, 10000, false ); +//PARAM_BOOL( AdaptiveRouting, true, false ); +//PARAM( NumberOfVirtualNetworks, 6, false ); +//PARAM( FanOutDegree, 4, false ); +//PARAM_BOOL( PrintTopology, true, false ); // Princeton Network (Garnet) -PARAM_BOOL( g_GARNET_NETWORK ); -PARAM_BOOL( g_DETAIL_NETWORK ); -PARAM_BOOL( g_NETWORK_TESTING ); -PARAM( g_FLIT_SIZE ); -PARAM( g_NUM_PIPE_STAGES ); -PARAM( g_VCS_PER_CLASS ); -PARAM( g_BUFFER_SIZE ); +//PARAM_BOOL( UsingGarnetNetwork, true, false ); +//PARAM_BOOL( UsingDetailNetwork, false, false ); +//PARAM_BOOL( UsingNetworkTesting, false, false ); +//PARAM( FlitSize, 16, false ); +//PARAM( NumberOfPipeStages, 4, false ); +//PARAM( VCSPerClass, 4, false ); +//PARAM( BufferSize, 4, false ); // MemoryControl: -PARAM( MEM_BUS_CYCLE_MULTIPLIER ); -PARAM( BANKS_PER_RANK ); -PARAM( RANKS_PER_DIMM ); -PARAM( DIMMS_PER_CHANNEL ); -PARAM( BANK_BIT_0 ); -PARAM( RANK_BIT_0 ); -PARAM( DIMM_BIT_0 ); -PARAM( BANK_QUEUE_SIZE ); -PARAM( BANK_BUSY_TIME ); -PARAM( RANK_RANK_DELAY ); -PARAM( READ_WRITE_DELAY ); -PARAM( BASIC_BUS_BUSY_TIME ); -PARAM( MEM_CTL_LATENCY ); -PARAM( REFRESH_PERIOD ); -PARAM( TFAW ); -PARAM( MEM_RANDOM_ARBITRATE ); -PARAM( MEM_FIXED_DELAY ); +//PARAM( MEM_BUS_CYCLE_MULTIPLIER, 10, false ); +//PARAM( BANKS_PER_RANK, 8, false ); +//PARAM( RANKS_PER_DIMM, 2, false ); +//PARAM( DIMMS_PER_CHANNEL, 2, false ); +//PARAM( BANK_BIT_0, 8, false ); +//PARAM( RANK_BIT_0, 11, false ); +//PARAM( DIMM_BIT_0, 12, false ); +//PARAM( BANK_QUEUE_SIZE, 12, false ); +//PARAM( BankBusyTime, 11, false ); +//PARAM( RANK_RANK_DELAY, 1, false ); +//PARAM( READ_WRITE_DELAY, 2, false ); +//PARAM( BASIC_BUS_BUSY_TIME, 2, false ); +//PARAM( MEM_CTL_LATENCY, 12, false ); +//PARAM( REFRESH_PERIOD, 1560, false ); +//PARAM( TFAW, 0, false ); +//PARAM( MEM_RANDOM_ARBITRATE, 0, false ); +//PARAM( MEM_FIXED_DELAY, 0, false ); diff --git a/src/mem/ruby/config/defaults.rb b/src/mem/ruby/config/defaults.rb new file mode 100644 index 0000000000..110bf42411 --- /dev/null +++ b/src/mem/ruby/config/defaults.rb @@ -0,0 +1,181 @@ +#!/usr/bin/ruby + + + +class NetPort < LibRubyObject + # number of transitions a SLICC state machine can transition per + # cycle + default_param :transitions_per_cycle, Integer, 32 + + # buffer_size limits the size of all other buffers connecting to + # SLICC Controllers. When 0, infinite buffering is used. + default_param :buffer_size, Integer, 32 + + # added by SS for TBE + default_param :number_of_TBEs, Integer, 128 + + default_param :recycle_latency, Integer, 10 +end + +class Sequencer < IfacePort + # Maximum number of requests (including prefetches) outstanding from + # the sequencer + default_param :max_outstanding_requests, Integer, 16 + + # Maximum number of cycles a request is can be outstanding before + # the Sequencer declares we're in deadlock/livelock + default_param :deadlock_threshold, Integer, 500000 + +end + +class Debug < LibRubyObject + # For debugging purposes, one can enable a trace of all the protocol + # state machine changes. Unfortunately, the code to generate the + # trace is protocol specific. To enable the code for some of the + # standard protocols, + # 1. change protocol_trace = true + # 2. enable debug in the Ruby Makefile + # 3. set start_time = 1 + default_param :protocol_trace, Boolean, false + + # a string for filtering debugging output (for all g_debug vars see Debug.h) + default_param :filter_string, String, "q" + + # filters debugging messages based on priority (low, med, high) + default_param :verbosity_string, String, "none" + + # filters debugging messages based on a ruby time + default_param :start_time, Integer, 1 + + # sends debugging messages to a output filename + default_param :output_filename, String, "" +end + +class Topology < LibRubyObject + # The default link latency between all nodes (internal and external) + # in the toplogy + default_param :link_latency, Integer, 1 + + # the bandwidth from an external network port to it's corresponding + # internal switch + default_param :external_bw, Integer, 64 + + # the bandwitch between internal switches in the network + default_param :internal_bw, Integer, 16 + + # indicates whether the topology config will be displayed in the + # stats file + default_param :print_config, Boolean, true +end + +class Network < LibRubyObject + default_param :endpoint_bandwidth, Integer, 10000 + default_param :adaptive_routing, Boolean, true + default_param :number_of_virtual_networks, Integer, 6 + default_param :fan_out_degree, Integer, 4 + + # default buffer size. Setting to 0 indicates infinite buffering + default_param :buffer_size, Integer, 3 + + # local memory latency ?? NetworkLinkLatency + default_param :link_latency, Integer, 1 + + # on chip latency + default_param :on_chip_latency, Integer, 1 +end + +class GarnetNetwork < Network + default_param :flit_size, Integer, 16 + default_param :number_of_pipe_stages, Integer, 4 + default_param :vcs_per_class, Integer, 4 + default_param :buffer_size, Integer, 4 + default_param :using_network_testing, Boolean, false +end + + + +#added by SS +class Tracer < LibRubyObject + default_param :warmup_length, Integer, 1000000 +end + +#added by SS +class Profiler < LibRubyObject + default_param :hot_lines, Boolean, false + default_param :all_instructions, Boolean, false +end + +#added by SS +class MI_example_CacheController < CacheController + default_param :issue_latency, Integer, 2 + default_param :cache_response_latency, Integer, 12 +end + +class MI_example_DirectoryController < DirectoryController + default_param :to_mem_ctrl_latency, Integer, 1 + default_param :directory_latency, Integer, 6 + default_param :memory_latency, Integer, 158 +end + + +#added by SS +class MemoryControl < LibRubyObject + + default_param :mem_bus_cycle_multiplier, Integer, 10 + default_param :banks_per_rank, Integer, 8 + default_param :ranks_per_dimm, Integer, 2 + default_param :dimms_per_channel, Integer, 2 + default_param :bank_bit_0, Integer, 8 + default_param :rank_bit_0, Integer, 11 + default_param :dimm_bit_0, Integer, 12 + default_param :bank_queue_size, Integer, 12 + default_param :bank_busy_time, Integer, 11 + default_param :rank_rank_delay, Integer, 1 + default_param :read_write_delay, Integer, 2 + default_param :basic_bus_busy_time, Integer, 2 + default_param :mem_ctl_latency, Integer, 12 + default_param :refresh_period, Integer, 1560 + default_param :tFaw, Integer, 0 + default_param :mem_random_arbitrate, Integer, 0 + default_param :mem_fixed_delay, Integer, 0 + +end + +class RubySystem + + # Random seed used by the simulation. If set to "rand", the seed + # will be set to the current wall clock at libruby + # initialization. Otherwise, set this to an integer. + default_param :random_seed, Object, "rand" + + # When set to true, the simulation will insert random delays on + # message enqueue times. Note that even if this is set to false, + # you can still have a non-deterministic simulation if random seed + # is set to "rand". This is because the Ruby swtiches use random + # link priority elevation + default_param :randomization, Boolean, false + + # tech_nm is the device size used to calculate latency and area + # information about system components + default_param :tech_nm, Integer, 45 + + # default frequency for the system + default_param :freq_mhz, Integer, 3000 + + # the default cache block size in the system + # libruby does not currently support different block sizes + # among different caches + # Must be a power of two + default_param :block_size_bytes, Integer, 64 + + # The default debug object. There shouldn't be a reason to ever + # change this line. To adjust debug paramters statically, adjust + # them in the Debug class above. To adjust these fields + # dynamically, access this RubySystem object, + # e.g. RubySystem.debug.protocol_trace = true + default_param :debug, Debug, Debug.new("dbg0") + default_param :tracer, Tracer, Tracer.new("tracer0") + + default_param :profiler, Profiler, Profiler.new("profiler0") +end + diff --git a/src/mem/ruby/config/libruby_cfg_test.cc b/src/mem/ruby/config/libruby_cfg_test.cc new file mode 100644 index 0000000000..5d5b69d5fd --- /dev/null +++ b/src/mem/ruby/config/libruby_cfg_test.cc @@ -0,0 +1,14 @@ + +#include +#include + +#include "../libruby.hh" + +int main(int argc, char* argv[]) +{ + assert(argc == 2); + const char* cfg_file = argv[1]; + + libruby_init(cfg_file); + libruby_print_config(std::cout); +} diff --git a/src/mem/ruby/config/print_cfg.rb b/src/mem/ruby/config/print_cfg.rb new file mode 100644 index 0000000000..0a6d180d40 --- /dev/null +++ b/src/mem/ruby/config/print_cfg.rb @@ -0,0 +1,14 @@ + +ruby_cfg_file = nil +$stderr.puts $*.inspect +for i in 0..$*.size-1 do + if $*[i] == "-r" # ruby config file + i += 1 + ruby_cfg_file = $*[i] + break + end +end + +require ruby_cfg_file + +RubySystem.generateConfig diff --git a/src/mem/ruby/config/rubyconfig.defaults b/src/mem/ruby/config/rubyconfig.defaults index 873192c056..936a2f091f 100644 --- a/src/mem/ruby/config/rubyconfig.defaults +++ b/src/mem/ruby/config/rubyconfig.defaults @@ -43,10 +43,6 @@ g_DEADLOCK_THRESHOLD: 500000 // (does not apply when running Opal) SIMICS_RUBY_MULTIPLIER: 4 -// corresponding parameter when using Opal+Ruby+Simics -OPAL_RUBY_MULTIPLIER: 1 - - // Ruby cycles between when a sequencer issues a request and it arrives at // the L1 cache controller // @@ -107,7 +103,7 @@ L2_CACHE_ASSOC: 4 L2_CACHE_NUM_SETS_BITS: 16 // 32 bits = 4 GB address space -g_MEMORY_SIZE_BYTES: 4294967296 +g_MEMORY_SIZE_BYTES: 1073741824 //4294967296 g_DATA_BLOCK_BYTES: 64 g_PAGE_SIZE_BYTES: 4096 g_REPLACEMENT_POLICY: PSEDUO_LRU // currently, only other option is LRU @@ -176,8 +172,6 @@ L1_REQUEST_LATENCY: 2 L2_REQUEST_LATENCY: 4 - - // Number of transitions each controller state machines can complete per cycle // i.e. the number of ports to each controller // L1cache is the sum of the L1I and L1D cache ports @@ -186,6 +180,7 @@ L1CACHE_TRANSITIONS_PER_RUBY_CYCLE: 32 // much greater constraint on the concurrency of a L2 cache bank L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 32 DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 32 +DMA_TRANSITIONS_PER_RUBY_CYCLE: 1 // Number of TBEs available for demand misses, ALL prefetches, and replacements @@ -195,10 +190,6 @@ NUMBER_OF_TBES: 128 NUMBER_OF_L1_TBES: 32 NUMBER_OF_L2_TBES: 32 -// TSO is deprecated -TSO: false - - // ** INTERCONECT PARAMETERS ** // g_PRINT_TOPOLOGY: true @@ -207,7 +198,7 @@ g_CACHE_DESIGN: NUCA // specifies file prefix for FILE_SPECIFIED topology FAN_OUT_DEGREE: 4 // for HIERARCHICAL SWITCH topology g_adaptive_routing: true -NUMBER_OF_VIRTUAL_NETWORKS: 4 +NUMBER_OF_VIRTUAL_NETWORKS: 6 // bandwidth unit is 1/1000 byte per cycle. the following parameter is multiplied by // topology specific link weights @@ -240,57 +231,6 @@ PROTOCOL_BUFFER_SIZE: 32 SINGLE_ACCESS_L2_BANKS: true -// constants used by TM protocols -PROFILE_EXCEPTIONS: false -PROFILE_XACT: true -PROFILE_NONXACT: false -XACT_DEBUG: true -XACT_DEBUG_LEVEL: 1 -//XACT_MEMORY: true // set to true for TM protocols. set it HERE for lazy systems to register the proper SIMICS interfaces -XACT_MEMORY: false -XACT_ENABLE_TOURMALINE: false // perfect memory system -XACT_NUM_CURRENT: 0 // must be 0 -XACT_LAST_UPDATE: 0 // must be 0 -XACT_ISOLATION_CHECK: false // Checks whether each memory access preserves transaction isolation -PERFECT_FILTER: true // If true, use perfect physical read/write filters -READ_WRITE_FILTER: Perfect_ -PERFECT_VIRTUAL_FILTER: true // If true, use perfect virtual read/write filters -VIRTUAL_READ_WRITE_FILTER: Perfect_ -PERFECT_SUMMARY_FILTER: true // If true, use perfect summary read/write filters -SUMMARY_READ_WRITE_FILTER: Perfect_ -XACT_EAGER_CD: true -XACT_LAZY_VM: false -XACT_CONFLICT_RES: BASE -XACT_COMMIT_TOKEN_LATENCY: 0 -XACT_VISUALIZER: false -XACT_NO_BACKOFF: false -XACT_LOG_BUFFER_SIZE: 0 -XACT_STORE_PREDICTOR_ENTRIES: 256 -XACT_STORE_PREDICTOR_HISTORY: 256 -XACT_STORE_PREDICTOR_THRESHOLD: 4 -XACT_FIRST_ACCESS_COST: 0 -XACT_FIRST_PAGE_ACCESS_COST: 0 -ENABLE_MAGIC_WAITING: false -ENABLE_WATCHPOINT: false -XACT_ENABLE_VIRTUALIZATION_LOGTM_SE: false -// g_NETWORK_TOPOLOGY: FILE_SPECIFIED -// NUMBER_OF_VIRTUAL_NETWORKS: 5 -// L2_REQUEST_LATENCY: 15 -// SEQUENCER_TO_CONTROLLER_LATENCY: 3 -// L2_RESPONSE_LATENCY: 20 -// L2_TAG_LATENCY: 6 -// MEMORY_RESPONSE_LATENCY_MINUS_2: 448 -// RECYCLE_LATENCY: 1 -// g_MEMORY_SIZE_BYTES: 268435456 -// REMOVE_SINGLE_CYCLE_DCACHE_FAST_PATH: true - -// ATMTP -ATMTP_ENABLED: false -ATMTP_ABORT_ON_NON_XACT_INST: false -ATMTP_ALLOW_SAVE_RESTORE_IN_XACT: false -ATMTP_XACT_MAX_STORES: 32 -ATMTP_DEBUG_LEVEL: 0 - // MOESI_CMP_token parameters (some might be deprecated) g_FILTERING_ENABLED: false g_DISTRIBUTED_PERSISTENT_ENABLED: true @@ -321,7 +261,7 @@ g_hold_time: 5 g_wait_time: 5 // Princeton Network (Garnet) -g_GARNET_NETWORK: false +g_GARNET_NETWORK: true g_DETAIL_NETWORK: false g_NETWORK_TESTING: false g_FLIT_SIZE: 16 diff --git a/src/mem/ruby/config/tester.defaults b/src/mem/ruby/config/tester.defaults index 6ba6557700..b30d1ba99b 100644 --- a/src/mem/ruby/config/tester.defaults +++ b/src/mem/ruby/config/tester.defaults @@ -6,10 +6,11 @@ // Please: - Add new variables only to rubyconfig.defaults file. // - Change them here only when necessary. +g_SIMICS: false DATA_BLOCK: true RANDOMIZATION: true -g_SYNTHETIC_DRIVER: true -g_DETERMINISTIC_DRIVER: false +g_SYNTHETIC_DRIVER: false +g_DETERMINISTIC_DRIVER: true g_DEADLOCK_THRESHOLD: 500000 g_SpecifiedGenerator: DetermGETXGenerator @@ -28,23 +29,13 @@ L2_CACHE_NUM_SETS_BITS: 5 g_MEMORY_SIZE_BYTES: 1048576 -// XACT MEMORY -XACT_LENGTH: 2000 -XACT_SIZE: 1000 -ABORT_RETRY_TIME: 400 -XACT_ISOLATION_CHECK: true -L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000 -DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000 -PERFECT_FILTER: true // If true, use perfect read/write filters -READ_WRITE_FILTER: Perfect_ - //g_NETWORK_TOPOLOGY: FILE_SPECIFIED RECYCLE_LATENCY: 1 //NUMBER_OF_VIRTUAL_NETWORKS: 5 //g_NUM_MEMORIES: 16 L2CACHE_TRANSITIONS_PER_RUBY_CYCLE: 1000 DIRECTORY_TRANSITIONS_PER_RUBY_CYCLE: 1000 -//g_PROCS_PER_CHIP: 16 +//g_PROCS_PER_CHIP: 2 //g_NUM_L2_BANKS: 16 //g_endpoint_bandwidth: 10000 //g_NUM_PROCESSORS: 16 diff --git a/src/mem/ruby/eventqueue/RubyEventQueue.cc b/src/mem/ruby/eventqueue/RubyEventQueue.cc index 4a979942ff..1a4159f1da 100644 --- a/src/mem/ruby/eventqueue/RubyEventQueue.cc +++ b/src/mem/ruby/eventqueue/RubyEventQueue.cc @@ -49,7 +49,7 @@ RubyEventQueue::RubyEventQueue() RubyEventQueue::~RubyEventQueue() { - // delete m_prio_heap_ptr; + delete m_prio_heap_ptr; } void RubyEventQueue::init() @@ -91,7 +91,7 @@ void RubyEventQueue::triggerEvents(Time t) assert(thisNode.m_consumer_ptr != NULL); DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr)); DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time); - thisNode.m_consumer_ptr->triggerWakeup(); + thisNode.m_consumer_ptr->triggerWakeup(this); } m_globalTime = t; } @@ -107,7 +107,7 @@ void RubyEventQueue::triggerAllEvents() assert(thisNode.m_consumer_ptr != NULL); DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,*(thisNode.m_consumer_ptr)); DEBUG_EXPR(EVENTQUEUE_COMP,MedPrio,thisNode.m_time); - thisNode.m_consumer_ptr->triggerWakeup(); + thisNode.m_consumer_ptr->triggerWakeup(this); } } diff --git a/src/mem/ruby/filters/AbstractBloomFilter.hh b/src/mem/ruby/filters/AbstractBloomFilter.hh new file mode 100644 index 0000000000..7e37a6e068 --- /dev/null +++ b/src/mem/ruby/filters/AbstractBloomFilter.hh @@ -0,0 +1,71 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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. + */ + +/* + * AbstractBloomFilter.hh + * + * Description: + * + * + */ + +#ifndef ABSTRACT_BLOOM_FILTER_H +#define ABSTRACT_BLOOM_FILTER_H + +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/common/Address.hh" + +class AbstractBloomFilter { +public: + + virtual ~AbstractBloomFilter() {}; + virtual void clear() = 0; + virtual void increment(const Address& addr) = 0; + virtual void decrement(const Address& addr) = 0; + virtual void merge(AbstractBloomFilter * other_filter) = 0; + virtual void set(const Address& addr) = 0; + virtual void unset(const Address& addr) = 0; + + virtual bool isSet(const Address& addr) = 0; + virtual int getCount(const Address& addr) = 0; + virtual int getTotalCount() = 0; + + virtual void print(ostream& out) const = 0; + + virtual int getIndex(const Address& addr) = 0; + virtual int readBit(const int index) = 0; + virtual void writeBit(const int index, const int value) = 0; + +private: + +}; + + +#endif diff --git a/src/mem/ruby/filters/BlockBloomFilter.cc b/src/mem/ruby/filters/BlockBloomFilter.cc new file mode 100644 index 0000000000..9bf5b41c5a --- /dev/null +++ b/src/mem/ruby/filters/BlockBloomFilter.cc @@ -0,0 +1,147 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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. + */ + +/* + * BlockBloomFilter.cc + * + * Description: + * + * + */ + +#include "mem/ruby/filters/BlockBloomFilter.hh" +#include "mem/gems_common/Map.hh" +#include "mem/ruby/common/Address.hh" + +BlockBloomFilter::BlockBloomFilter(string str) +{ + string tail(str); + string head = string_split(tail, '_'); + + m_filter_size = atoi(head.c_str()); + m_filter_size_bits = log_int(m_filter_size); + + m_filter.setSize(m_filter_size); + + clear(); +} + +BlockBloomFilter::~BlockBloomFilter(){ +} + +void BlockBloomFilter::clear() +{ + for (int i = 0; i < m_filter_size; i++) { + m_filter[i] = 0; + } +} + +void BlockBloomFilter::increment(const Address& addr) +{ + // Not used +} + + +void BlockBloomFilter::decrement(const Address& addr) +{ + // Not used +} + +void BlockBloomFilter::merge(AbstractBloomFilter * other_filter) +{ + // TODO +} + +void BlockBloomFilter::set(const Address& addr) +{ + int i = get_index(addr); + m_filter[i] = 1; +} + +void BlockBloomFilter::unset(const Address& addr) +{ + int i = get_index(addr); + m_filter[i] = 0; +} + +bool BlockBloomFilter::isSet(const Address& addr) +{ + int i = get_index(addr); + return (m_filter[i]); +} + + +int BlockBloomFilter::getCount(const Address& addr) +{ + return m_filter[get_index(addr)]; +} + +int BlockBloomFilter::getTotalCount() +{ + int count = 0; + + for (int i = 0; i < m_filter_size; i++) { + if (m_filter[i]) { + count++; + } + } + return count; +} + +int BlockBloomFilter::getIndex(const Address& addr) +{ + return get_index(addr); +} + +void BlockBloomFilter::print(ostream& out) const +{ +} + +int BlockBloomFilter::readBit(const int index) { + return m_filter[index]; +} + +void BlockBloomFilter::writeBit(const int index, const int value) { + m_filter[index] = value; +} + +int BlockBloomFilter::get_index(const Address& addr) +{ + // Pull out some bit field ==> B1 + // Pull out additional bits, not the same as B1 ==> B2 + // XOR B1 and B2 to get hash index + physical_address_t block_bits = addr.bitSelect( RubySystem::getBlockSizeBits(), 2*RubySystem::getBlockSizeBits() - 1); + int offset = 5; + physical_address_t other_bits = addr.bitSelect( 2*RubySystem::getBlockSizeBits() + offset, 2*RubySystem::getBlockSizeBits() + offset + m_filter_size_bits - 1); + int index = block_bits ^ other_bits; + assert(index < m_filter_size); + return index; +} + + diff --git a/src/mem/ruby/filters/BlockBloomFilter.hh b/src/mem/ruby/filters/BlockBloomFilter.hh new file mode 100644 index 0000000000..205b4172d4 --- /dev/null +++ b/src/mem/ruby/filters/BlockBloomFilter.hh @@ -0,0 +1,82 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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. + */ + +/* + * BlockBloomFilter.hh + * + * Description: + * + * + */ + +#ifndef BLOCK_BLOOM_FILTER_H +#define BLOCK_BLOOM_FILTER_H + +#include "mem/gems_common/Map.hh" +#include "mem/ruby/common/Global.hh" +#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/filters/AbstractBloomFilter.hh" + +class BlockBloomFilter : public AbstractBloomFilter { +public: + + ~BlockBloomFilter(); + BlockBloomFilter(string config); + + void clear(); + void increment(const Address& addr); + void decrement(const Address& addr); + void merge(AbstractBloomFilter * other_filter); + void set(const Address& addr); + void unset(const Address& addr); + + bool isSet(const Address& addr); + int getCount(const Address& addr); + int getTotalCount(); + int getIndex(const Address& addr); + int readBit(const int index); + void writeBit(const int index, const int value); + + void print(ostream& out) const; + +private: + + int get_index(const Address& addr); + + Vector m_filter; + int m_filter_size; + int m_filter_size_bits; + + int m_count_bits; + int m_count; +}; + + +#endif diff --git a/src/mem/ruby/filters/BulkBloomFilter.cc b/src/mem/ruby/filters/BulkBloomFilter.cc new file mode 100644 index 0000000000..264b4201c9 --- /dev/null +++ b/src/mem/ruby/filters/BulkBloomFilter.cc @@ -0,0 +1,232 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * 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. + */ + +/* + * BulkBloomFilter.cc + * + * Description: + * + * + */ + +#include "mem/ruby/filters/BulkBloomFilter.hh" +#include "mem/gems_common/Map.hh" +#include "mem/ruby/common/Address.hh" + +BulkBloomFilter::BulkBloomFilter(string str) +{ + string tail(str); + string head = string_split(tail, '_'); + + m_filter_size = atoi(head.c_str()); + m_filter_size_bits = log_int(m_filter_size); + // split the filter bits in half, c0 and c1 + m_sector_bits = m_filter_size_bits - 1; + + m_temp_filter.setSize(m_filter_size); + m_filter.setSize(m_filter_size); + clear(); + + // clear temp filter + for(int i=0; i < m_filter_size; ++i){ + m_temp_filter[i] = 0; + } +} + +BulkBloomFilter::~BulkBloomFilter(){ + +} + +void BulkBloomFilter::clear() +{ + for (int i = 0; i < m_filter_size; i++) { + m_filter[i] = 0; + } +} + +void BulkBloomFilter::increment(const Address& addr) +{ + // Not used +} + + +void BulkBloomFilter::decrement(const Address& addr) +{ + // Not used +} + +void BulkBloomFilter::merge(AbstractBloomFilter * other_filter) +{ + // TODO +} + +void BulkBloomFilter::set(const Address& addr) +{ + // c0 contains the cache index bits + int set_bits = m_sector_bits; + int block_bits = RubySystem::getBlockSizeBits(); + int c0 = addr.bitSelect( block_bits, block_bits + set_bits - 1); + // c1 contains the lower m_sector_bits permuted bits + //Address permuted_bits = permute(addr); + //int c1 = permuted_bits.bitSelect(0, set_bits-1); + int c1 = addr.bitSelect( block_bits+set_bits, (block_bits+2*set_bits) - 1); + //ASSERT(c0 < (m_filter_size/2)); + //ASSERT(c0 + (m_filter_size/2) < m_filter_size); + //ASSERT(c1 < (m_filter_size/2)); + // set v0 bit + m_filter[c0 + (m_filter_size/2)] = 1; + // set v1 bit + m_filter[c1] = 1; +} + +void BulkBloomFilter::unset(const Address& addr) +{ + // not used +} + +bool BulkBloomFilter::isSet(const Address& addr) +{ + // c0 contains the cache index bits + int set_bits = m_sector_bits; + int block_bits = RubySystem::getBlockSizeBits(); + int c0 = addr.bitSelect( block_bits, block_bits + set_bits - 1); + // c1 contains the lower 10 permuted bits + //Address permuted_bits = permute(addr); + //int c1 = permuted_bits.bitSelect(0, set_bits-1); + int c1 = addr.bitSelect( block_bits+set_bits, (block_bits+2*set_bits) - 1); + //ASSERT(c0 < (m_filter_size/2)); + //ASSERT(c0 + (m_filter_size/2) < m_filter_size); + //ASSERT(c1 < (m_filter_size/2)); + // set v0 bit + m_temp_filter[c0 + (m_filter_size/2)] = 1; + // set v1 bit + m_temp_filter[c1] = 1; + + // perform filter intersection. If any c part is 0, no possibility of address being in signature. + // get first c intersection part + bool zero = false; + for(int i=0; i < m_filter_size/2; ++i){ + // get intersection of signatures + m_temp_filter[i] = m_temp_filter[i] && m_filter[i]; + zero = zero || m_temp_filter[i]; + } + zero = !zero; + if(zero){ + // one section is zero, no possiblility of address in signature + // reset bits we just set + m_temp_filter[c0 + (m_filter_size/2)] = 0; + m_temp_filter[c1] = 0; + return false; + } + + // check second section + zero = false; + for(int i=m_filter_size/2; i < m_filter_size; ++i){ + // get intersection of signatures + m_temp_filter[i] = m_temp_filter[i] && m_filter[i]; + zero = zero || m_temp_filter[i]; + } + zero = !zero; + if(zero){ + // one section is zero, no possiblility of address in signature + m_temp_filter[c0 + (m_filter_size/2)] = 0; + m_temp_filter[c1] = 0; + return false; + } + // one section has at least one bit set + m_temp_filter[c0 + (m_filter_size/2)] = 0; + m_temp_filter[c1] = 0; + return true; +} + + +int BulkBloomFilter::getCount(const Address& addr) +{ + // not used + return 0; +} + +int BulkBloomFilter::getTotalCount() +{ + int count = 0; + for (int i = 0; i < m_filter_size; i++) { + if (m_filter[i]) { + count++; + } + } + return count; +} + +int BulkBloomFilter::getIndex(const Address& addr) +{ + return get_index(addr); +} + +int BulkBloomFilter::readBit(const int index) { + return 0; + // TODO +} + +void BulkBloomFilter::writeBit(const int index, const int value) { + // TODO +} + +void BulkBloomFilter::print(ostream& out) const +{ +} + +int BulkBloomFilter::get_index(const Address& addr) +{ + return addr.bitSelect( RubySystem::getBlockSizeBits(), RubySystem::getBlockSizeBits() + m_filter_size_bits - 1); +} + +Address BulkBloomFilter::permute(const Address & addr){ + // permutes the original address bits according to Table 5 + int block_offset = RubySystem::getBlockSizeBits(); + physical_address_t part1 = addr.bitSelect( block_offset, block_offset + 6 ); + physical_address_t part2 = addr.bitSelect( block_offset + 9, block_offset + 9 ); + physical_address_t part3 = addr.bitSelect( block_offset + 11, block_offset + 11 ); + physical_address_t part4 = addr.bitSelect( block_offset + 17, block_offset + 17 ); + physical_address_t part5 = addr.bitSelect( block_offset + 7, block_offset + 8 ); + physical_address_t part6 = addr.bitSelect( block_offset + 10, block_offset + 10 ); + physical_address_t part7 = addr.bitSelect( block_offset + 12, block_offset + 12 ); + physical_address_t part8 = addr.bitSelect( block_offset + 13, block_offset + 13 ); + physical_address_t part9 = addr.bitSelect( block_offset + 15, block_offset + 16 ); + physical_address_t part10 = addr.bitSelect( block_offset + 18, block_offset + 20 ); + physical_address_t part11 = addr.bitSelect( block_offset + 14, block_offset + 14 ); + + physical_address_t result = (part1 << 14 ) | (part2 << 13 ) | (part3 << 12 ) | (part4 << 11 ) | (part5 << 9) | (part6 << 8) + | (part7 << 7) | (part8 << 6) | (part9 << 4) | (part10 << 1) | (part11); + // assume 32 bit addresses (both virtual and physical) + // select the remaining high-order 11 bits + physical_address_t remaining_bits = (addr.bitSelect( block_offset + 21, 31 )) << 21; + result = result | remaining_bits; + + return Address(result); +} diff --git a/src/mem/ruby/tester/Tester.hh b/src/mem/ruby/filters/BulkBloomFilter.hh similarity index 60% rename from src/mem/ruby/tester/Tester.hh rename to src/mem/ruby/filters/BulkBloomFilter.hh index 7b721e038a..2dbdb66123 100644 --- a/src/mem/ruby/tester/Tester.hh +++ b/src/mem/ruby/filters/BulkBloomFilter.hh @@ -28,66 +28,60 @@ */ /* - * $Id$ + * BulkBloomFilter.hh * * Description: * + * */ -#ifndef TESTER_H -#define TESTER_H +#ifndef BULK_BLOOM_FILTER_H +#define BULK_BLOOM_FILTER_H +#include "mem/gems_common/Map.hh" #include "mem/ruby/common/Global.hh" -#include "mem/ruby/common/Driver.hh" -#include "mem/ruby/tester/CheckTable.hh" -#include "mem/protocol/CacheRequestType.hh" +#include "mem/ruby/config/RubyConfig.hh" +#include "mem/ruby/common/Address.hh" +#include "mem/ruby/filters/AbstractBloomFilter.hh" -class RubySystem; - -class Tester : public Driver, public Consumer { +class BulkBloomFilter : public AbstractBloomFilter { public: - // Constructors - Tester(RubySystem* sys_ptr); - // Destructor - ~Tester(); + ~BulkBloomFilter(); + BulkBloomFilter(string config); - // Public Methods + void clear(); + void increment(const Address& addr); + void decrement(const Address& addr); + void merge(AbstractBloomFilter * other_filter); + void set(const Address& addr); + void unset(const Address& addr); - void hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread); - void wakeup(); - void printStats(ostream& out) const {} - void clearStats() {} - void printConfig(ostream& out) const {} + bool isSet(const Address& addr); + int getCount(const Address& addr); + int getTotalCount(); + int getIndex(const Address& addr); + int readBit(const int index); + void writeBit(const int index, const int value); void print(ostream& out) const; + private: - // Private Methods - void checkForDeadlock(); + int get_index(const Address& addr); + Address permute(const Address & addr); - // Private copy constructor and assignment operator - Tester(const Tester& obj); - Tester& operator=(const Tester& obj); + Vector m_filter; + Vector m_temp_filter; - // Data Members (m_ prefix) + int m_filter_size; + int m_filter_size_bits; - CheckTable m_checkTable; - Vector