diff options
Diffstat (limited to 'src/mem/ruby/common')
25 files changed, 3989 insertions, 0 deletions
diff --git a/src/mem/ruby/common/Address.cc b/src/mem/ruby/common/Address.cc new file mode 100644 index 000000000..5d38faae0 --- /dev/null +++ b/src/mem/ruby/common/Address.cc @@ -0,0 +1,68 @@ + +/* + * 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 "Address.hh" + +void Address::output(ostream& out) const +{ + // Note: this outputs addresses in the form "ffff", not "0xffff". + // This code should always be able to write out addresses in a + // format that can be read in by the below input() method. Please + // don't change this without talking to Milo first. + out << hex << m_address << dec; +} + +void Address::input(istream& in) +{ + // Note: this only works with addresses in the form "ffff", not + // "0xffff". This code should always be able to read in addresses + // written out by the above output() method. Please don't change + // this without talking to Milo first. + in >> hex >> m_address >> dec; +} + +Address::Address(const Address& obj) +{ + m_address = obj.m_address; +} + +Address& Address::operator=(const Address& obj) +{ + if (this == &obj) { + // assert(false); + } else { + m_address = obj.m_address; + } + return *this; +} + diff --git a/src/mem/ruby/common/Address.hh b/src/mem/ruby/common/Address.hh new file mode 100644 index 000000000..3c3c5ad30 --- /dev/null +++ b/src/mem/ruby/common/Address.hh @@ -0,0 +1,255 @@ + +/* + * Copyright (c) 1999 by Mark Hill and David Wood for the Wisconsin + * Multifacet Project. ALL RIGHTS RESERVED. + * + * ##HEADER## + * + * This software is furnished under a license and may be used and + * copied only in accordance with the terms of such license and the + * inclusion of the above copyright notice. This software or any + * other copies thereof or any derivative works may not be provided or + * otherwise made available to any other persons. Title to and + * ownership of the software is retained by Mark Hill and David Wood. + * Any use of this software must include the above copyright notice. + * + * THIS SOFTWARE IS PROVIDED "AS IS". THE LICENSOR MAKES NO + * WARRANTIES ABOUT ITS CORRECTNESS OR PERFORMANCE. + * */ + +/* + * $Id$ + */ + +#ifndef ADDRESS_H +#define ADDRESS_H + +#include <iomanip> +#include "Global.hh" +#include "RubyConfig.hh" +#include "NodeID.hh" +#include "MachineID.hh" + +const int ADDRESS_WIDTH = 64; // address width in bytes + +class Address; +typedef Address PhysAddress; +typedef Address VirtAddress; + +class Address { +public: + // Constructors + Address() { m_address = 0; } + explicit Address(physical_address_t address) { m_address = address; } + + Address(const Address& obj); + Address& operator=(const Address& obj); + + // Destructor + // ~Address(); + + // Public Methods + + void setAddress(physical_address_t address) { m_address = address; } + physical_address_t getAddress() const {return m_address;} + // selects bits inclusive + physical_address_t bitSelect(int small, int big) const; + physical_address_t maskLowOrderBits(int number) const; + 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); } + physical_address_t getOffset() const + { return bitSelect(0, RubyConfig::dataBlockBits()-1); } + + void makeLineAddress() { m_address = maskLowOrderBits(RubyConfig::dataBlockBits()); } + // returns the next stride address based on line address + void makeNextStrideAddress( int stride) { + m_address = maskLowOrderBits(RubyConfig::dataBlockBits()) + + RubyConfig::dataBlockBytes()*stride; + } + void makePageAddress() { m_address = maskLowOrderBits(RubyConfig::pageSizeBits()); } + int getBankSetNum() const; + int getBankSetDist() const; + + Index memoryModuleIndex() const; + + void print(ostream& out) const; + void output(ostream& out) const; + void input(istream& in); + + void setOffset( int offset ){ + // first, zero out the offset bits + makeLineAddress(); + m_address |= (physical_address_t) offset; + } + +private: + // Private Methods + + // Private copy constructor and assignment operator + // Address(const Address& obj); + // Address& operator=(const Address& obj); + + // Data Members (m_ prefix) + physical_address_t m_address; +}; + +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; + temp.makeNextStrideAddress(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); +// comparison operator declaration +bool operator==(const Address& obj1, const Address& obj2); +bool operator!=(const Address& obj1, const Address& obj2); +bool operator<(const Address& obj1, const Address& obj2); +/* Address& operator=(const physical_address_t address); */ + +inline +bool operator<(const Address& obj1, const Address& obj2) +{ + return obj1.getAddress() < obj2.getAddress(); +} + +// ******************* Definitions ******************* + +// Output operator definition +inline +ostream& operator<<(ostream& out, const Address& obj) +{ + obj.print(out); + out << flush; + return out; +} + +inline +bool operator==(const Address& obj1, const Address& obj2) +{ + return (obj1.getAddress() == obj2.getAddress()); +} + +inline +bool operator!=(const Address& obj1, const Address& obj2) +{ + return (obj1.getAddress() != obj2.getAddress()); +} + +inline +physical_address_t Address::bitSelect(int small, int big) const // rips bits inclusive +{ + physical_address_t mask; + assert(big >= small); + + if (big >= ADDRESS_WIDTH - 1) { + return (m_address >> small); + } else { + mask = ~((physical_address_t)~0 << (big + 1)); + // FIXME - this is slow to manipulate a 64-bit number using 32-bits + physical_address_t partial = (m_address & mask); + return (partial >> small); + } +} + +inline +physical_address_t Address::maskLowOrderBits(int number) const +{ + physical_address_t mask; + + if (number >= ADDRESS_WIDTH - 1) { + mask = ~0; + } else { + mask = (physical_address_t)~0 << number; + } + return (m_address & mask); +} + +inline +physical_address_t Address::maskHighOrderBits(int number) const +{ + physical_address_t mask; + + if (number >= ADDRESS_WIDTH - 1) { + mask = ~0; + } else { + mask = (physical_address_t)~0 >> number; + } + return (m_address & mask); +} + +inline +physical_address_t Address::shiftLowOrderBits(int number) const +{ + return (m_address >> number); +} + +inline +integer_t Address::memoryModuleIndex() const +{ + integer_t index = bitSelect(RubyConfig::dataBlockBits()+RubyConfig::memoryBits(), 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 + << "error: limit exceeded. " << + " dataBlockBits: " << RubyConfig::dataBlockBits() << + " 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); + // Index indexLowPortion = address.bitSelect(DATA_BLOCK_BITS, PAGE_SIZE_BITS-1); + + //Index index = indexLowPortion | (indexHighPortion << (PAGE_SIZE_BITS - DATA_BLOCK_BITS)); + + /* + Round-robin mapping of addresses, at page size granularity + +ADDRESS_WIDTH MEMORY_SIZE_BITS PAGE_SIZE_BITS DATA_BLOCK_BITS + | | | | + \ / \ / \ / \ / 0 + ----------------------------------------------------------------------- + | unused |xxxxxxxxxxxxxxx| |xxxxxxxxxxxxxxx| | + | |xxxxxxxxxxxxxxx| |xxxxxxxxxxxxxxx| | + ----------------------------------------------------------------------- + indexHighPortion indexLowPortion + <-------> + NUMBER_OF_MEMORY_MODULE_BITS + */ +} + +inline +void Address::print(ostream& out) const +{ + out << "[" << hex << "0x" << m_address << "," << " line 0x" << maskLowOrderBits(RubyConfig::dataBlockBits()) << dec << "]" << flush; +} + +class Address; +namespace __gnu_cxx { + template <> struct hash<Address> + { + size_t operator()(const Address &s) const { return (size_t) s.getAddress(); } + }; +} +namespace std { + template <> struct equal_to<Address> + { + bool operator()(const Address& s1, const Address& s2) const { return s1 == s2; } + }; +} + +#endif //ADDRESS_H + diff --git a/src/mem/ruby/common/BigSet.cc b/src/mem/ruby/common/BigSet.cc new file mode 100644 index 000000000..e16284f15 --- /dev/null +++ b/src/mem/ruby/common/BigSet.cc @@ -0,0 +1,249 @@ + +/* + * 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. + */ + +#include "Set.hh" +#include "RubyConfig.hh" + +Set::Set() +{ + setSize(RubyConfig::numberOfProcessors()); +} + +Set::Set(int size) +{ + setSize(size); +} + +void Set::add(NodeID index) +{ + m_bits[index] = Present; +} + +void Set::addSet(const Set& set) +{ + assert(m_bits.size() == set.getSize()); + for (int i=0; i<m_bits.size(); i++) { + if(set.isElement(i)){ + add(i); + } + } +} + +void Set::addRandom() +{ + int rand = random(); + for (int i=0; i<m_bits.size(); i++) { + if(rand & 0x1 == 0) { // Look at the low order bit + add(i); + } + rand = (rand >> 1); // Shift the random number to look at the next bit + } +} + +void Set::remove(NodeID index) +{ + m_bits[index] = NotPresent; +} + +void Set::removeSet(const Set& set) +{ + assert(m_bits.size() == set.getSize()); + for (int i=0; i<m_bits.size(); i++) { + if(set.isElement(i)){ + remove(i); + } + } +} + +void Set::clear() +{ + for (int i=0; i<m_bits.size(); i++) { + m_bits[i] = NotPresent; + } +} + +void Set::broadcast() +{ + for (int i=0; i<m_bits.size(); i++) { + m_bits[i] = Present; + } +} + +int Set::count() const +{ + int counter = 0; + for (int i=0; i<m_bits.size(); i++) { + if (m_bits[i] == Present) { + counter++; + } + } + return counter; +} + +bool Set::isEqual(const Set& set) const +{ + assert(m_bits.size() == set.getSize()); + for (int i=0; i<m_bits.size(); i++) { + if (m_bits[i] != set.isElement(i)) { + return false; + } + } + return true; +} + +NodeID Set::smallestElement() const +{ + assert(count() > 0); + for (int i=0; i<m_bits.size(); i++) { + if (isElement(i)) { + return i; + } + } + ERROR_MSG("No smallest element of an empty set."); +} + +// Returns true iff all bits are set +bool Set::isBroadcast() const +{ + for (int i=0; i<m_bits.size(); i++) { + if (m_bits[i] == NotPresent) { + return false; + } + } + return true; +} + +// Returns true iff no bits are set +bool Set::isEmpty() const +{ + for (int i=0; i<m_bits.size(); i++) { + if (m_bits[i] == Present) { + return false; + } + } + return true; +} + +// returns the logical OR of "this" set and orSet +Set Set::OR(const Set& orSet) const +{ + Set result; + assert(m_bits.size() == orSet.getSize()); + result.setSize(m_bits.size()); + for (int i=0; i<m_bits.size(); i++) { + if(m_bits[i] == Present || orSet.isElement(i)){ + result.add(i); + }else{ + result.remove(i); + } + } + + return result; + +} + +// returns the logical AND of "this" set and andSet +Set Set::AND(const Set& andSet) const +{ + Set result; + assert(m_bits.size() == andSet.getSize()); + result.setSize(m_bits.size()); + for (int i=0; i<m_bits.size(); i++) { + if(m_bits[i] == Present && andSet.isElement(i)){ + result.add(i); + }else{ + result.remove(i); + } + } + return result; +} + +// Returns true if the intersection of the two sets is non-empty +bool Set::intersectionIsNotEmpty(const Set& other_set) const +{ + assert(m_bits.size() == other_set.getSize()); + for(int index=0; index < m_bits.size(); index++){ + if(other_set.isElement(index) && isElement(index)) { + return true; + } + } + return false; +} + +// Returns true if the intersection of the two sets is non-empty +bool Set::intersectionIsEmpty(const Set& other_set) const +{ + assert(m_bits.size() == other_set.getSize()); + for(int index=0; index < m_bits.size(); index++){ + if(other_set.isElement(index) && isElement(index)) { + return false; + } + } + return true; +} + +bool Set::isSuperset(const Set& test) const +{ + assert(m_bits.size() == test.getSize()); + for(int index=0; index < m_bits.size(); index++){ + if(test.isElement(index) && !isElement(index)) { + return false; + } + } + return true; +} + +bool Set::isElement(NodeID element) const +{ + return (m_bits[element] == Present); +} + +NodeID Set::elementAt(int index) const +{ + if (m_bits[index] == Present) { + return m_bits[index] == Present; + } else { + return 0; + } +} + +void Set::setSize(int size) +{ + m_bits.setSize(size); + clear(); +} + +void Set::print(ostream& out) const +{ + out << "[Set "; + for (int i=0; i<m_bits.size(); i++) { + out << (bool)m_bits[i] << " "; + } + out << "]"; +} diff --git a/src/mem/ruby/common/BigSet.hh b/src/mem/ruby/common/BigSet.hh new file mode 100644 index 000000000..4eae01681 --- /dev/null +++ b/src/mem/ruby/common/BigSet.hh @@ -0,0 +1,125 @@ + +/* + * 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. + */ + +// NOTE: Never include this file directly, this should only be +// included from Set.h + +#ifndef SET_H +#define SET_H + +#include "Global.hh" +#include "Vector.hh" +#include "NodeID.hh" +#include "RubyConfig.hh" + +enum PresenceBit {NotPresent, Present}; + +class Set { +public: + // Constructors + // creates and empty set + Set(); + Set (int size); + + // used during the replay mechanism + // Set(const char *str); + + // Set(const Set& obj); + // Set& operator=(const Set& obj); + + // Destructor + // ~Set(); + + // Public Methods + + void add(NodeID newElement); + void addSet(const Set& set); + void addRandom(); + void remove(NodeID newElement); + void removeSet(const Set& set); + void clear(); + void broadcast(); + int count() const; + bool isEqual(const Set& set) const; + + Set OR(const Set& orSet) const; // return the logical OR of this set and orSet + Set AND(const Set& andSet) const; // return the logical AND of this set and andSet + + // Returns true if the intersection of the two sets is non-empty + bool intersectionIsNotEmpty(const Set& other_set) const; + + // Returns true if the intersection of the two sets is empty + bool intersectionIsEmpty(const Set& other_set) const; + + bool isSuperset(const Set& test) const; + bool isSubset(const Set& test) const { return test.isSuperset(*this); } + bool isElement(NodeID element) const; + bool isBroadcast() const; + bool isEmpty() const; + + NodeID smallestElement() const; + + // int size() const; + void setSize (int size); + + // get element for a index + NodeID elementAt(int index) const; + int getSize() const { return m_bits.size(); } + + // DEPRECATED METHODS + void addToSet(NodeID newElement) { add(newElement); } // Deprecated + void removeFromSet(NodeID newElement) { remove(newElement); } // Deprecated + void clearSet() { clear(); } // Deprecated + void setBroadcast() { broadcast(); } // Deprecated + bool presentInSet(NodeID element) const { return isElement(element); } // Deprecated + + void print(ostream& out) const; +private: + // Private Methods + + // Data Members (m_ prefix) + Vector<uint8> m_bits; // This is an vector of uint8 to reduce the size of the set +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Set& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Set& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SET_H + diff --git a/src/mem/ruby/common/Consumer.hh b/src/mem/ruby/common/Consumer.hh new file mode 100644 index 000000000..bd51af7ba --- /dev/null +++ b/src/mem/ruby/common/Consumer.hh @@ -0,0 +1,89 @@ + +/* + * 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$ + * + * Description: This is the virtual base class of all classes that can + * be the targets of wakeup events. There is only two methods, + * wakeup() and print() and no data members. + * + */ + +#ifndef CONSUMER_H +#define CONSUMER_H + +#include "Global.hh" +#include "EventQueue.hh" + +class MessageBuffer; + +class Consumer { +public: + // Constructors + Consumer() { m_last_scheduled_wakeup = 0; m_last_wakeup = 0; m_out_link_vec.setSize(0); } + + // Destructor + 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; }} + virtual void wakeup() = 0; + virtual void print(ostream& out) const = 0; + const Time& getLastScheduledWakeup() const { return m_last_scheduled_wakeup; } + void setLastScheduledWakeup(const Time& time) { m_last_scheduled_wakeup = time; } + Vector< Vector<MessageBuffer*> > getOutBuffers() { return m_out_link_vec; } + +protected: + Vector< Vector<MessageBuffer*> > m_out_link_vec; + +private: + // Private Methods + + // Data Members (m_ prefix) + Time m_last_scheduled_wakeup; + Time m_last_wakeup; +}; + +// Output operator declaration +inline extern +ostream& operator<<(ostream& out, const Consumer& obj); + +// ******************* Definitions ******************* + +// Output operator definition +inline extern +ostream& operator<<(ostream& out, const Consumer& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //CONSUMER_H diff --git a/src/mem/ruby/common/DataBlock.cc b/src/mem/ruby/common/DataBlock.cc new file mode 100644 index 000000000..c4d6d7a33 --- /dev/null +++ b/src/mem/ruby/common/DataBlock.cc @@ -0,0 +1,91 @@ + +/* + * 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 "DataBlock.hh" + +DataBlock::DataBlock() +{ + 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]; + } else { + return 0; + } +} + +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 new file mode 100644 index 000000000..aae364078 --- /dev/null +++ b/src/mem/ruby/common/DataBlock.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. + */ + +#ifndef DATABLOCK_H +#define DATABLOCK_H + +#include "Global.hh" +#include "RubyConfig.hh" +#include "Vector.hh" + +class DataBlock { +public: + // Constructors + DataBlock(); + + // Destructor + ~DataBlock(); + + // Public Methods + void clear(); + uint8 getByte(int whichByte) const; + void setByte(int whichByte, uint8 data); + bool equal(const DataBlock& obj) const; + void print(ostream& out) const; + +private: + // Private Methods + + // Data Members (m_ prefix) + Vector<uint8> m_data; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const DataBlock& obj); + +bool operator==(const DataBlock& obj1, const DataBlock& obj2); + + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const DataBlock& obj) +{ + obj.print(out); + out << flush; + return out; +} + +extern inline +bool operator==(const DataBlock& obj1,const DataBlock& obj2) +{ + return (obj1.equal(obj2)); +} + +#endif //DATABLOCK_H diff --git a/src/mem/ruby/common/Debug.cc b/src/mem/ruby/common/Debug.cc new file mode 100644 index 000000000..f0319ceb8 --- /dev/null +++ b/src/mem/ruby/common/Debug.cc @@ -0,0 +1,369 @@ + +/* + * 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 <fstream> +#include <stdarg.h> + +#include "Global.hh" +#include "Debug.hh" +#include "EventQueue.hh" + +class Debug; +extern Debug* g_debug_ptr; +std::ostream * debug_cout_ptr; + +// component character list +const char DEFINE_COMP_CHAR[] = +{ +#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); +extern "C" void changeDebugFilter(int filter); + +void changeDebugVerbosity(VerbosityLevel vb) +{ + g_debug_ptr->setVerbosity(vb); +} + +void changeDebugFilter(int filter) +{ + g_debug_ptr->setFilter(filter); +} + +Debug::Debug( const char *filterString, const char *verboseString, + Time filterStartTime, const char *filename ) +{ + m_verbosityLevel = No_Verb; + clearFilter(); + debug_cout_ptr = &cout; + + m_starting_cycle = filterStartTime; + setFilterString( filterString ); + setVerbosityString( verboseString ); + setDebugOutputFile( filename ); +} + +Debug::~Debug() +{ +} + +void Debug::printVerbosity(ostream& out) const +{ + switch (getVerbosity()) { + case No_Verb: + out << "verbosity = No_Verb" << endl; + break; + case Low_Verb: + out << "verbosity = Low_Verb" << endl; + break; + case Med_Verb: + out << "verbosity = Med_Verb" << endl; + break; + case High_Verb: + out << "verbosity = High_Verb" << endl; + break; + default: + out << "verbosity = unknown" << endl; + } +} + +bool Debug::validDebug(int module, PriorityLevel priority) +{ + int local_module = (1 << module); + if(m_filter & local_module) { + if (g_eventQueue_ptr == NULL || + g_eventQueue_ptr->getTime() >= m_starting_cycle) { + switch(m_verbosityLevel) { + case No_Verb: + return false; + break; + case Low_Verb: + if(priority == HighPrio) { + return true; + }else{ + return false; + } + break; + case Med_Verb: + if(priority == HighPrio || priority == MedPrio ) { + return true; + }else{ + return false; + } + break; + case High_Verb: + return true; + break; + } + } + } + return false; +} + +void Debug::setDebugTime(Time t) +{ + m_starting_cycle = t; +} + +void Debug::setVerbosity(VerbosityLevel vb) +{ + m_verbosityLevel = vb; +} + +void Debug::setFilter(int filter) +{ + m_filter = filter; +} + +bool Debug::checkVerbosityString(const char *verb_str) +{ + if (verb_str == NULL) { + cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl; + return true; // error + } else if ( (string(verb_str) == "none") || + (string(verb_str) == "low") || + (string(verb_str) == "med") || + (string(verb_str) == "high") ) { + return false; + } + cerr << "Error: unrecognized verbosity (use none, low, med, high): NULL" << endl; + return true; // error +} + +bool Debug::setVerbosityString(const char *verb_str) +{ + bool check_fails = checkVerbosityString(verb_str); + if (check_fails) { + return true; // error + } + if (string(verb_str) == "none") { + setVerbosity(No_Verb); + } else if (string(verb_str) == "low") { + setVerbosity(Low_Verb); + } else if (string(verb_str) == "med") { + setVerbosity(Med_Verb); + } else if (string(verb_str) == "high") { + setVerbosity(High_Verb); + } else { + cerr << "Error: unrecognized verbosity (use none, low, med, high): " << verb_str << endl; + return true; // error + } + return false; // no error +} + +bool Debug::checkFilter(char ch) +{ + for (int i=0; i<NUMBER_OF_COMPS; i++) { + // Look at all components to find a character match + if (DEFINE_COMP_CHAR[i] == ch) { + // We found a match - return no error + return false; // no error + } + } + return true; // error +} + +bool Debug::checkFilterString(const char *filter_str) +{ + if (filter_str == NULL) { + cerr << "Error: unrecognized component filter: NULL" << endl; + return true; // error + } + + // check for default filter ("none") before reporting RUBY_DEBUG error + if ( (string(filter_str) == "none") ) { + return false; // no error + } + + if (RUBY_DEBUG == false) { + cerr << "Error: User specified set of debug components, but the RUBY_DEBUG compile-time flag is false." << endl; + cerr << "Solution: Re-compile with RUBY_DEBUG set to true." << endl; + return true; // error + } + + if ( (string(filter_str) == "all") ) { + return false; // no error + } + + // scan string checking each character + for (unsigned int i = 0; i < strlen(filter_str); i++) { + bool unrecognized = checkFilter( filter_str[i] ); + if (unrecognized == true) { + return true; // error + } + } + return false; // no error +} + +bool Debug::setFilterString(const char *filter_str) +{ + if (checkFilterString(filter_str)) { + return true; // error + } + + if (string(filter_str) == "all" ) { + allFilter(); + } else if (string(filter_str) == "none") { + clearFilter(); + } else { + // scan string adding to bit mask for each component which is present + for (unsigned int i = 0; i < strlen(filter_str); i++) { + bool error = addFilter( filter_str[i] ); + if (error) { + return true; // error + } + } + } + return false; // no error +} + +bool Debug::addFilter(char ch) +{ + for (int i=0; i<NUMBER_OF_COMPS; i++) { + // Look at all components to find a character match + if (DEFINE_COMP_CHAR[i] == ch) { + // We found a match - update the filter bit mask + cout << " Debug: Adding to filter: '" << ch << "' (" << DEFINE_COMP_DESCRIPTION[i] << ")" << endl; + m_filter |= (1 << i); + return false; // no error + } + } + + // We didn't find the character + cerr << "Error: unrecognized component filter: " << ch << endl; + usageInstructions(); + return true; // error +} + +void Debug::clearFilter() +{ + m_filter = 0; +} + +void Debug::allFilter() +{ + m_filter = ~0; +} + +void Debug::usageInstructions(void) +{ + cerr << "Debug components: " << endl; + for (int i=0; i<NUMBER_OF_COMPS; i++) { + cerr << " " << DEFINE_COMP_CHAR[i] << ": " << DEFINE_COMP_DESCRIPTION[i] << endl; + } +} + +void Debug::print(ostream& out) const +{ + out << "[Debug]" << endl; +} + +void Debug::setDebugOutputFile (const char * filename) +{ + if ( (filename == NULL) || + (!strcmp(filename, "none")) ) { + debug_cout_ptr = &cout; + return; + } + + if (m_fout.is_open() ) { + m_fout.close (); + } + m_fout.open (filename, std::ios::out); + if (! m_fout.is_open() ) { + cerr << "setDebugOutputFile: can't open file " << filename << endl; + } + else { + debug_cout_ptr = &m_fout; + } +} + +void Debug::closeDebugOutputFile () +{ + if (m_fout.is_open() ) { + m_fout.close (); + debug_cout_ptr = &cout; + } +} + +void Debug::debugMsg( const char *fmt, ... ) +{ + va_list args; + + // you could check validDebug() here before printing the message + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); +} + +/* +void DEBUG_OUT( const char* fmt, ...) { + if (RUBY_DEBUG) { + cout << "Debug: in fn " + << __PRETTY_FUNCTION__ + << " in " << __FILE__ << ":" + << __LINE__ << ": "; + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); + } +} + +void ERROR_OUT( const char* fmt, ... ) { + if (ERROR_MESSAGE_FLAG) { + cout << "error: in fn " + << __PRETTY_FUNCTION__ << " in " + << __FILE__ << ":" + << __LINE__ << ": "; + va_list args; + va_start(args, fmt); + vfprintf(stdout, fmt, args); + va_end(args); + } + assert(0); +} +*/ + diff --git a/src/mem/ruby/common/Debug.def b/src/mem/ruby/common/Debug.def new file mode 100644 index 000000000..23af06655 --- /dev/null +++ b/src/mem/ruby/common/Debug.def @@ -0,0 +1,17 @@ +DEFINE_COMP(SYSTEM_COMP, 's', "System") +DEFINE_COMP(NODE_COMP, 'N', "Node") +DEFINE_COMP(QUEUE_COMP, 'q', "Queue") +DEFINE_COMP(EVENTQUEUE_COMP, 'e', "Event Queue") +DEFINE_COMP(NETWORK_COMP, 'n', "Network") +DEFINE_COMP(SEQUENCER_COMP, 'S', "Sequencer") +DEFINE_COMP(TESTER_COMP, 't', "Tester") +DEFINE_COMP(GENERATED_COMP, 'g', "Generated") +DEFINE_COMP(SLICC_COMP, 'l', "SLICC") +DEFINE_COMP(NETWORKQUEUE_COMP, 'Q', "Network Queues") +DEFINE_COMP(TIME_COMP, 'T', "Time") +DEFINE_COMP(NETWORK_INTERNALS_COMP, 'i', "Network Internals") +DEFINE_COMP(STOREBUFFER_COMP, 'b', "Store Buffer") +DEFINE_COMP(CACHE_COMP, 'c', "Cache") +DEFINE_COMP(PREDICTOR_COMP, 'p', "Predictor") +DEFINE_COMP(ALLOCATOR_COMP, 'a', "Allocator") + diff --git a/src/mem/ruby/common/Debug.hh b/src/mem/ruby/common/Debug.hh new file mode 100644 index 000000000..afa10f57f --- /dev/null +++ b/src/mem/ruby/common/Debug.hh @@ -0,0 +1,291 @@ + +/* + * 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$ + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include <unistd.h> +#include <iostream> + +extern std::ostream * debug_cout_ptr; + +// component enumeration +enum DebugComponents +{ +#undef DEFINE_COMP +#define DEFINE_COMP(component, character, description) component, +#include "Debug.def" + NUMBER_OF_COMPS +}; + +enum PriorityLevel {HighPrio, MedPrio, LowPrio}; +enum VerbosityLevel {No_Verb, Low_Verb, Med_Verb, High_Verb}; + +class Debug { +public: + // Constructors + Debug( const char *filterString, const char *verboseString, + Time filterStartTime, const char *filename ); + + // Destructor + ~Debug(); + + // Public Methods + bool validDebug(int module, PriorityLevel priority); + void printVerbosity(ostream& out) const; + void setVerbosity(VerbosityLevel vb); + static bool checkVerbosityString(const char *verb_str); + bool setVerbosityString(const char *); + VerbosityLevel getVerbosity() const { return m_verbosityLevel; } + void setFilter(int); + static bool checkFilter( char); + static bool checkFilterString(const char *); + bool setFilterString(const char *); + void setDebugTime(Time); + Time getDebugTime() const { return m_starting_cycle; } + bool addFilter(char); + void clearFilter(); + void allFilter(); + void print(ostream& out) const; + /* old school debugging "vararg": sends messages to screen and log */ + void debugMsg( const char *fmt, ... ); + + void setDebugOutputFile (const char * filename); + void closeDebugOutputFile (); + static void usageInstructions(void); + +private: + // Private Methods + + // Private copy constructor and assignment operator + Debug(const Debug& obj); + Debug& operator=(const Debug& obj); + + // Data Members (m_ prefix) + VerbosityLevel m_verbosityLevel; + int m_filter; + Time m_starting_cycle; + + std::fstream m_fout; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Debug& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Debug& obj) +{ + obj.print(out); + out << flush; + return out; +} + +const bool ERROR_MESSAGE_FLAG = true; +const bool WARNING_MESSAGE_FLAG = true; + +#ifdef RUBY_NO_ASSERT +const bool ASSERT_FLAG = false; +#else +const bool ASSERT_FLAG = true; +#endif + +#undef assert +#define assert(EXPR) ASSERT(EXPR) +#undef ASSERT +#define ASSERT(EXPR)\ +{\ + if (ASSERT_FLAG) {\ + if (!(EXPR)) {\ + cerr << "failed assertion '"\ + << #EXPR << "' at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + (* debug_cout_ptr) << "failed assertion '"\ + << #EXPR << "' at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + 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;\ + cerr << "PID: " << getpid();\ + cerr << endl << flush; \ + char c; \ + cin.get(c); \ + }\ + abort();\ + }\ + }\ +} + +#define BREAK(X)\ +{\ + cerr << "breakpoint '"\ + << #X << "' reached at fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << endl << flush;\ + if(isatty(STDIN_FILENO)) {\ + cerr << "press enter to continue" << endl;\ + cerr << "PID: " << getpid();\ + cerr << endl << flush; \ + char c; \ + cin.get(c); \ + }\ +} + +#define ERROR_MSG(MESSAGE)\ +{\ + if (ERROR_MESSAGE_FLAG) {\ + cerr << "Fatal Error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + (* debug_cout_ptr) << "Fatal Error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + abort();\ + }\ +} + +#define WARN_MSG(MESSAGE)\ +{\ + if (WARNING_MESSAGE_FLAG) {\ + cerr << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + (* debug_cout_ptr) << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + }\ +} + +#define WARN_EXPR(EXPR)\ +{\ + if (WARNING_MESSAGE_FLAG) {\ + cerr << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + (* debug_cout_ptr) << "Warning: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + }\ +} + +#define DEBUG_MSG(module, priority, MESSAGE)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "\ + << (MESSAGE) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_EXPR(module, priority, EXPR)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "\ + << #EXPR << " is "\ + << (EXPR) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_NEWLINE(module, priority)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(module, priority)) {\ + (* debug_cout_ptr) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_SLICC(priority, LINE, MESSAGE)\ +{\ + if (RUBY_DEBUG) {\ + if (g_debug_ptr->validDebug(SLICC_COMP, priority)) {\ + (* debug_cout_ptr) << (LINE) << (MESSAGE) << endl << flush;\ + }\ + }\ +} + +#define DEBUG_OUT( rest... ) \ +{\ + if (RUBY_DEBUG) {\ + cout << "Debug: in fn "\ + << __PRETTY_FUNCTION__\ + << " in " << __FILE__ << ":"\ + << __LINE__ << ": "; \ + g_debug_ptr->debugMsg(rest); \ + }\ +} + +#define ERROR_OUT( rest... ) \ +{\ + if (ERROR_MESSAGE_FLAG) {\ + cout << "error: in fn "\ + << __PRETTY_FUNCTION__ << " in "\ + << __FILE__ << ":"\ + << __LINE__ << ": ";\ + g_debug_ptr->debugMsg(rest); \ + }\ +} + +#endif //DEBUG_H + diff --git a/src/mem/ruby/common/Driver.cc b/src/mem/ruby/common/Driver.cc new file mode 100644 index 000000000..019ac6403 --- /dev/null +++ b/src/mem/ruby/common/Driver.cc @@ -0,0 +1,39 @@ + +/* + * 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. + */ + +#include "Driver.hh" + +Driver::Driver() +{ +} + +// still need to be defined for subclasses +Driver::~Driver() +{ +} diff --git a/src/mem/ruby/common/Driver.hh b/src/mem/ruby/common/Driver.hh new file mode 100644 index 000000000..911cb742b --- /dev/null +++ b/src/mem/ruby/common/Driver.hh @@ -0,0 +1,98 @@ + +/* + * 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. + */ + +#ifndef DRIVER_H +#define DRIVER_H + +#include "Global.hh" +#include "Consumer.hh" +#include "NodeID.hh" +#include "CacheRequestType.hh" + +class System; +class SubBlock; +class Address; +class MachineID; +class SimicsHypervisor; + +class Driver { +public: + // Constructors + Driver(); + + // Destructor + virtual ~Driver() = 0; + + // Public Methods + virtual void get_network_config() {} + 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 SimicsHypervisor * getHypervisor() { return NULL; } + virtual void notifySendNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id) { assert(0); }; //Called by Sequencer + virtual void notifyReceiveNack( int procID, const Address & addr, uint64 remote_timestamp, const MachineID & remote_id) { assert(0); }; //Called by Sequencer + virtual void notifyReceiveNackFinal( int procID, const Address & addr) { assert(0); }; // Called by Sequencer + virtual void notifyTrapStart( int procID, const Address & handlerPC, int threadID, int smtThread ) { assert(0); } //called by Sequencer + virtual void notifyTrapComplete( int procID, const Address & newPC, int smtThread ) {assert(0); } // called by Sequencer + virtual int getOpalTransactionLevel(int procID, int thread) const { + cout << "Driver.hh getOpalTransactionLevel() " << endl; + return 0; } //called by Sequencer + virtual void addThreadDependency(int procID, int requestor_thread, int conflict_thread) const { assert(0);} + virtual uint64 getOpalTime(int procID) const{ return 0; } //called by Sequencer + virtual uint64 getOpalTimestamp(int procID, int thread) const{ + cout << "Driver.hh getOpalTimestamp " << endl; + return 0; } // called by Sequencer + 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; + virtual void clearStats() = 0; + + 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; } + + virtual void writePhysicalMemory( int procID, physical_address_t address, + integer_t value, int len ){ ASSERT(0); } + +protected: + // accessible by subclasses + +private: + // inaccessible by subclasses + +}; + +#endif //DRIVER_H diff --git a/src/mem/ruby/common/Global.cc b/src/mem/ruby/common/Global.cc new file mode 100644 index 000000000..e60cd4fd3 --- /dev/null +++ b/src/mem/ruby/common/Global.cc @@ -0,0 +1,35 @@ + +/* + * 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. + */ + +#include "Global.hh" + +EventQueue* g_eventQueue_ptr = NULL; +System* g_system_ptr = NULL; +Debug* g_debug_ptr = NULL; + diff --git a/src/mem/ruby/common/Global.hh b/src/mem/ruby/common/Global.hh new file mode 100644 index 000000000..eaec05d46 --- /dev/null +++ b/src/mem/ruby/common/Global.hh @@ -0,0 +1,110 @@ + +/* + * 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$ + * + * */ + +#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 +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // " +#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // " +#define L2_CACHE_VARIABLE m_L1Cache_cacheMemory_vec +#else +const bool TWO_LEVEL_CACHE = true; +#ifdef IS_CMP +#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version] +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version] +#define L2_CACHE_MEMBER_VARIABLE m_L2Cache_L2cacheMemory_vec[m_version] +#define L2_CACHE_VARIABLE m_L2Cache_L2cacheMemory_vec +#else // not IS_CMP +#define L1I_CACHE_MEMBER_VARIABLE m_L1Cache_L1IcacheMemory_vec[m_version] // currently all protocols require L1s == nodes +#define L1D_CACHE_MEMBER_VARIABLE m_L1Cache_L1DcacheMemory_vec[m_version] // " +// #define L2_CACHE_MEMBER_VARIABLE m_L1Cache_L2cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes +#define L2_CACHE_MEMBER_VARIABLE m_L1Cache_cacheMemory_vec[m_version] // old exclusive caches don't support L2s != nodes +#define L2_CACHE_VARIABLE m_L1Cache_L2cacheMemory_vec +#endif // IS_CMP +#endif //SINGLE_LEVEL_CACHE + +#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 "std-includes.hh" +#include "Debug.hh" + +// simple type declarations +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; + +class EventQueue; +extern EventQueue* g_eventQueue_ptr; + +class System; +extern System* g_system_ptr; + +class Debug; +extern Debug* g_debug_ptr; + +// FIXME: this is required by the contructor of Directory_Entry.h. It can't go +// into slicc_util.h because it opens a can of ugly worms +extern inline int max_tokens() +{ + return 1024; +} + + +#endif //GLOBAL_H + diff --git a/src/mem/ruby/common/Histogram.cc b/src/mem/ruby/common/Histogram.cc new file mode 100644 index 000000000..9c5e8e623 --- /dev/null +++ b/src/mem/ruby/common/Histogram.cc @@ -0,0 +1,185 @@ + +/* + * 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 "Histogram.hh" + +Histogram::Histogram(int binsize, int bins) +{ + m_binsize = binsize; + m_bins = bins; + clear(); +} + +Histogram::~Histogram() +{ +} + +void Histogram::clear(int binsize, int bins) +{ + m_binsize = binsize; + clear(bins); +} + +void Histogram::clear(int bins) +{ + m_bins = bins; + m_largest_bin = 0; + m_max = 0; + m_data.setSize(m_bins); + for (int i = 0; i < m_bins; i++) { + m_data[i] = 0; + } + m_count = 0; + m_max = 0; + + m_sumSamples = 0; + m_sumSquaredSamples = 0; +} + + +void Histogram::add(int64 value) +{ + assert(value >= 0); + m_max = max(m_max, value); + m_count++; + + m_sumSamples += value; + m_sumSquaredSamples += (value*value); + + int index; + if (m_binsize == -1) { + // This is a log base 2 histogram + if (value == 0) { + index = 0; + } else { + index = int(log(double(value))/log(2.0))+1; + if (index >= m_data.size()) { + index = m_data.size()-1; + } + } + } else { + // This is a linear histogram + while (m_max >= (m_bins * m_binsize)) { + for (int i = 0; i < m_bins/2; i++) { + m_data[i] = m_data[i*2] + m_data[i*2 + 1]; + } + for (int i = m_bins/2; i < m_bins; i++) { + m_data[i] = 0; + } + m_binsize *= 2; + } + index = value/m_binsize; + } + assert(index >= 0); + m_data[index]++; + m_largest_bin = max(m_largest_bin, index); +} + +void Histogram::add(const Histogram& hist) +{ + assert(hist.getBins() == m_bins); + assert(hist.getBinSize() == -1); // assume log histogram + assert(m_binsize == -1); + + for (int j = 0; j < hist.getData(0); j++) { + add(0); + } + + for (int i = 1; i < m_bins; i++) { + for (int j = 0; j < hist.getData(i); j++) { + add(1<<(i-1)); // account for the + 1 index + } + } + +} + +// Computation of standard deviation of samples a1, a2, ... aN +// variance = [SUM {ai^2} - (SUM {ai})^2/N]/(N-1) +// std deviation equals square root of variance +double Histogram::getStandardDeviation() const +{ + double variance; + if(m_count > 1){ + variance = (double)(m_sumSquaredSamples - m_sumSamples*m_sumSamples/m_count)/(m_count - 1); + } else { + return 0; + } + return sqrt(variance); +} + +void Histogram::print(ostream& out) const +{ + printWithMultiplier(out, 1.0); +} + +void Histogram::printPercent(ostream& out) const +{ + if (m_count == 0) { + printWithMultiplier(out, 0.0); + } else { + printWithMultiplier(out, 100.0/double(m_count)); + } +} + +void Histogram::printWithMultiplier(ostream& out, double multiplier) const +{ + if (m_binsize == -1) { + out << "[binsize: log2 "; + } else { + out << "[binsize: " << m_binsize << " "; + } + out << "max: " << m_max << " "; + out << "count: " << m_count << " "; + // out << "total: " << m_sumSamples << " "; + if (m_count == 0) { + out << "average: NaN |"; + out << "standard deviation: NaN |"; + } else { + out << "average: " << setw(5) << ((double) m_sumSamples)/m_count << " | "; + out << "standard deviation: " << getStandardDeviation() << " |"; + } + for (int i = 0; i < m_bins && i <= m_largest_bin; i++) { + if (multiplier == 1.0) { + out << " " << m_data[i]; + } else { + out << " " << double(m_data[i]) * multiplier; + } + } + out << " ]"; +} + +bool node_less_then_eq(const Histogram* n1, const Histogram* n2) +{ + return (n1->size() > n2->size()); +} diff --git a/src/mem/ruby/common/Histogram.hh b/src/mem/ruby/common/Histogram.hh new file mode 100644 index 000000000..e48efc35f --- /dev/null +++ b/src/mem/ruby/common/Histogram.hh @@ -0,0 +1,104 @@ + +/* + * 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$ + * + * Description: The histogram class implements a simple histogram + * + */ + +#ifndef HISTOGRAM_H +#define HISTOGRAM_H + +#include "Global.hh" +#include "Vector.hh" + +class Histogram { +public: + // Constructors + Histogram(int binsize = 1, int bins = 50); + + // Destructor + ~Histogram(); + + // Public Methods + + void add(int64 value); + void add(const Histogram& hist); + void clear() { clear(m_bins); } + void clear(int bins); + void clear(int binsize, int bins); + int64 size() const { return m_count; } + int getBins() const { return m_bins; } + int getBinSize() const { return m_binsize; } + int64 getTotal() const { return m_sumSamples; } + int64 getData(int index) const { return m_data[index]; } + + void printWithMultiplier(ostream& out, double multiplier) const; + void printPercent(ostream& out) const; + void print(ostream& out) const; +private: + // Private Methods + + // Private copy constructor and assignment operator + // Histogram(const Histogram& obj); + // Histogram& operator=(const Histogram& obj); + + // Data Members (m_ prefix) + Vector<int64> m_data; + int64 m_max; // the maximum value seen so far + int64 m_count; // the number of elements added + int m_binsize; // the size of each bucket + int m_bins; // the number of buckets + int m_largest_bin; // the largest bin used + + int64 m_sumSamples; // the sum of all samples + int64 m_sumSquaredSamples; // the sum of the square of all samples + + double getStandardDeviation() const; +}; + +bool node_less_then_eq(const Histogram* n1, const Histogram* n2); + +// Output operator declaration +ostream& operator<<(ostream& out, const Histogram& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Histogram& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //HISTOGRAM_H diff --git a/src/mem/ruby/common/Message.cc b/src/mem/ruby/common/Message.cc new file mode 100644 index 000000000..baad8ac9b --- /dev/null +++ b/src/mem/ruby/common/Message.cc @@ -0,0 +1,34 @@ + +/* + * 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 "Message.hh" diff --git a/src/mem/ruby/common/NetDest.cc b/src/mem/ruby/common/NetDest.cc new file mode 100644 index 000000000..79a6078e9 --- /dev/null +++ b/src/mem/ruby/common/NetDest.cc @@ -0,0 +1,259 @@ + +/* + * 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. + */ + +/* + * NetDest.C + * + * Description: See NetDest.h + * + * $Id$ + * + */ + +#include "NetDest.hh" +#include "RubyConfig.hh" +#include "Protocol.hh" + +NetDest::NetDest() +{ + setSize(); +} + +void NetDest::add(MachineID newElement) +{ + m_bits[vecIndex(newElement)].add(bitIndex(newElement.num)); +} + +void NetDest::addNetDest(const NetDest& netDest) +{ + assert(m_bits.size() == netDest.getSize()); + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].addSet(netDest.m_bits[i]); + } +} + +void NetDest::addRandom() +{ + int i = random()%m_bits.size(); + m_bits[i].addRandom(); +} + +void NetDest::setNetDest(MachineType machine, const Set& set) +{ + // assure that there is only one set of destinations for this machine + assert(MachineType_base_level((MachineType)(machine+1)) - MachineType_base_level(machine) == 1); + m_bits[MachineType_base_level(machine)] = set; +} + +void NetDest::remove(MachineID oldElement) +{ + m_bits[vecIndex(oldElement)].remove(bitIndex(oldElement.num)); +} + +void NetDest::removeNetDest(const NetDest& netDest) +{ + assert(m_bits.size() == netDest.getSize()); + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].removeSet(netDest.m_bits[i]); + + } +} + +void NetDest::clear() +{ + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].clear(); + } +} + +void NetDest::broadcast() +{ + for (MachineType machine = MachineType_FIRST; machine < MachineType_NUM; ++machine) { + broadcast(machine); + } +} + +void NetDest::broadcast(MachineType machineType) { + + for (int i = 0; i < MachineType_base_count(machineType); i++) { + MachineID mach = {machineType, i}; + add(mach); + } +} + +//For Princeton Network +Vector<NodeID> NetDest::getAllDest() { + Vector<NodeID> dest; + dest.clear(); + for (int i=0; i<m_bits.size(); i++) { + for (int j=0; j<m_bits[i].getSize(); j++) { + if (m_bits[i].isElement(j)) { + dest.insertAtBottom((NodeID) (MachineType_base_number((MachineType) i) + j)); + } + } + } + return dest; +} + +int NetDest::count() const +{ + int counter = 0; + for (int i=0; i<m_bits.size(); i++) { + counter += m_bits[i].count(); + } + return counter; +} + +NodeID NetDest::elementAt(MachineID index) { + return m_bits[vecIndex(index)].elementAt(bitIndex(index.num)); +} + +NodeID NetDest::smallestElement() const +{ + assert(count() > 0); + for (int i=0; i<m_bits.size(); i++) { + for (int j=0; j<m_bits[i].getSize(); j++) { + if (m_bits[i].isElement(j)) { + return j; + } + } + } + ERROR_MSG("No smallest element of an empty set."); +} + +MachineID NetDest::smallestElement(MachineType machine) const +{ + for (int j = 0; j < m_bits[MachineType_base_level(machine)].getSize(); j++) { + if (m_bits[MachineType_base_level(machine)].isElement(j)) { + MachineID mach = {machine, j}; + return mach; + } + } + + ERROR_MSG("No smallest element of given MachineType."); +} + + +// Returns true iff all bits are set +bool NetDest::isBroadcast() const +{ + for (int i=0; i<m_bits.size(); i++) { + if (!m_bits[i].isBroadcast()) { + return false; + } + } + return true; +} + +// Returns true iff no bits are set +bool NetDest::isEmpty() const +{ + for (int i=0; i<m_bits.size(); i++) { + if (!m_bits[i].isEmpty()) { + return false; + } + } + return true; +} + +// returns the logical OR of "this" set and orNetDest +NetDest NetDest::OR(const NetDest& orNetDest) const +{ + assert(m_bits.size() == orNetDest.getSize()); + NetDest result; + for (int i=0; i<m_bits.size(); i++) { + result.m_bits[i] = m_bits[i].OR(orNetDest.m_bits[i]); + } + return result; +} + + +// returns the logical AND of "this" set and andNetDest +NetDest NetDest::AND(const NetDest& andNetDest) const +{ + assert(m_bits.size() == andNetDest.getSize()); + NetDest result; + for (int i=0; i<m_bits.size(); i++) { + result.m_bits[i] = m_bits[i].AND(andNetDest.m_bits[i]); + } + return result; +} + +// Returns true if the intersection of the two sets is non-empty +bool NetDest::intersectionIsNotEmpty(const NetDest& other_netDest) const +{ + assert(m_bits.size() == other_netDest.getSize()); + for (int i=0; i<m_bits.size(); i++) { + if (m_bits[i].intersectionIsNotEmpty(other_netDest.m_bits[i])) { + return true; + } + } + return false; +} + +bool NetDest::isSuperset(const NetDest& test) const +{ + assert(m_bits.size() == test.getSize()); + + for (int i=0; i<m_bits.size(); i++) { + if (!m_bits[i].isSuperset(test.m_bits[i])) { + return false; + } + } + return true; +} + +bool NetDest::isElement(MachineID element) const +{ + return ((m_bits[vecIndex(element)])).isElement(bitIndex(element.num)); +} + +void NetDest::setSize() +{ + m_bits.setSize(MachineType_base_level(MachineType_NUM)); + assert(m_bits.size() == MachineType_NUM); + + for (int i = 0; i < m_bits.size(); i++) { + m_bits[i].setSize(MachineType_base_count((MachineType)i)); + } +} + +void NetDest::print(ostream& out) const +{ + out << "[NetDest (" << m_bits.size() << ") "; + + for (int i=0; i<m_bits.size(); i++) { + for (int j=0; j<m_bits[i].getSize(); j++) { + out << (bool) m_bits[i].isElement(j) << " "; + } + out << " - "; + } + out << "]"; +} + diff --git a/src/mem/ruby/common/NetDest.hh b/src/mem/ruby/common/NetDest.hh new file mode 100644 index 000000000..04f7871f6 --- /dev/null +++ b/src/mem/ruby/common/NetDest.hh @@ -0,0 +1,145 @@ + +/* + * 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. + */ + +/* + * Set.h + * + * Description: + * + * $Id$ + * + */ + +// NetDest specifies the network destination of a NetworkMessage +// This is backward compatible with the Set class that was previously +// used to specify network destinations. +// NetDest supports both node networks and component networks + +#ifndef NETDEST_H +#define NETDEST_H + +#include "Global.hh" +#include "Vector.hh" +#include "NodeID.hh" +#include "MachineID.hh" +#include "RubyConfig.hh" +#include "Set.hh" +#include "MachineType.hh" + +class Set; + +class NetDest { +public: + // Constructors + // creates and empty set + NetDest(); + explicit NetDest(int bit_size); + + NetDest& operator=(const Set& obj); + + // Destructor + // ~NetDest(); + + // Public Methods + void add(MachineID newElement); + void addNetDest(const NetDest& netDest); + void addRandom(); + void setNetDest(MachineType machine, const Set& set); + void remove(MachineID oldElement); + void removeNetDest(const NetDest& netDest); + void clear(); + void broadcast(); + void broadcast(MachineType machine); + int count() const; + bool isEqual(const NetDest& netDest); + + NetDest OR(const NetDest& orNetDest) const; // return the logical OR of this netDest and orNetDest + NetDest AND(const NetDest& andNetDest) const; // return the logical AND of this netDest and andNetDest + + // Returns true if the intersection of the two netDests is non-empty + bool intersectionIsNotEmpty(const NetDest& other_netDest) const; + + // Returns true if the intersection of the two netDests is empty + bool intersectionIsEmpty(const NetDest& other_netDest) const; + + bool isSuperset(const NetDest& test) const; + bool isSubset(const NetDest& test) const { return test.isSuperset(*this); } + bool isElement(MachineID element) const; + bool isBroadcast() const; + bool isEmpty() const; + + //For Princeton Network + Vector<NodeID> getAllDest(); + + NodeID smallestElement() const; + MachineID smallestElement(MachineType machine) const; + + void setSize(); + int getSize() const { return m_bits.size(); } + + // get element for a index + NodeID elementAt(MachineID index); + + void print(ostream& out) const; + +private: + + // Private Methods + // returns a value >= MachineType_base_level("this machine") and < MachineType_base_level("next highest machine") + int vecIndex(MachineID m) const { + int vec_index = MachineType_base_level(m.type); + assert(vec_index < m_bits.size()); + return vec_index; + } + + NodeID bitIndex(NodeID index) const { + return index; + } + + // Data Members (m_ prefix) + Vector < Set > m_bits; // a Vector of bit vectors - i.e. Sets + +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const NetDest& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const NetDest& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //NETDEST_H + diff --git a/src/mem/ruby/common/OptBigSet.cc b/src/mem/ruby/common/OptBigSet.cc new file mode 100644 index 000000000..51214e936 --- /dev/null +++ b/src/mem/ruby/common/OptBigSet.cc @@ -0,0 +1,576 @@ + +/* + * 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. + */ + +/* + * Set.C + * + * Description: See Set.h + * + * $Id: BigSet.C 1.9 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $ + * + */ + +// modified (rewritten) 05/20/05 by Dan Gibson to accomimdate FASTER >32 bit +// set sizes + +#include "Set.hh" +#include "RubyConfig.hh" + +#if __amd64__ || __LP64__ +#define __64BITS__ +#else +#define __32BITS__ +#endif + +Set::Set() +{ + m_p_nArray = NULL; + setSize(RubyConfig::numberOfProcessors()); +} + +// copy constructor +Set::Set(const Set& obj) { + m_p_nArray = NULL; + setSize(obj.m_nSize); + + // copy from the host to this array + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] = obj.m_p_nArray[i]; + } + +} + +Set::Set(int size) +{ + m_p_nArray = NULL; + assert(size>0); + setSize(size); +} + +Set::~Set() { + if( (m_p_nArray != (&m_p_nArray_Static[0])) && (m_p_nArray != NULL)) + delete [] m_p_nArray; + m_p_nArray = NULL; +} + + +// /* +// * This function should set the bit corresponding to index +// * to 1. +// */ + +// void Set::add(NodeID index) +// { +// assert(index<m_nSize && index >= 0); + +// #ifdef __32BITS__ +// m_p_nArray[index>>5] |= (1 << (index & 0x01F)); +// #else +// m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F)); +// #endif // __32BITS__ + +// } + +/* + * This function should set all the bits in the current set + * that are already set in the parameter set + */ +void Set::addSet(const Set& set) +{ + assert(getSize()==set.getSize()); + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] |= set.m_p_nArray[i]; + } + +} + +/* + * This function should randomly assign 1 to the bits in the set-- + * it should not clear the bits bits first, though? + */ +void Set::addRandom() +{ + + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] |= random() ^ (random() << 4); // this ensures that all 32 bits are subject to random effects, + // as RAND_MAX typically = 0x7FFFFFFF + } + + // now just ensure that no bits over the maximum size were set +#ifdef __32BITS__ + long mask = 0x7FFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 32, so the uppermost 32 - m_nSize%32 bits should be + // cleared + + if((m_nSize % 32) != 0) { + for(int j=0; j<32-(m_nSize&0x01F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#else + long mask = 0x7FFFFFFFFFFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be + // cleared + + if((m_nSize % 64) != 0) { + for(int j=0; j<64-(m_nSize&0x03F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#endif // __32BITS__ + +} + +// /* +// * This function unsets the bit associated with index +// */ +// void Set::remove(NodeID index) +// { +// assert(index<m_nSize && index>=0); + +// #ifdef __32BITS__ +// m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); +// #else +// m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F)); +// #endif // __32BITS__ + +// } + + +/* + * This function clears bits that are =1 in the parameter set + */ +void Set::removeSet(const Set& set) +{ + + assert(m_nSize==set.m_nSize); + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] &= ~(set.m_p_nArray[i]); + } + +} + +// /* +// * This function clears all bits in the set +// */ +// void Set::clear() +// { +// for(int i=0; i<m_nArrayLen; i++) { +// m_p_nArray[i] = 0; +// } +// } + +/* + * this function sets all bits in the set + */ +void Set::broadcast() +{ + + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] = -1; // note that -1 corresponds to all 1's in 2's comp. + } + + // now just ensure that no bits over the maximum size were set +#ifdef __32BITS__ + long mask = 0x7FFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 32, so the uppermost 32 - m_nSize%32 bits should be + // cleared + + if((m_nSize % 32) != 0) { + for(int j=0; j<32-(m_nSize&0x01F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#else + long mask = 0x7FFFFFFFFFFFFFFF; + + // the number of populated spaces in the higest-order array slot is: + // m_nSize % 64, so the uppermost 64 - m_nSize%64 bits should be + // cleared + + if((m_nSize % 64) != 0) { + for(int j=0; j<64-(m_nSize&0x03F); j++) { + m_p_nArray[m_nArrayLen-1] &= mask; + mask = mask >> 1; + } + } +#endif // __32BITS__ + +} + +/* + * This function returns the population count of 1's in the set + */ +int Set::count() const +{ + int counter = 0; + long mask; + for( int i=0; i<m_nArrayLen; i++) { + mask = (long) 0x01; + +#ifdef __32BITS__ + for( int j=0; j<32; j++) { + if(m_p_nArray[i] & mask) counter++; + mask = mask << 1; + } + +#else + + for( int j=0; j<64; j++) { // FIXME - significant performance loss when array population << 64 + if((m_p_nArray[i] & mask) != 0) { + counter++; + } + mask = mask << 1; + } + +#endif // __32BITS__ + + } + + return counter; +} + +/* + * This function checks for set equality + */ + +bool Set::isEqual(const Set& set) const +{ + assert(m_nSize==set.m_nSize); + + for(int i=0;i<m_nArrayLen;i++) { + if(m_p_nArray[i] != set.m_p_nArray[i]) { + return false; + } + } + + return true; +} + +/* + * This function returns the NodeID (int) of the + * least set bit + */ +NodeID Set::smallestElement() const +{ + assert(count() > 0); + long x; + for( int i=0; i<m_nArrayLen; i++) { + if(m_p_nArray[i]!=0) { + // the least-set bit must be in here + x = m_p_nArray[i]; + +#ifdef __32BITS__ + for( int j=0; j<32; j++) { + if(x & 0x00000001) { + return 32*i+j; + } + + x = x >> 1; + } +#else + for( int j=0; j<64; j++) { + if(x & 0x0000000000000001) { + return 64*i+j; + } + + x = x >> 1; + } +#endif // __32BITS__ + + ERROR_MSG("No smallest element of an empty set."); + } + } + + ERROR_MSG("No smallest element of an empty set."); + + return 0; +} + +/* + * this function returns true iff all bits are set + */ +bool Set::isBroadcast() const +{ + // check the fully-loaded words by equal to 0xffffffff + // only the last word may not be fully loaded, it is not + // fully loaded iff m_nSize % 32 or 64 !=0 => fully loaded iff + // m_nSize % 32 or 64 == 0 + +#ifdef __32BITS__ + for(int i=0; i< (((m_nSize % 32)==0) ? m_nArrayLen : m_nArrayLen-1); i++) { + if(m_p_nArray[i]!=-1) { + return false; + } + } + + // now check the last word, which may not be fully loaded + long mask = 1; + for(int j=0; j< (m_nSize % 32); j++) { + if((mask & m_p_nArray[m_nArrayLen-1])==0) { + return false; + } + mask = mask << 1; + } +#else + for(int i=0; i< (((m_nSize % 64)==0) ? m_nArrayLen : m_nArrayLen-1); i++) { + if(m_p_nArray[i]!=-1) { + return false; + } + } + + // now check the last word, which may not be fully loaded + long mask = 1; + for(int j=0; j< (m_nSize % 64); j++) { + if((mask & m_p_nArray[m_nArrayLen-1])==0) { + return false; + } + mask = mask << 1; + } + +#endif // __32BITS__ + + return true; +} + +/* + * this function returns true iff no bits are set + */ +bool Set::isEmpty() const +{ + + // here we can simply check if all = 0, since we ensure + // that "extra slots" are all zero + for(int i=0; i< m_nArrayLen ; i++) { + if(m_p_nArray[i]!=0) { + return false; + } + } + + return true; +} + +// returns the logical OR of "this" set and orSet +Set Set::OR(const Set& orSet) const +{ + Set result(m_nSize); + assert(m_nSize == orSet.m_nSize); + for(int i=0; i< m_nArrayLen; i++) { + result.m_p_nArray[i] = m_p_nArray[i] | orSet.m_p_nArray[i]; + } + + return result; + +} + +// returns the logical AND of "this" set and andSet +Set Set::AND(const Set& andSet) const +{ + Set result(m_nSize); + assert(m_nSize == andSet.m_nSize); + + for(int i=0; i< m_nArrayLen; i++) { + result.m_p_nArray[i] = m_p_nArray[i] & andSet.m_p_nArray[i]; + } + + return result; +} + +// // Returns true if the intersection of the two sets is non-empty +// bool Set::intersectionIsNotEmpty(const Set& other_set) const +// { +// assert(m_nSize == other_set.m_nSize); +// for(int i=0; i< m_nArrayLen; i++) { +// if(m_p_nArray[i] & other_set.m_p_nArray[i]) { +// return true; +// } +// } + +// return false; + +// } + +// // Returns true if the intersection of the two sets is empty +// bool Set::intersectionIsEmpty(const Set& other_set) const +// { +// assert(m_nSize == other_set.m_nSize); +// for(int i=0; i< m_nArrayLen; i++) { +// if(m_p_nArray[i] & other_set.m_p_nArray[i]) { +// return false; +// } +// } + +// return true; + +// } + +/* + * Returns false if a bit is set in the parameter set that is + * NOT set in this set + */ +bool Set::isSuperset(const Set& test) const +{ + assert(m_nSize == test.m_nSize); + + for(int i=0;i<m_nArrayLen;i++) { + if(((test.m_p_nArray[i] & m_p_nArray[i]) | ~test.m_p_nArray[i]) != -1) { + return false; + } + } + + return true; +} + +// /* +// * Returns true iff this bit is set +// */ +// bool Set::isElement(NodeID element) const +// { +// bool result; + +// #ifdef __32BITS__ +// result = ((m_p_nArray[element>>5] & (0x00000001 << (element & 0x01F)))!=0); +// #else +// result = ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0); +// #endif // __32BITS__ + +// return result; +// } + +/* + * "Supposed" to return the node id of the (n+1)th set + * bit, IE n=0 => returns nodeid of first set bit, BUT + * since BigSet.C behaves strangely, this implementation + * will behave strangely just for reverse compatability. + * + * Was originally implemented for the flight data recorder + * FDR + */ + +// NodeID Set::elementAt(int n) const +// { +// if(isElement(n)) return (NodeID) true; +// else return 0; + +// /* +// int match = -1; +// for(int i=0;i<m_nSize;i++) { +// if(isElement(i)) match++; +// if(match==n) { +// return i; +// } +// } + +// return -1; +// */ +// } + +void Set::setSize(int size) +{ + m_nSize = size; + +#ifdef __32BITS__ + m_nArrayLen = m_nSize/32 + ((m_nSize%32==0) ? 0 : 1 ); +#else + m_nArrayLen = m_nSize/64 + ((m_nSize%64==0) ? 0 : 1 ); +#endif // __32BITS__ + + // decide whether to use dynamic or static alloction + if(m_nArrayLen<=NUMBER_WORDS_PER_SET) { // constant defined in RubyConfig.h + // 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) + + // if switching from dyanamic to static allocation (which + // is probably rare, but why not be complete?), must delete + // the dynamically allocated space + if((m_p_nArray != NULL) && (m_p_nArray != &m_p_nArray_Static[0])) + delete [] m_p_nArray; + + m_p_nArray = & m_p_nArray_Static[0]; + } else { + + // can't use static allocation...simply not enough room + // so dynamically allocate some space + if((m_p_nArray != NULL) && (m_p_nArray != &m_p_nArray_Static[0])) + delete [] m_p_nArray; + + m_p_nArray = new long[m_nArrayLen]; + } + + clear(); +} + +Set& Set::operator=(const Set& obj) { + if(this == &obj) { + // do nothing + } else { + + // resize this item + setSize(obj.getSize()); + + // copy the elements from obj to this + for(int i=0; i<m_nArrayLen; i++) { + m_p_nArray[i] = obj.m_p_nArray[i]; + } + } + + return *this; +} + +void Set::print(ostream& out) const +{ + if(m_p_nArray==NULL) { + out << "[Set {Empty}]"; + return; + } + char buff[24]; + out << "[Set 0x "; + for (int i=m_nArrayLen-1; i>=0; i--) { +#ifdef __32BITS__ + sprintf(buff,"%08X ",m_p_nArray[i]); +#else + sprintf(buff,"0x %016llX ",m_p_nArray[i]); +#endif // __32BITS__ + out << buff; + } + out << " ]"; + +} + + diff --git a/src/mem/ruby/common/OptBigSet.hh b/src/mem/ruby/common/OptBigSet.hh new file mode 100644 index 000000000..a57a07e13 --- /dev/null +++ b/src/mem/ruby/common/OptBigSet.hh @@ -0,0 +1,202 @@ + +/* + * 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. + */ + +/* + * Set.h + * + * Description: + * + * $Id: BigSet.h 1.6 05/01/19 13:12:25-06:00 mikem@maya.cs.wisc.edu $ + * + */ + +// modified by Dan Gibson on 05/20/05 to accomidate FASTER +// >32 set lengths, using an array of ints w/ 32 bits/int + +// NOTE: Never include this file directly, this should only be +// included from Set.h + +#ifndef SET_H +#define SET_H + +#include "Global.hh" +#include "Vector.hh" +#include "NodeID.hh" +#include "RubyConfig.hh" + +// gibson 05/20/05 +// enum PresenceBit {NotPresent, Present}; + +class Set { +public: + // Constructors + // creates and empty set + Set(); + Set (int size); + + // used during the replay mechanism + // Set(const char *str); + + Set(const Set& obj); + Set& operator=(const Set& obj); + + // Destructor + ~Set(); + + // Public Methods + + inline void add(NodeID index) + { +#ifdef __32BITS__ + m_p_nArray[index>>5] |= (1 << (index & 0x01F)); +#else + m_p_nArray[index>>6] |= (((unsigned long) 1) << (index & 0x03F)); +#endif // __32BITS__ + } + + void addSet(const Set& set); + void addRandom(); + + inline void remove(NodeID index) + { +#ifdef __32BITS__ + m_p_nArray[index>>5] &= ~(0x00000001 << (index & 0x01F)); +#else + m_p_nArray[index>>6] &= ~(((unsigned long) 0x0000000000000001) << (index & 0x03F)); +#endif // __32BITS__ + } + + + void removeSet(const Set& set); + + inline void clear() { for(int i=0; i<m_nArrayLen; i++) m_p_nArray[i] = 0; } + + void broadcast(); + int count() const; + bool isEqual(const Set& set) const; + + Set OR(const Set& orSet) const; // return the logical OR of this set and orSet + Set AND(const Set& andSet) const; // return the logical AND of this set and andSet + + // Returns true if the intersection of the two sets is non-empty + inline bool intersectionIsNotEmpty(const Set& other_set) const + { + for(int i=0; i< m_nArrayLen; i++) { + if(m_p_nArray[i] & other_set.m_p_nArray[i]) { + return true; + } + } + return false; + } + + // Returns true if the intersection of the two sets is empty + inline bool intersectionIsEmpty(const Set& other_set) const + { + for(int i=0; i< m_nArrayLen; i++) { + if(m_p_nArray[i] & other_set.m_p_nArray[i]) { + return false; + } + } + return true; + } + + bool isSuperset(const Set& test) const; + bool isSubset(const Set& test) const { return test.isSuperset(*this); } + + inline bool isElement(NodeID element) const + { +#ifdef __32BITS__ + return ((m_p_nArray[element>>5] & (0x00000001 << (element & 0x01F)))!=0); +#else + return ((m_p_nArray[element>>6] & (((unsigned long) 0x0000000000000001) << (element & 0x03F)))!=0); +#endif // __32BITS__ + + } + + bool isBroadcast() const; + bool isEmpty() const; + + NodeID smallestElement() const; + + // int size() const; + void setSize (int size); + + // get element for a index + inline NodeID elementAt(int index) const + { + if(isElement(index)) return (NodeID) true; + else return 0; + } + + // gibson 05/20/05 + int getSize() const { return m_nSize; } + + // DEPRECATED METHODS + void addToSet(NodeID newElement) { add(newElement); } // Deprecated + void removeFromSet(NodeID newElement) { remove(newElement); } // Deprecated + void clearSet() { clear(); } // Deprecated + void setBroadcast() { broadcast(); } // Deprecated + bool presentInSet(NodeID element) const { return isElement(element); } // Deprecated + + void print(ostream& out) const; +private: + // Private Methods + + // Data Members (m_ prefix) + // gibson 05/20/05 + // Vector<uint8> m_bits; // This is an vector of uint8 to reduce the size of the set + + int m_nSize; // the number of bits in this set + int m_nArrayLen; // the number of 32-bit words that are held in the array + + // Changed 5/24/05 for static allocation of array + // note that "long" corresponds to 32 bits on a 32-bit machine, + // 64 bits if the -m64 parameter is passed to g++, which it is + // for an AMD opteron under our configuration + + long * m_p_nArray; // an word array to hold the bits in the set + long m_p_nArray_Static[NUMBER_WORDS_PER_SET]; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Set& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Set& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SET_H + diff --git a/src/mem/ruby/common/Set.cc b/src/mem/ruby/common/Set.cc new file mode 100644 index 000000000..1f5b49f90 --- /dev/null +++ b/src/mem/ruby/common/Set.cc @@ -0,0 +1,231 @@ + +/* + * 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. + */ + +/* + * Set.C + * + * Description: See Set.h + * + * $Id$ + * + */ + +#include "Set.hh" +#include "RubyConfig.hh" + +#ifdef OPTBIGSET +#include "OptBigSet.cc" +#else + +#ifdef BIGSET +#include "BigSet.cc" // code to supports sets larger than 32 +#else + +Set::Set() +{ + setSize(RubyConfig::numberOfChips()); +} + +Set::Set(int size) +{ + setSize(size); +} + +bool Set::isEqual(const Set& set) +{ + return (m_bits == set.m_bits); +} + +void Set::add(NodeID index) +{ + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range + assert(index < m_size); + m_bits |= (1 << index); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::addSet(const Set& set) +{ + assert(m_size == set.m_size); + m_bits |= set.m_bits; + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::addRandom() +{ + m_bits |= random(); + m_bits &= m_mask; + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::remove(NodeID index) +{ + assert(index < m_size); + m_bits &= ~(1 << index); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::removeSet(const Set& set) +{ + assert(m_size == set.m_size); + m_bits &= ~(set.m_bits); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::clear() +{ + m_bits = 0; +} + +void Set::broadcast() +{ + m_bits = m_mask; +} + +int Set::count() const +{ + int counter = 0; + for (int i=0; i<m_size; i++) { + if ((m_bits & (1 << i)) != 0) { + counter++; + } + } + return counter; +} + +NodeID Set::elementAt(int index) { + // count from right to left, index starts from 0 + for (int i=0; i<m_size; i++) { + if ((m_bits & (1 << i)) != 0) { + if (index == 0) return i; + index --; + } + } + assert(0); // index out of range + return 0; +} + +NodeID Set::smallestElement() const +{ + assert(count() > 0); + int counter = 0; + for (int i=0; i<m_size; i++) { + if (isElement(i)) { + return i; + } + } + ERROR_MSG("No smallest element of an empty set."); +} + +// Returns true iff all bits are set +bool Set::isBroadcast() const +{ + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range + return (m_mask == m_bits); +} + +// Returns true iff no bits are set +bool Set::isEmpty() const +{ + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range + return (m_bits == 0); +} + +// returns the logical OR of "this" set and orSet +Set Set::OR(const Set& orSet) const +{ + assert(m_size == orSet.m_size); + Set result(m_size); + result.m_bits = (m_bits | orSet.m_bits); + assert((result.m_bits & result.m_mask) == result.m_bits); // check for any bits outside the range + return result; +} + +// returns the logical AND of "this" set and andSet +Set Set::AND(const Set& andSet) const +{ + assert(m_size == andSet.m_size); + Set result(m_size); + result.m_bits = (m_bits & andSet.m_bits); + assert((result.m_bits & result.m_mask) == result.m_bits); // check for any bits outside the range + return result; +} + +// Returns true if the intersection of the two sets is non-empty +bool Set::intersectionIsNotEmpty(const Set& other_set) const +{ + assert(m_size == other_set.m_size); + return ((m_bits & other_set.m_bits) != 0); +} + +// Returns true if the intersection of the two sets is empty +bool Set::intersectionIsEmpty(const Set& other_set) const +{ + assert(m_size == other_set.m_size); + return ((m_bits & other_set.m_bits) == 0); +} + +bool Set::isSuperset(const Set& test) const +{ + assert(m_size == test.m_size); + uint32 temp = (test.m_bits & (~m_bits)); + return (temp == 0); +} + +bool Set::isElement(NodeID element) const +{ + return ((m_bits & (1 << element)) != 0); +} + +void Set::setSize(int size) +{ + // We're using 32 bit ints, and the 32nd bit acts strangely due to + // signed/unsigned, so restrict the set size to 31 bits. + assert(size < 32); + m_size = size; + m_bits = 0; + m_mask = ~((~0) << m_size); + assert(m_mask != 0); + assert((m_bits & m_mask) == m_bits); // check for any bits outside the range +} + +void Set::print(ostream& out) const +{ + out << "[Set (" << m_size << ") "; + + for (int i=0; i<m_size; i++) { + out << (bool) isElement(i) << " "; + } + out << "]"; +} + +#endif // BIGSET + +#endif // OPTBIGSET + diff --git a/src/mem/ruby/common/Set.hh b/src/mem/ruby/common/Set.hh new file mode 100644 index 000000000..7c33c840d --- /dev/null +++ b/src/mem/ruby/common/Set.hh @@ -0,0 +1,149 @@ + +/* + * 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. + */ + +/* + * Set.h + * + * Description: + * + * $Id$ + * + */ + +// Define this to use the BigSet class which is slower, but supports +// sets of size larger than 32. + +// #define BIGSET + +#define OPTBIGSET + +#ifdef OPTBIGSET +#include "OptBigSet.hh" +#else + +#ifdef BIGSET +#include "BigSet.hh" // code to supports sets larger than 32 +#else + +#ifndef SET_H +#define SET_H + +#include "Global.hh" +#include "Vector.hh" +#include "NodeID.hh" +#include "RubyConfig.hh" + +class Set { +public: + // Constructors + // creates and empty set + Set(); + Set(int size); + + // used during the replay mechanism + // Set(const char *str); + + // Set(const Set& obj); + // Set& operator=(const Set& obj); + + // Destructor + // ~Set(); + + // Public Methods + + void add(NodeID newElement); + void addSet(const Set& set); + void addRandom(); + void remove(NodeID newElement); + void removeSet(const Set& set); + void clear(); + void broadcast(); + int count() const; + bool isEqual(const Set& set); + + Set OR(const Set& orSet) const; // return the logical OR of this set and orSet + Set AND(const Set& andSet) const; // return the logical AND of this set and andSet + + // Returns true if the intersection of the two sets is non-empty + bool intersectionIsNotEmpty(const Set& other_set) const; + + // Returns true if the intersection of the two sets is empty + bool intersectionIsEmpty(const Set& other_set) const; + + bool isSuperset(const Set& test) const; + bool isSubset(const Set& test) const { return test.isSuperset(*this); } + bool isElement(NodeID element) const; + bool isBroadcast() const; + bool isEmpty() const; + + NodeID smallestElement() const; + + // int size() const; + void setSize (int size); + + // get element for a index + NodeID elementAt(int index); + int getSize() const { return m_size; } + + // DEPRECATED METHODS + void addToSet(NodeID newElement) { add(newElement); } // Deprecated + void removeFromSet(NodeID newElement) { remove(newElement); } // Deprecated + void clearSet() { clear(); } // Deprecated + void setBroadcast() { broadcast(); } // Deprecated + bool presentInSet(NodeID element) const { return isElement(element); } // Deprecated + + void print(ostream& out) const; +private: + // Private Methods + + // Data Members (m_ prefix) + int m_size; + uint32 m_bits; // Set as a bit vector + uint32 m_mask; // a 000001111 mask where the number of 1s is equal to m_size + +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const Set& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const Set& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SET_H +#endif //BIGSET +#endif //OPTBIGSET + diff --git a/src/mem/ruby/common/SubBlock.cc b/src/mem/ruby/common/SubBlock.cc new file mode 100644 index 000000000..f79e33d9c --- /dev/null +++ b/src/mem/ruby/common/SubBlock.cc @@ -0,0 +1,81 @@ + +/* + * 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 "SubBlock.hh" + +SubBlock::SubBlock(const Address& addr, int size) +{ + m_address = addr; + setSize(size); + for(int i=0; i<size; i++) { + setByte(i, 0); + } +} + +SubBlock::SubBlock(const Address& addr, const Address& logicalAddress, int size) +{ + m_address = addr; + m_logicalAddress = logicalAddress; + setSize(size); + for(int i=0; i<size; i++) { + setByte(i, 0); + } +} + +void SubBlock::internalMergeFrom(const DataBlock& data) +{ + int size = getSize(); + assert(size > 0); + int offset = m_address.getOffset(); + for(int i=0; i<size; i++) { + this->setByte(i, data.getByte(offset+i)); + } +} + +void SubBlock::internalMergeTo(DataBlock& data) const +{ + int size = getSize(); + assert(size > 0); + int offset = m_address.getOffset(); + for(int i=0; i<size; i++) { + data.setByte(offset+i, this->getByte(i)); // This will detect crossing a cache line boundary + } +} + +void SubBlock::print(ostream& out) const +{ + out << "[" << m_address << ", " << getSize() << ", " << m_data << "]"; +} + + + diff --git a/src/mem/ruby/common/SubBlock.hh b/src/mem/ruby/common/SubBlock.hh new file mode 100644 index 000000000..43f91e191 --- /dev/null +++ b/src/mem/ruby/common/SubBlock.hh @@ -0,0 +1,105 @@ + +/* + * 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$ + * + */ + +#ifndef SubBlock_H +#define SubBlock_H + +#include "Global.hh" +#include "Address.hh" +#include "RubyConfig.hh" +#include "DataBlock.hh" +#include "Vector.hh" + +class SubBlock { +public: + // Constructors + SubBlock() { } + SubBlock(const Address& addr, int size); + SubBlock(const Address& addr, const Address& logicalAddress, int size); + + // Destructor + ~SubBlock() { } + + // Public Methods + const Address& getAddress() const { return m_address; } + const Address& getLogicalAddress() const { return m_logicalAddress; } + void setAddress(const Address& addr) { m_address = addr; } + void setLogicalAddress(const Address& addr) { m_logicalAddress = addr; } + + int getSize() const { return m_data.size(); } + void setSize(int size) { m_data.setSize(size); } + uint8 getByte(int offset) const { return m_data[offset]; } + void setByte(int offset, uint8 data) { m_data[offset] = data; } + + // Shorthands + uint8 readByte() const { return getByte(0); } + void writeByte(uint8 data) { setByte(0, data); } + + // Merging to and from DataBlocks - We only need to worry about + // updates when we are using DataBlocks + void mergeTo(DataBlock& data) const { if (DATA_BLOCK) { internalMergeTo(data); } } + void mergeFrom(const DataBlock& data) { if (DATA_BLOCK) { internalMergeFrom(data); } } + + void print(ostream& out) const; +private: + // Private Methods + // SubBlock(const SubBlock& obj); + // SubBlock& operator=(const SubBlock& obj); + // bool bytePresent(const Address& addr) { return ((addr.getAddress() >= 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<uint> m_data; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const SubBlock& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const SubBlock& obj) +{ + obj.print(out); + out << flush; + return out; +} + +#endif //SubBlock_H |