diff options
author | Nilay Vaish <nilay@cs.wisc.edu> | 2015-08-19 10:02:01 -0500 |
---|---|---|
committer | Nilay Vaish <nilay@cs.wisc.edu> | 2015-08-19 10:02:01 -0500 |
commit | 2f44dada688ace9c24f085a8422b3054c3edb72e (patch) | |
tree | 372bb043430552b0f4424eaa5571933883fcaaae /src/mem/ruby | |
parent | 2d9f3f8582e2de60850852c803a8c8ba0d6b91b5 (diff) | |
download | gem5-2f44dada688ace9c24f085a8422b3054c3edb72e.tar.xz |
ruby: reverts to changeset: bf82f1f7b040
Diffstat (limited to 'src/mem/ruby')
52 files changed, 556 insertions, 394 deletions
diff --git a/src/mem/ruby/common/DataBlock.hh b/src/mem/ruby/common/DataBlock.hh index 129a88e25..ac08fac82 100644 --- a/src/mem/ruby/common/DataBlock.hh +++ b/src/mem/ruby/common/DataBlock.hh @@ -67,8 +67,6 @@ class DataBlock private: void alloc(); uint8_t *m_data; - //! true if this DataBlock is responsible for deleting m_data, - //! false otherwise. bool m_alloc; }; diff --git a/src/mem/ruby/common/Histogram.cc b/src/mem/ruby/common/Histogram.cc index 31de160cf..e377bc253 100644 --- a/src/mem/ruby/common/Histogram.cc +++ b/src/mem/ruby/common/Histogram.cc @@ -84,7 +84,7 @@ Histogram::doubleBinSize() } void -Histogram::add(int64_t value) +Histogram::add(int64 value) { assert(value >= 0); m_max = max(m_max, value); diff --git a/src/mem/ruby/common/Histogram.hh b/src/mem/ruby/common/Histogram.hh index f02c4bedd..c34e39af1 100644 --- a/src/mem/ruby/common/Histogram.hh +++ b/src/mem/ruby/common/Histogram.hh @@ -40,7 +40,7 @@ class Histogram Histogram(int binsize = 1, uint32_t bins = 50); ~Histogram(); - void add(int64_t value); + void add(int64 value); void add(Histogram& hist); void doubleBinSize(); @@ -51,10 +51,10 @@ class Histogram uint64_t size() const { return m_count; } uint32_t getBins() const { return m_data.size(); } int getBinSize() const { return m_binsize; } - int64_t getTotal() const { return m_sumSamples; } + int64 getTotal() const { return m_sumSamples; } uint64_t getSquaredTotal() const { return m_sumSquaredSamples; } uint64_t getData(int index) const { return m_data[index]; } - int64_t getMax() const { return m_max; } + int64 getMax() const { return m_max; } void printWithMultiplier(std::ostream& out, double multiplier) const; void printPercent(std::ostream& out) const; @@ -62,12 +62,12 @@ class Histogram private: std::vector<uint64_t> m_data; - int64_t m_max; // the maximum value seen so far + int64 m_max; // the maximum value seen so far uint64_t m_count; // the number of elements added int m_binsize; // the size of each bucket uint32_t m_largest_bin; // the largest bin used - int64_t m_sumSamples; // the sum of all samples + int64 m_sumSamples; // the sum of all samples uint64_t m_sumSquaredSamples; // the sum of the square of all samples double getStandardDeviation() const; diff --git a/src/mem/ruby/common/SubBlock.cc b/src/mem/ruby/common/SubBlock.cc index f1839df72..5175cb950 100644 --- a/src/mem/ruby/common/SubBlock.cc +++ b/src/mem/ruby/common/SubBlock.cc @@ -41,7 +41,7 @@ SubBlock::SubBlock(Addr addr, int size) } void -SubBlock::mergeFrom(const DataBlock& data) +SubBlock::internalMergeFrom(const DataBlock& data) { int size = getSize(); assert(size > 0); @@ -52,7 +52,7 @@ SubBlock::mergeFrom(const DataBlock& data) } void -SubBlock::mergeTo(DataBlock& data) const +SubBlock::internalMergeTo(DataBlock& data) const { int size = getSize(); assert(size > 0); @@ -68,3 +68,6 @@ SubBlock::print(std::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 index f336328fa..ad1d68ae1 100644 --- a/src/mem/ruby/common/SubBlock.hh +++ b/src/mem/ruby/common/SubBlock.hh @@ -56,12 +56,15 @@ class SubBlock // Merging to and from DataBlocks - We only need to worry about // updates when we are using DataBlocks - void mergeTo(DataBlock& data) const; - void mergeFrom(const DataBlock& data); + void mergeTo(DataBlock& data) const { internalMergeTo(data); } + void mergeFrom(const DataBlock& data) { internalMergeFrom(data); } void print(std::ostream& out) const; private: + void internalMergeTo(DataBlock& data) const; + void internalMergeFrom(const DataBlock& data); + // Data Members (m_ prefix) Addr m_address; std::vector<uint8_t> m_data; diff --git a/src/mem/ruby/common/TypeDefines.hh b/src/mem/ruby/common/TypeDefines.hh index f29efe8b5..203b63779 100644 --- a/src/mem/ruby/common/TypeDefines.hh +++ b/src/mem/ruby/common/TypeDefines.hh @@ -30,6 +30,9 @@ #ifndef TYPEDEFINES_H #define TYPEDEFINES_H +typedef unsigned long long uint64; +typedef long long int64; + typedef unsigned int LinkID; typedef unsigned int NodeID; typedef unsigned int SwitchID; diff --git a/src/mem/ruby/filters/H3BloomFilter.cc b/src/mem/ruby/filters/H3BloomFilter.cc index b0d277782..21b9152be 100644 --- a/src/mem/ruby/filters/H3BloomFilter.cc +++ b/src/mem/ruby/filters/H3BloomFilter.cc @@ -507,8 +507,8 @@ H3BloomFilter::print(ostream& out) const int H3BloomFilter::get_index(Addr addr, int i) { - uint64_t x = makeLineAddress(addr); - // uint64_t y = (x*mults_list[i] + adds_list[i]) % primes_list[i]; + uint64 x = makeLineAddress(addr); + // uint64 y = (x*mults_list[i] + adds_list[i]) % primes_list[i]; int y = hash_H3(x,i); if (isParallel) { @@ -519,10 +519,10 @@ H3BloomFilter::get_index(Addr addr, int i) } int -H3BloomFilter::hash_H3(uint64_t value, int index) +H3BloomFilter::hash_H3(uint64 value, int index) { - uint64_t mask = 1; - uint64_t val = value; + uint64 mask = 1; + uint64 val = value; int result = 0; for (int i = 0; i < 64; i++) { diff --git a/src/mem/ruby/filters/H3BloomFilter.hh b/src/mem/ruby/filters/H3BloomFilter.hh index b6628f5e1..8596d6acb 100644 --- a/src/mem/ruby/filters/H3BloomFilter.hh +++ b/src/mem/ruby/filters/H3BloomFilter.hh @@ -68,7 +68,7 @@ class H3BloomFilter : public AbstractBloomFilter private: int get_index(Addr addr, int hashNumber); - int hash_H3(uint64_t value, int index); + int hash_H3(uint64 value, int index); std::vector<int> m_filter; int m_filter_size; diff --git a/src/mem/ruby/filters/MultiBitSelBloomFilter.cc b/src/mem/ruby/filters/MultiBitSelBloomFilter.cc index f326030e9..3cdca7e3b 100644 --- a/src/mem/ruby/filters/MultiBitSelBloomFilter.cc +++ b/src/mem/ruby/filters/MultiBitSelBloomFilter.cc @@ -171,7 +171,7 @@ MultiBitSelBloomFilter::get_index(Addr addr, int i) // m_skip_bits is used to perform BitSelect after skipping some // bits. Used to simulate BitSel hashing on larger than cache-line // granularities - uint64_t x = (makeLineAddress(addr) >> m_skip_bits); + uint64 x = (makeLineAddress(addr) >> m_skip_bits); int y = hash_bitsel(x, i, m_num_hashes, 30, m_filter_size_bits); //36-bit addresses, 6-bit cache lines @@ -183,10 +183,10 @@ MultiBitSelBloomFilter::get_index(Addr addr, int i) } int -MultiBitSelBloomFilter::hash_bitsel(uint64_t value, int index, int jump, +MultiBitSelBloomFilter::hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits) { - uint64_t mask = 1; + uint64 mask = 1; int result = 0; int bit, i; diff --git a/src/mem/ruby/filters/MultiBitSelBloomFilter.hh b/src/mem/ruby/filters/MultiBitSelBloomFilter.hh index b4fac0671..e43dcd6f1 100644 --- a/src/mem/ruby/filters/MultiBitSelBloomFilter.hh +++ b/src/mem/ruby/filters/MultiBitSelBloomFilter.hh @@ -68,7 +68,7 @@ class MultiBitSelBloomFilter : public AbstractBloomFilter private: int get_index(Addr addr, int hashNumber); - int hash_bitsel(uint64_t value, int index, int jump, int maxBits, + int hash_bitsel(uint64 value, int index, int jump, int maxBits, int numBits); std::vector<int> m_filter; diff --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc index e9c575028..a72d8509e 100644 --- a/src/mem/ruby/network/MessageBuffer.cc +++ b/src/mem/ruby/network/MessageBuffer.cc @@ -362,6 +362,32 @@ MessageBuffer::isReady() const (m_prio_heap.front()->getLastEnqueueTime() <= m_receiver->clockEdge())); } +bool +MessageBuffer::functionalRead(Packet *pkt) +{ + // Check the priority heap and read any messages that may + // correspond to the address in the packet. + for (unsigned int i = 0; i < m_prio_heap.size(); ++i) { + Message *msg = m_prio_heap[i].get(); + if (msg->functionalRead(pkt)) return true; + } + + // Read the messages in the stall queue that correspond + // to the address in the packet. + for (StallMsgMapType::iterator map_iter = m_stall_msg_map.begin(); + map_iter != m_stall_msg_map.end(); + ++map_iter) { + + for (std::list<MsgPtr>::iterator it = (map_iter->second).begin(); + it != (map_iter->second).end(); ++it) { + + Message *msg = (*it).get(); + if (msg->functionalRead(pkt)) return true; + } + } + return false; +} + uint32_t MessageBuffer::functionalWrite(Packet *pkt) { diff --git a/src/mem/ruby/network/MessageBuffer.hh b/src/mem/ruby/network/MessageBuffer.hh index 2625acabd..732b7ec6c 100644 --- a/src/mem/ruby/network/MessageBuffer.hh +++ b/src/mem/ruby/network/MessageBuffer.hh @@ -136,6 +136,11 @@ class MessageBuffer : public SimObject void setIncomingLink(int link_id) { m_input_link_id = link_id; } void setVnet(int net) { m_vnet_id = net; } + // Function for figuring out if any of the messages in the buffer can + // satisfy the read request for the address in the packet. + // Return value, if true, indicates that the request was fulfilled. + bool functionalRead(Packet *pkt); + // Function for figuring out if any of the messages in the buffer need // to be updated with the data from the packet. // Return value indicates the number of messages that were updated. @@ -179,7 +184,7 @@ class MessageBuffer : public SimObject int m_not_avail_count; // count the # of times I didn't have N // slots available - uint64_t m_msg_counter; + uint64 m_msg_counter; int m_priority_rank; const bool m_strict_fifo; const bool m_randomization; diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc index f72cea5a8..d834ea1a3 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc @@ -281,7 +281,7 @@ NetworkInterface::wakeup() int vnet = t_flit->get_vnet(); m_net_ptr->increment_received_flits(vnet); - Cycles network_delay = curCycle() - t_flit->get_creation_time(); + Cycles network_delay = curCycle() - t_flit->get_enqueue_time(); Cycles queueing_delay = t_flit->get_delay(); m_net_ptr->increment_network_latency(network_delay, vnet); diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/flit.cc b/src/mem/ruby/network/garnet/flexible-pipeline/flit.cc index aaf19b3b5..7cf68560f 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/flit.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/flit.cc @@ -31,10 +31,14 @@ #include "mem/ruby/network/garnet/flexible-pipeline/flit.hh" flit::flit(int id, int vc, int vnet, int size, MsgPtr msg_ptr, Cycles curTime) - : m_id(id), m_vnet(vnet), m_vc(vc), m_size(size), m_creation_time(curTime) { + m_size = size; m_msg_ptr = msg_ptr; + m_enqueue_time = curTime; m_time = curTime; + m_id = id; + m_vnet = vnet; + m_vc = vc; if (size == 1) { m_type = HEAD_TAIL_; @@ -48,6 +52,78 @@ flit::flit(int id, int vc, int vnet, int size, MsgPtr msg_ptr, Cycles curTime) m_type = BODY_; } +int +flit::get_size() +{ + return m_size; +} + +int +flit::get_id() +{ + return m_id; +} + +Cycles +flit::get_time() +{ + return m_time; +} + +Cycles +flit::get_enqueue_time() +{ + return m_enqueue_time; +} + +void +flit::set_time(Cycles time) +{ + m_time = time; +} + +int +flit::get_vnet() +{ + return m_vnet; +} + +int +flit::get_vc() +{ + return m_vc; +} + +void +flit::set_vc(int vc) +{ + m_vc = vc; +} + +MsgPtr& +flit::get_msg_ptr() +{ + return m_msg_ptr; +} + +flit_type +flit::get_type() +{ + return m_type; +} + +void +flit::set_delay(Cycles delay) +{ + src_delay = delay; +} + +Cycles +flit::get_delay() +{ + return src_delay; +} + void flit::print(std::ostream& out) const { @@ -56,7 +132,7 @@ flit::print(std::ostream& out) const out << "Type=" << m_type << " "; out << "Vnet=" << m_vnet << " "; out << "VC=" << m_vc << " "; - out << "Creation Time=" << m_creation_time << " "; + out << "Enqueue Time=" << m_enqueue_time << " "; out << "]"; } diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/flit.hh b/src/mem/ruby/network/garnet/flexible-pipeline/flit.hh index 4049a9212..ff4afbc08 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/flit.hh +++ b/src/mem/ruby/network/garnet/flexible-pipeline/flit.hh @@ -43,18 +43,18 @@ class flit public: flit(int id, int vc, int vnet, int size, MsgPtr msg_ptr, Cycles curTime); - int get_size() const { return m_size; } - int get_id() const { return m_id; } - Cycles get_time() const { return m_time; } - Cycles get_creation_time() const { return m_creation_time; } - void set_time(Cycles time) { m_time = time; } - int get_vnet() const { return m_vnet; } - int get_vc() const { return m_vc; } - void set_vc(int vc) { m_vc = vc; } - MsgPtr& get_msg_ptr() { return m_msg_ptr; } - flit_type get_type() const { return m_type; } - void set_delay(Cycles delay) { src_delay = delay; } - Cycles get_delay() const { return src_delay; } + int get_size(); + int get_id(); + Cycles get_time(); + Cycles get_enqueue_time(); + void set_time(Cycles time); + int get_vnet(); + int get_vc(); + void set_vc(int vc); + MsgPtr& get_msg_ptr(); + flit_type get_type(); + void set_delay(Cycles delay); + Cycles get_delay(); void print(std::ostream& out) const; static bool @@ -71,12 +71,11 @@ class flit bool functionalWrite(Packet *pkt); private: - const int m_id; - const int m_vnet; + int m_id; + int m_vnet; int m_vc; - const int m_size; - const Cycles m_creation_time; - Cycles m_time; + int m_size; + Cycles m_enqueue_time, m_time; flit_type m_type; MsgPtr m_msg_ptr; Cycles src_delay; diff --git a/src/mem/ruby/network/simple/PerfectSwitch.cc b/src/mem/ruby/network/simple/PerfectSwitch.cc index 697357ccb..de038d211 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.cc +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc @@ -49,8 +49,9 @@ operator<(const LinkOrder& l1, const LinkOrder& l2) } PerfectSwitch::PerfectSwitch(SwitchID sid, Switch *sw, uint32_t virt_nets) - : Consumer(sw), m_switch_id(sid), m_switch(sw) + : Consumer(sw) { + m_switch_id = sid; m_round_robin_start = 0; m_wakeups_wo_switch = 0; m_virtual_networks = virt_nets; @@ -103,6 +104,9 @@ PerfectSwitch::~PerfectSwitch() void PerfectSwitch::operateVnet(int vnet) { + MsgPtr msg_ptr; + Message *net_msg_ptr = NULL; + // This is for round-robin scheduling int incoming = m_round_robin_start; m_round_robin_start++; @@ -119,6 +123,10 @@ PerfectSwitch::operateVnet(int vnet) incoming = 0; } + // temporary vectors to store the routing results + vector<LinkID> output_links; + vector<NetDest> output_link_destinations; + // Is there a message waiting? if (m_in[incoming].size() <= vnet) { continue; @@ -129,151 +137,138 @@ PerfectSwitch::operateVnet(int vnet) continue; } - operateMessageBuffer(buffer, incoming, vnet); - } - } -} - -void -PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming, - int vnet) -{ - MsgPtr msg_ptr; - Message *net_msg_ptr = NULL; - - // temporary vectors to store the routing results - vector<LinkID> output_links; - vector<NetDest> output_link_destinations; - - while (buffer->isReady()) { - DPRINTF(RubyNetwork, "incoming: %d\n", incoming); - - // Peek at message - msg_ptr = buffer->peekMsgPtr(); - net_msg_ptr = msg_ptr.get(); - DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); - - output_links.clear(); - output_link_destinations.clear(); - NetDest msg_dsts = net_msg_ptr->getDestination(); - - // Unfortunately, the token-protocol sends some - // zero-destination messages, so this assert isn't valid - // assert(msg_dsts.count() > 0); - - assert(m_link_order.size() == m_routing_table.size()); - assert(m_link_order.size() == m_out.size()); - - if (m_network_ptr->getAdaptiveRouting()) { - if (m_network_ptr->isVNetOrdered(vnet)) { - // Don't adaptively route - for (int out = 0; out < m_out.size(); out++) { - m_link_order[out].m_link = out; - m_link_order[out].m_value = 0; - } - } else { - // Find how clogged each link is - for (int out = 0; out < m_out.size(); out++) { - int out_queue_length = 0; - for (int v = 0; v < m_virtual_networks; v++) { - out_queue_length += m_out[out][v]->getSize(); + while (buffer->isReady()) { + DPRINTF(RubyNetwork, "incoming: %d\n", incoming); + + // Peek at message + msg_ptr = buffer->peekMsgPtr(); + net_msg_ptr = msg_ptr.get(); + DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); + + output_links.clear(); + output_link_destinations.clear(); + NetDest msg_dsts = net_msg_ptr->getDestination(); + + // Unfortunately, the token-protocol sends some + // zero-destination messages, so this assert isn't valid + // assert(msg_dsts.count() > 0); + + assert(m_link_order.size() == m_routing_table.size()); + assert(m_link_order.size() == m_out.size()); + + if (m_network_ptr->getAdaptiveRouting()) { + if (m_network_ptr->isVNetOrdered(vnet)) { + // Don't adaptively route + for (int out = 0; out < m_out.size(); out++) { + m_link_order[out].m_link = out; + m_link_order[out].m_value = 0; + } + } else { + // Find how clogged each link is + for (int out = 0; out < m_out.size(); out++) { + int out_queue_length = 0; + for (int v = 0; v < m_virtual_networks; v++) { + out_queue_length += m_out[out][v]->getSize(); + } + int value = + (out_queue_length << 8) | + random_mt.random(0, 0xff); + m_link_order[out].m_link = out; + m_link_order[out].m_value = value; + } + + // Look at the most empty link first + sort(m_link_order.begin(), m_link_order.end()); } - int value = - (out_queue_length << 8) | - random_mt.random(0, 0xff); - m_link_order[out].m_link = out; - m_link_order[out].m_value = value; } - // Look at the most empty link first - sort(m_link_order.begin(), m_link_order.end()); - } - } + for (int i = 0; i < m_routing_table.size(); i++) { + // pick the next link to look at + int link = m_link_order[i].m_link; + NetDest dst = m_routing_table[link]; + DPRINTF(RubyNetwork, "dst: %s\n", dst); - for (int i = 0; i < m_routing_table.size(); i++) { - // pick the next link to look at - int link = m_link_order[i].m_link; - NetDest dst = m_routing_table[link]; - DPRINTF(RubyNetwork, "dst: %s\n", dst); + if (!msg_dsts.intersectionIsNotEmpty(dst)) + continue; - if (!msg_dsts.intersectionIsNotEmpty(dst)) - continue; + // Remember what link we're using + output_links.push_back(link); - // Remember what link we're using - output_links.push_back(link); + // Need to remember which destinations need this message in + // another vector. This Set is the intersection of the + // routing_table entry and the current destination set. The + // intersection must not be empty, since we are inside "if" + output_link_destinations.push_back(msg_dsts.AND(dst)); - // Need to remember which destinations need this message in - // another vector. This Set is the intersection of the - // routing_table entry and the current destination set. The - // intersection must not be empty, since we are inside "if" - output_link_destinations.push_back(msg_dsts.AND(dst)); - - // Next, we update the msg_destination not to include - // those nodes that were already handled by this link - msg_dsts.removeNetDest(dst); - } + // Next, we update the msg_destination not to include + // those nodes that were already handled by this link + msg_dsts.removeNetDest(dst); + } - assert(msg_dsts.count() == 0); + assert(msg_dsts.count() == 0); - // Check for resources - for all outgoing queues - bool enough = true; - for (int i = 0; i < output_links.size(); i++) { - int outgoing = output_links[i]; + // Check for resources - for all outgoing queues + bool enough = true; + for (int i = 0; i < output_links.size(); i++) { + int outgoing = output_links[i]; - if (!m_out[outgoing][vnet]->areNSlotsAvailable(1)) - enough = false; + if (!m_out[outgoing][vnet]->areNSlotsAvailable(1)) + enough = false; - DPRINTF(RubyNetwork, "Checking if node is blocked ..." - "outgoing: %d, vnet: %d, enough: %d\n", - outgoing, vnet, enough); - } + DPRINTF(RubyNetwork, "Checking if node is blocked ..." + "outgoing: %d, vnet: %d, enough: %d\n", + outgoing, vnet, enough); + } - // There were not enough resources - if (!enough) { - scheduleEvent(Cycles(1)); - DPRINTF(RubyNetwork, "Can't deliver message since a node " - "is blocked\n"); - DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); - break; // go to next incoming port - } + // There were not enough resources + if (!enough) { + scheduleEvent(Cycles(1)); + DPRINTF(RubyNetwork, "Can't deliver message since a node " + "is blocked\n"); + DPRINTF(RubyNetwork, "Message: %s\n", (*net_msg_ptr)); + break; // go to next incoming port + } - MsgPtr unmodified_msg_ptr; + MsgPtr unmodified_msg_ptr; - if (output_links.size() > 1) { - // If we are sending this message down more than one link - // (size>1), we need to make a copy of the message so each - // branch can have a different internal destination we need - // to create an unmodified MsgPtr because the MessageBuffer - // enqueue func will modify the message + if (output_links.size() > 1) { + // If we are sending this message down more than one link + // (size>1), we need to make a copy of the message so each + // branch can have a different internal destination we need + // to create an unmodified MsgPtr because the MessageBuffer + // enqueue func will modify the message - // This magic line creates a private copy of the message - unmodified_msg_ptr = msg_ptr->clone(); - } + // This magic line creates a private copy of the message + unmodified_msg_ptr = msg_ptr->clone(); + } - // Dequeue msg - buffer->dequeue(); - m_pending_message_count[vnet]--; + // Dequeue msg + buffer->dequeue(); + m_pending_message_count[vnet]--; - // Enqueue it - for all outgoing queues - for (int i=0; i<output_links.size(); i++) { - int outgoing = output_links[i]; + // Enqueue it - for all outgoing queues + for (int i=0; i<output_links.size(); i++) { + int outgoing = output_links[i]; - if (i > 0) { - // create a private copy of the unmodified message - msg_ptr = unmodified_msg_ptr->clone(); - } + if (i > 0) { + // create a private copy of the unmodified message + msg_ptr = unmodified_msg_ptr->clone(); + } - // Change the internal destination set of the message so it - // knows which destinations this link is responsible for. - net_msg_ptr = msg_ptr.get(); - net_msg_ptr->getDestination() = output_link_destinations[i]; + // Change the internal destination set of the message so it + // knows which destinations this link is responsible for. + net_msg_ptr = msg_ptr.get(); + net_msg_ptr->getDestination() = + output_link_destinations[i]; - // Enqeue msg - DPRINTF(RubyNetwork, "Enqueuing net msg from " - "inport[%d][%d] to outport [%d][%d].\n", - incoming, vnet, outgoing, vnet); + // Enqeue msg + DPRINTF(RubyNetwork, "Enqueuing net msg from " + "inport[%d][%d] to outport [%d][%d].\n", + incoming, vnet, outgoing, vnet); - m_out[outgoing][vnet]->enqueue(msg_ptr); + m_out[outgoing][vnet]->enqueue(msg_ptr); + } + } } } } diff --git a/src/mem/ruby/network/simple/PerfectSwitch.hh b/src/mem/ruby/network/simple/PerfectSwitch.hh index 1cc986964..f55281d54 100644 --- a/src/mem/ruby/network/simple/PerfectSwitch.hh +++ b/src/mem/ruby/network/simple/PerfectSwitch.hh @@ -85,10 +85,8 @@ class PerfectSwitch : public Consumer PerfectSwitch& operator=(const PerfectSwitch& obj); void operateVnet(int vnet); - void operateMessageBuffer(MessageBuffer *b, int incoming, int vnet); - const SwitchID m_switch_id; - Switch * const m_switch; + SwitchID m_switch_id; // vector of queues from the components std::vector<std::vector<MessageBuffer*> > m_in; diff --git a/src/mem/ruby/network/simple/SimpleNetwork.cc b/src/mem/ruby/network/simple/SimpleNetwork.cc index 09daa7960..5b7d7ebad 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.cc +++ b/src/mem/ruby/network/simple/SimpleNetwork.cc @@ -38,15 +38,23 @@ #include "mem/ruby/network/simple/Switch.hh" #include "mem/ruby/network/simple/Throttle.hh" #include "mem/ruby/profiler/Profiler.hh" +#include "mem/ruby/system/System.hh" using namespace std; using m5::stl_helpers::deletePointers; SimpleNetwork::SimpleNetwork(const Params *p) - : Network(p), m_buffer_size(p->buffer_size), - m_endpoint_bandwidth(p->endpoint_bandwidth), - m_adaptive_routing(p->adaptive_routing) + : Network(p) { + m_buffer_size = p->buffer_size; + m_endpoint_bandwidth = p->endpoint_bandwidth; + m_adaptive_routing = p->adaptive_routing; + + // Note: the parent Network Object constructor is called before the + // SimpleNetwork child constructor. Therefore, the member variables + // used below should already be initialized. + m_endpoint_switches.resize(m_nodes); + // record the routers for (vector<BasicRouter*>::const_iterator i = p->routers.begin(); i != p->routers.end(); ++i) { @@ -91,6 +99,8 @@ SimpleNetwork::makeOutLink(SwitchID src, NodeID dest, BasicLink* link, m_switches[src]->addOutPort(m_fromNetQueues[dest], routing_table_entry, simple_link->m_latency, simple_link->m_bw_multiplier); + + m_endpoint_switches[dest] = m_switches[src]; } // From an endpoint node to a switch @@ -223,6 +233,12 @@ SimpleNetwork::functionalRead(Packet *pkt) } } + for (unsigned int i = 0; i < m_int_link_buffers.size(); ++i) { + if (m_int_link_buffers[i]->functionalRead(pkt)) { + return true; + } + } + return false; } diff --git a/src/mem/ruby/network/simple/SimpleNetwork.hh b/src/mem/ruby/network/simple/SimpleNetwork.hh index efb342e6e..fe0c1838b 100644 --- a/src/mem/ruby/network/simple/SimpleNetwork.hh +++ b/src/mem/ruby/network/simple/SimpleNetwork.hh @@ -95,9 +95,11 @@ class SimpleNetwork : public Network std::vector<Switch*> m_switches; std::vector<MessageBuffer*> m_int_link_buffers; int m_num_connected_buffers; - const int m_buffer_size; - const int m_endpoint_bandwidth; - const bool m_adaptive_routing; + std::vector<Switch*> m_endpoint_switches; + + int m_buffer_size; + int m_endpoint_bandwidth; + bool m_adaptive_routing; //Statistical variables Stats::Formula m_msg_counts[MessageSizeType_NUM]; diff --git a/src/mem/ruby/network/simple/Switch.cc b/src/mem/ruby/network/simple/Switch.cc index e5988e505..b9d0b8010 100644 --- a/src/mem/ruby/network/simple/Switch.cc +++ b/src/mem/ruby/network/simple/Switch.cc @@ -184,6 +184,12 @@ Switch::print(std::ostream& out) const bool Switch::functionalRead(Packet *pkt) { + // Access the buffers in the switch for performing a functional read + for (unsigned int i = 0; i < m_port_buffers.size(); ++i) { + if (m_port_buffers[i]->functionalRead(pkt)) { + return true; + } + } return false; } diff --git a/src/mem/ruby/network/simple/Throttle.cc b/src/mem/ruby/network/simple/Throttle.cc index c97531e58..785e09aa2 100644 --- a/src/mem/ruby/network/simple/Throttle.cc +++ b/src/mem/ruby/network/simple/Throttle.cc @@ -31,7 +31,6 @@ #include "base/cast.hh" #include "base/cprintf.hh" #include "debug/RubyNetwork.hh" -#include "mem/ruby/network/simple/Switch.hh" #include "mem/ruby/network/simple/Throttle.hh" #include "mem/ruby/network/MessageBuffer.hh" #include "mem/ruby/network/Network.hh" @@ -49,10 +48,27 @@ static int network_message_to_size(Message* net_msg_ptr); Throttle::Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth, - Switch *em) - : Consumer(em), m_switch_id(sID), m_switch(em), m_node(node), - m_ruby_system(rs) + ClockedObject *em) + : Consumer(em), m_ruby_system(rs) { + init(node, link_latency, link_bandwidth_multiplier, endpoint_bandwidth); + m_sID = sID; +} + +Throttle::Throttle(RubySystem *rs, NodeID node, Cycles link_latency, + int link_bandwidth_multiplier, int endpoint_bandwidth, + ClockedObject *em) + : Consumer(em), m_ruby_system(rs) +{ + init(node, link_latency, link_bandwidth_multiplier, endpoint_bandwidth); + m_sID = 0; +} + +void +Throttle::init(NodeID node, Cycles link_latency, + int link_bandwidth_multiplier, int endpoint_bandwidth) +{ + m_node = node; m_vnets = 0; assert(link_bandwidth_multiplier > 0); @@ -82,7 +98,7 @@ Throttle::addLinks(const vector<MessageBuffer*>& in_vec, // Set consumer and description in_ptr->setConsumer(this); - string desc = "[Queue to Throttle " + to_string(m_switch_id) + " " + + string desc = "[Queue to Throttle " + to_string(m_sID) + " " + to_string(m_node) + "]"; } } diff --git a/src/mem/ruby/network/simple/Throttle.hh b/src/mem/ruby/network/simple/Throttle.hh index 405593bb1..85bf9691a 100644 --- a/src/mem/ruby/network/simple/Throttle.hh +++ b/src/mem/ruby/network/simple/Throttle.hh @@ -47,18 +47,20 @@ #include "mem/ruby/system/System.hh" class MessageBuffer; -class Switch; class Throttle : public Consumer { public: Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth, - Switch *em); + ClockedObject *em); + Throttle(RubySystem *rs, NodeID node, Cycles link_latency, + int link_bandwidth_multiplier, int endpoint_bandwidth, + ClockedObject *em); ~Throttle() {} std::string name() - { return csprintf("Throttle-%i", m_switch_id); } + { return csprintf("Throttle-%i", m_sID); } void addLinks(const std::vector<MessageBuffer*>& in_vec, const std::vector<MessageBuffer*>& out_vec); @@ -95,10 +97,8 @@ class Throttle : public Consumer unsigned int m_vnets; std::vector<int> m_units_remaining; - const int m_switch_id; - Switch *m_switch; + int m_sID; NodeID m_node; - int m_link_bandwidth_multiplier; Cycles m_link_latency; int m_wakeups_wo_switch; diff --git a/src/mem/ruby/profiler/AccessTraceForAddress.hh b/src/mem/ruby/profiler/AccessTraceForAddress.hh index 3e9d54499..af42489bc 100644 --- a/src/mem/ruby/profiler/AccessTraceForAddress.hh +++ b/src/mem/ruby/profiler/AccessTraceForAddress.hh @@ -67,12 +67,12 @@ class AccessTraceForAddress private: Addr m_addr; - uint64_t m_loads; - uint64_t m_stores; - uint64_t m_atomics; - uint64_t m_total; - uint64_t m_user; - uint64_t m_sharing; + uint64 m_loads; + uint64 m_stores; + uint64 m_atomics; + uint64 m_total; + uint64 m_user; + uint64 m_sharing; Set m_touched_by; Histogram* m_histogram_ptr; }; diff --git a/src/mem/ruby/profiler/AddressProfiler.cc b/src/mem/ruby/profiler/AddressProfiler.cc index 52c693330..0e7ea7e36 100644 --- a/src/mem/ruby/profiler/AddressProfiler.cc +++ b/src/mem/ruby/profiler/AddressProfiler.cc @@ -67,7 +67,7 @@ printSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map, { const int records_printed = 100; - uint64_t misses = 0; + uint64 misses = 0; std::vector<const AccessTraceForAddress *> sorted; AddressMap::const_iterator i = record_map.begin(); @@ -95,8 +95,8 @@ printSorted(ostream& out, int num_of_sequencers, const AddressMap &record_map, Histogram all_records_log(-1); // Allows us to track how many lines where touched by n processors - std::vector<int64_t> m_touched_vec; - std::vector<int64_t> m_touched_weighted_vec; + std::vector<int64> m_touched_vec; + std::vector<int64> m_touched_weighted_vec; m_touched_vec.resize(num_of_sequencers+1); m_touched_weighted_vec.resize(num_of_sequencers+1); for (int j = 0; j < m_touched_vec.size(); j++) { diff --git a/src/mem/ruby/profiler/AddressProfiler.hh b/src/mem/ruby/profiler/AddressProfiler.hh index ebd44080b..39544c0a2 100644 --- a/src/mem/ruby/profiler/AddressProfiler.hh +++ b/src/mem/ruby/profiler/AddressProfiler.hh @@ -75,7 +75,7 @@ class AddressProfiler AddressProfiler(const AddressProfiler& obj); AddressProfiler& operator=(const AddressProfiler& obj); - int64_t m_sharing_miss_counter; + int64 m_sharing_miss_counter; AddressMap m_dataAccessTrace; AddressMap m_macroBlockAccessTrace; diff --git a/src/mem/ruby/profiler/Profiler.cc b/src/mem/ruby/profiler/Profiler.cc index b3b37e5a6..7decd497a 100644 --- a/src/mem/ruby/profiler/Profiler.cc +++ b/src/mem/ruby/profiler/Profiler.cc @@ -61,10 +61,11 @@ using namespace std; using m5::stl_helpers::operator<<; Profiler::Profiler(const RubySystemParams *p, RubySystem *rs) - : m_ruby_system(rs), m_hot_lines(p->hot_lines), - m_all_instructions(p->all_instructions), - m_num_vnets(p->number_of_virtual_networks) + : m_ruby_system(rs) { + m_hot_lines = p->hot_lines; + m_all_instructions = p->all_instructions; + m_address_profiler_ptr = new AddressProfiler(p->num_of_sequencers, this); m_address_profiler_ptr->setHotLines(m_hot_lines); m_address_profiler_ptr->setAllInstructions(m_all_instructions); @@ -97,7 +98,8 @@ Profiler::regStats(const std::string &pName) .desc("delay histogram for all message") .flags(Stats::nozero | Stats::pdf | Stats::oneline); - for (int i = 0; i < m_num_vnets; i++) { + uint32_t numVNets = Network::getNumberOfVirtualNetworks(); + for (int i = 0; i < numVNets; i++) { delayVCHistogram.push_back(new Stats::Histogram()); delayVCHistogram[i] ->init(10) @@ -249,6 +251,7 @@ Profiler::collateStats() m_inst_profiler_ptr->collateStats(); } + uint32_t numVNets = Network::getNumberOfVirtualNetworks(); for (uint32_t i = 0; i < MachineType_NUM; i++) { for (map<uint32_t, AbstractController*>::iterator it = m_ruby_system->m_abstract_controls[i].begin(); @@ -257,7 +260,7 @@ Profiler::collateStats() AbstractController *ctr = (*it).second; delayHistogram.add(ctr->getDelayHist()); - for (uint32_t i = 0; i < m_num_vnets; i++) { + for (uint32_t i = 0; i < numVNets; i++) { delayVCHistogram[i]->add(ctr->getDelayVCHist(i)); } } diff --git a/src/mem/ruby/profiler/Profiler.hh b/src/mem/ruby/profiler/Profiler.hh index 6cfdab1d5..146beadd6 100644 --- a/src/mem/ruby/profiler/Profiler.hh +++ b/src/mem/ruby/profiler/Profiler.hh @@ -80,8 +80,8 @@ class Profiler void addAddressTraceSample(const RubyRequest& msg, NodeID id); // added by SS - bool getHotLines() const { return m_hot_lines; } - bool getAllInstructions() const { return m_all_instructions; } + bool getHotLines() { return m_hot_lines; } + bool getAllInstructions() { return m_all_instructions; } private: // Private copy constructor and assignment operator @@ -129,9 +129,8 @@ class Profiler Stats::Scalar m_IncompleteTimes[MachineType_NUM]; //added by SS - const bool m_hot_lines; - const bool m_all_instructions; - const uint32_t m_num_vnets; + bool m_hot_lines; + bool m_all_instructions; }; #endif // __MEM_RUBY_PROFILER_PROFILER_HH__ diff --git a/src/mem/ruby/profiler/StoreTrace.cc b/src/mem/ruby/profiler/StoreTrace.cc index c3c1f8a19..40bf2e7b6 100644 --- a/src/mem/ruby/profiler/StoreTrace.cc +++ b/src/mem/ruby/profiler/StoreTrace.cc @@ -33,7 +33,7 @@ using namespace std; bool StoreTrace::s_init = false; // Total number of store lifetimes of // all lines -int64_t StoreTrace::s_total_samples = 0; // Total number of store +int64 StoreTrace::s_total_samples = 0; // Total number of store // lifetimes of all lines Histogram* StoreTrace::s_store_count_ptr = NULL; Histogram* StoreTrace::s_store_first_to_stolen_ptr = NULL; diff --git a/src/mem/ruby/profiler/StoreTrace.hh b/src/mem/ruby/profiler/StoreTrace.hh index a686594f8..9c1b83cd6 100644 --- a/src/mem/ruby/profiler/StoreTrace.hh +++ b/src/mem/ruby/profiler/StoreTrace.hh @@ -53,7 +53,7 @@ class StoreTrace private: static bool s_init; - static int64_t s_total_samples; // Total number of store lifetimes + static int64 s_total_samples; // Total number of store lifetimes // of all lines static Histogram* s_store_count_ptr; static Histogram* s_store_first_to_stolen_ptr; @@ -66,7 +66,7 @@ class StoreTrace Tick m_last_store; int m_stores_this_interval; - int64_t m_total_samples; // Total number of store lifetimes of this line + int64 m_total_samples; // Total number of store lifetimes of this line Histogram m_store_count; Histogram m_store_first_to_stolen; Histogram m_store_last_to_stolen; diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc index 416aea73b..01fd3f522 100644 --- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc +++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.cc @@ -28,9 +28,6 @@ #include "mem/ruby/slicc_interface/AbstractCacheEntry.hh" -#include "base/trace.hh" -#include "debug/RubyCache.hh" - AbstractCacheEntry::AbstractCacheEntry() { m_Permission = AccessPermission_NotPresent; @@ -51,25 +48,3 @@ AbstractCacheEntry::changePermission(AccessPermission new_perm) m_locked = -1; } } - -void -AbstractCacheEntry::setLocked(int context) -{ - DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", m_Address, context); - m_locked = context; -} - -void -AbstractCacheEntry::clearLocked() -{ - DPRINTF(RubyCache, "Clear Lock for addr: %x\n", m_Address); - m_locked = -1; -} - -bool -AbstractCacheEntry::isLocked(int context) const -{ - DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", - m_Address, m_locked, context); - return m_locked == context; -} diff --git a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh index 926556781..6c7a4a008 100644 --- a/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh +++ b/src/mem/ruby/slicc_interface/AbstractCacheEntry.hh @@ -56,28 +56,10 @@ class AbstractCacheEntry : public AbstractEntry virtual DataBlock& getDataBlk() { panic("getDataBlk() not implemented!"); } - // Functions for locking and unlocking the cache entry. These are required - // for supporting atomic memory accesses. - void setLocked(int context); - void clearLocked(); - bool isLocked(int context) const; - void setSetIndex(uint32_t s) { m_set_index = s; } - uint32_t getSetIndex() const { return m_set_index; } - - void setWayIndex(uint32_t s) { m_way_index = s; } - uint32_t getWayIndex() const { return m_way_index; } - - // Address of this block, required by CacheMemory - Addr m_Address; - // Holds info whether the address is locked. - // Required for implementing LL/SC operations. - int m_locked; - - private: - // Set and way coordinates of the entry within the cache memory object. - uint32_t m_set_index; - uint32_t m_way_index; + Addr m_Address; // Address of this block, required by CacheMemory + int m_locked; // Holds info whether the address is locked, + // required for implementing LL/SC }; inline std::ostream& diff --git a/src/mem/ruby/slicc_interface/AbstractController.hh b/src/mem/ruby/slicc_interface/AbstractController.hh index 34160c149..94361034a 100644 --- a/src/mem/ruby/slicc_interface/AbstractController.hh +++ b/src/mem/ruby/slicc_interface/AbstractController.hh @@ -139,14 +139,14 @@ class AbstractController : public MemObject, public Consumer void wakeUpAllBuffers(); protected: - const NodeID m_version; + NodeID m_version; MachineID m_machineID; - const NodeID m_clusterID; + NodeID m_clusterID; // MasterID used by some components of gem5. - const MasterID m_masterId; + MasterID m_masterId; - Network *m_net_ptr; + Network* m_net_ptr; bool m_is_blocking; std::map<Addr, MessageBuffer*> m_block_map; @@ -157,9 +157,9 @@ class AbstractController : public MemObject, public Consumer unsigned int m_in_ports; unsigned int m_cur_in_port; - const int m_number_of_TBEs; - const int m_transitions_per_cycle; - const unsigned int m_buffer_size; + int m_number_of_TBEs; + int m_transitions_per_cycle; + unsigned int m_buffer_size; Cycles m_recycle_latency; //! Counter for the number of cycles when the transitions carried out diff --git a/src/mem/ruby/structures/AbstractReplacementPolicy.cc b/src/mem/ruby/structures/AbstractReplacementPolicy.cc index d802ecd31..fbcce6e2d 100644 --- a/src/mem/ruby/structures/AbstractReplacementPolicy.cc +++ b/src/mem/ruby/structures/AbstractReplacementPolicy.cc @@ -66,7 +66,7 @@ AbstractReplacementPolicy::~AbstractReplacementPolicy() } Tick -AbstractReplacementPolicy::getLastAccess(int64_t set, int64_t way) +AbstractReplacementPolicy::getLastAccess(int64 set, int64 way) { return m_last_ref_ptr[set][way]; } diff --git a/src/mem/ruby/structures/AbstractReplacementPolicy.hh b/src/mem/ruby/structures/AbstractReplacementPolicy.hh index c118f3c11..03ef0d2fd 100644 --- a/src/mem/ruby/structures/AbstractReplacementPolicy.hh +++ b/src/mem/ruby/structures/AbstractReplacementPolicy.hh @@ -44,13 +44,13 @@ class AbstractReplacementPolicy : public SimObject virtual ~AbstractReplacementPolicy(); /* touch a block. a.k.a. update timestamp */ - virtual void touch(int64_t set, int64_t way, Tick time) = 0; + virtual void touch(int64 set, int64 way, Tick time) = 0; /* returns the way to replace */ - virtual int64_t getVictim(int64_t set) const = 0; + virtual int64 getVictim(int64 set) const = 0; /* get the time of the last access */ - Tick getLastAccess(int64_t set, int64_t way); + Tick getLastAccess(int64 set, int64 way); virtual bool useOccupancy() const { return false; } diff --git a/src/mem/ruby/structures/BankedArray.cc b/src/mem/ruby/structures/BankedArray.cc index b25962df6..8bc3cf584 100644 --- a/src/mem/ruby/structures/BankedArray.cc +++ b/src/mem/ruby/structures/BankedArray.cc @@ -49,7 +49,7 @@ BankedArray::BankedArray(unsigned int banks, Cycles accessLatency, } bool -BankedArray::tryAccess(int64_t idx) +BankedArray::tryAccess(int64 idx) { if (accessLatency == 0) return true; @@ -65,7 +65,7 @@ BankedArray::tryAccess(int64_t idx) } void -BankedArray::reserve(int64_t idx) +BankedArray::reserve(int64 idx) { if (accessLatency == 0) return; @@ -91,7 +91,7 @@ BankedArray::reserve(int64_t idx) } unsigned int -BankedArray::mapIndexToBank(int64_t idx) +BankedArray::mapIndexToBank(int64 idx) { if (banks == 1) { return 0; diff --git a/src/mem/ruby/structures/BankedArray.hh b/src/mem/ruby/structures/BankedArray.hh index 179676f19..438186944 100644 --- a/src/mem/ruby/structures/BankedArray.hh +++ b/src/mem/ruby/structures/BankedArray.hh @@ -51,7 +51,7 @@ class BankedArray { public: AccessRecord() : idx(0), startAccess(0), endAccess(0) {} - int64_t idx; + int64 idx; Tick startAccess; Tick endAccess; }; @@ -60,7 +60,7 @@ class BankedArray // otherwise, schedule the event and wait for it to complete std::vector<AccessRecord> busyBanks; - unsigned int mapIndexToBank(int64_t idx); + unsigned int mapIndexToBank(int64 idx); public: BankedArray(unsigned int banks, Cycles accessLatency, @@ -68,9 +68,9 @@ class BankedArray // Note: We try the access based on the cache index, not the address // This is so we don't get aliasing on blocks being replaced - bool tryAccess(int64_t idx); + bool tryAccess(int64 idx); - void reserve(int64_t idx); + void reserve(int64 idx); Cycles getLatency() const { return accessLatency; } }; diff --git a/src/mem/ruby/structures/CacheMemory.cc b/src/mem/ruby/structures/CacheMemory.cc index ac6f823ce..7eba450c1 100644 --- a/src/mem/ruby/structures/CacheMemory.cc +++ b/src/mem/ruby/structures/CacheMemory.cc @@ -98,7 +98,7 @@ CacheMemory::~CacheMemory() } // convert a Address to its location in the cache -int64_t +int64 CacheMemory::addressToCacheSet(Addr address) const { assert(address == makeLineAddress(address)); @@ -109,7 +109,7 @@ CacheMemory::addressToCacheSet(Addr address) const // Given a cache index: returns the index of the tag in a set. // returns -1 if the tag is not found. int -CacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const +CacheMemory::findTagInSet(int64 cacheSet, Addr tag) const { assert(tag == makeLineAddress(tag)); // search the set for the tags @@ -124,7 +124,7 @@ CacheMemory::findTagInSet(int64_t cacheSet, Addr tag) const // Given a cache index: returns the index of the tag in a set. // returns -1 if the tag is not found. int -CacheMemory::findTagInSetIgnorePermissions(int64_t cacheSet, +CacheMemory::findTagInSetIgnorePermissions(int64 cacheSet, Addr tag) const { assert(tag == makeLineAddress(tag)); @@ -158,12 +158,62 @@ CacheMemory::getAddressAtIdx(int idx) const return entry->m_Address; } +bool +CacheMemory::tryCacheAccess(Addr address, RubyRequestType type, + DataBlock*& data_ptr) +{ + assert(address == makeLineAddress(address)); + DPRINTF(RubyCache, "address: %s\n", address); + int64 cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + if (loc != -1) { + // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + data_ptr = &(entry->getDataBlk()); + + if (entry->m_Permission == AccessPermission_Read_Write) { + return true; + } + if ((entry->m_Permission == AccessPermission_Read_Only) && + (type == RubyRequestType_LD || type == RubyRequestType_IFETCH)) { + return true; + } + // The line must not be accessible + } + data_ptr = NULL; + return false; +} + +bool +CacheMemory::testCacheAccess(Addr address, RubyRequestType type, + DataBlock*& data_ptr) +{ + assert(address == makeLineAddress(address)); + DPRINTF(RubyCache, "address: %s\n", address); + int64 cacheSet = addressToCacheSet(address); + int loc = findTagInSet(cacheSet, address); + + if (loc != -1) { + // Do we even have a tag match? + AbstractCacheEntry* entry = m_cache[cacheSet][loc]; + m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); + data_ptr = &(entry->getDataBlk()); + + return m_cache[cacheSet][loc]->m_Permission != + AccessPermission_NotPresent; + } + + data_ptr = NULL; + return false; +} + // tests to see if an address is present in the cache bool CacheMemory::isTagPresent(Addr address) const { assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if (loc == -1) { @@ -183,7 +233,7 @@ CacheMemory::cacheAvail(Addr address) const { assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); for (int i = 0; i < m_cache_assoc; i++) { AbstractCacheEntry* entry = m_cache[cacheSet][i]; @@ -201,7 +251,7 @@ CacheMemory::cacheAvail(Addr address) const } AbstractCacheEntry* -CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) +CacheMemory::allocate(Addr address, AbstractCacheEntry* entry, bool touch) { assert(address == makeLineAddress(address)); assert(!isTagPresent(address)); @@ -209,7 +259,7 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) DPRINTF(RubyCache, "address: %s\n", address); // Find the first open slot - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); std::vector<AbstractCacheEntry*> &set = m_cache[cacheSet]; for (int i = 0; i < m_cache_assoc; i++) { if (!set[i] || set[i]->m_Permission == AccessPermission_NotPresent) { @@ -220,8 +270,6 @@ CacheMemory::allocate(Addr address, AbstractCacheEntry *entry, bool touch) address); set[i]->m_locked = -1; m_tag_index[address] = i; - entry->setSetIndex(cacheSet); - entry->setWayIndex(i); if (touch) { m_replacementPolicy_ptr->touch(cacheSet, i, curTick()); @@ -239,7 +287,7 @@ CacheMemory::deallocate(Addr address) assert(address == makeLineAddress(address)); assert(isTagPresent(address)); DPRINTF(RubyCache, "address: %s\n", address); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if (loc != -1) { delete m_cache[cacheSet][loc]; @@ -255,7 +303,7 @@ CacheMemory::cacheProbe(Addr address) const assert(address == makeLineAddress(address)); assert(!cacheAvail(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); return m_cache[cacheSet][m_replacementPolicy_ptr->getVictim(cacheSet)]-> m_Address; } @@ -265,7 +313,7 @@ AbstractCacheEntry* CacheMemory::lookup(Addr address) { assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if(loc == -1) return NULL; return m_cache[cacheSet][loc]; @@ -276,7 +324,7 @@ const AbstractCacheEntry* CacheMemory::lookup(Addr address) const { assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if(loc == -1) return NULL; return m_cache[cacheSet][loc]; @@ -286,7 +334,7 @@ CacheMemory::lookup(Addr address) const void CacheMemory::setMRU(Addr address) { - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); if(loc != -1) @@ -294,19 +342,11 @@ CacheMemory::setMRU(Addr address) } void -CacheMemory::setMRU(const AbstractCacheEntry *e) -{ - uint32_t cacheSet = e->getSetIndex(); - uint32_t loc = e->getWayIndex(); - m_replacementPolicy_ptr->touch(cacheSet, loc, curTick()); -} - -void CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const { - uint64_t warmedUpBlocks = 0; - uint64_t totalBlocks M5_VAR_USED = (uint64_t)m_cache_num_sets * - (uint64_t)m_cache_assoc; + uint64 warmedUpBlocks = 0; + uint64 totalBlocks M5_VAR_USED = (uint64)m_cache_num_sets + * (uint64)m_cache_assoc; for (int i = 0; i < m_cache_num_sets; i++) { for (int j = 0; j < m_cache_assoc; j++) { @@ -336,7 +376,8 @@ CacheMemory::recordCacheContents(int cntrl, CacheRecorder* tr) const DPRINTF(RubyCacheTrace, "%s: %lli blocks of %lli total blocks" "recorded %.2f%% \n", name().c_str(), warmedUpBlocks, - totalBlocks, (float(warmedUpBlocks) / float(totalBlocks)) * 100.0); + (uint64)m_cache_num_sets * (uint64)m_cache_assoc, + (float(warmedUpBlocks)/float(totalBlocks))*100.0); } void @@ -369,10 +410,10 @@ CacheMemory::setLocked(Addr address, int context) { DPRINTF(RubyCache, "Setting Lock for addr: %x to %d\n", address, context); assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); assert(loc != -1); - m_cache[cacheSet][loc]->setLocked(context); + m_cache[cacheSet][loc]->m_locked = context; } void @@ -380,22 +421,22 @@ CacheMemory::clearLocked(Addr address) { DPRINTF(RubyCache, "Clear Lock for addr: %x\n", address); assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); assert(loc != -1); - m_cache[cacheSet][loc]->clearLocked(); + m_cache[cacheSet][loc]->m_locked = -1; } bool CacheMemory::isLocked(Addr address, int context) { assert(address == makeLineAddress(address)); - int64_t cacheSet = addressToCacheSet(address); + int64 cacheSet = addressToCacheSet(address); int loc = findTagInSet(cacheSet, address); assert(loc != -1); DPRINTF(RubyCache, "Testing Lock for addr: %llx cur %d con %d\n", address, m_cache[cacheSet][loc]->m_locked, context); - return m_cache[cacheSet][loc]->isLocked(context); + return m_cache[cacheSet][loc]->m_locked == context; } void @@ -553,13 +594,13 @@ CacheMemory::checkResourceAvailable(CacheResourceType res, Addr addr) } bool -CacheMemory::isBlockInvalid(int64_t cache_set, int64_t loc) +CacheMemory::isBlockInvalid(int64 cache_set, int64 loc) { return (m_cache[cache_set][loc]->m_Permission == AccessPermission_Invalid); } bool -CacheMemory::isBlockNotBusy(int64_t cache_set, int64_t loc) +CacheMemory::isBlockNotBusy(int64 cache_set, int64 loc) { return (m_cache[cache_set][loc]->m_Permission != AccessPermission_Busy); } diff --git a/src/mem/ruby/structures/CacheMemory.hh b/src/mem/ruby/structures/CacheMemory.hh index 94174b286..08551ab87 100644 --- a/src/mem/ruby/structures/CacheMemory.hh +++ b/src/mem/ruby/structures/CacheMemory.hh @@ -56,6 +56,15 @@ class CacheMemory : public SimObject void init(); + // Public Methods + // perform a cache access and see if we hit or not. Return true on a hit. + bool tryCacheAccess(Addr address, RubyRequestType type, + DataBlock*& data_ptr); + + // similar to above, but doesn't require full access check + bool testCacheAccess(Addr address, RubyRequestType type, + DataBlock*& data_ptr); + // tests to see if an address is present in the cache bool isTagPresent(Addr address) const; @@ -89,22 +98,15 @@ class CacheMemory : public SimObject Cycles getTagLatency() const { return tagArray.getLatency(); } Cycles getDataLatency() const { return dataArray.getLatency(); } - bool isBlockInvalid(int64_t cache_set, int64_t loc); - bool isBlockNotBusy(int64_t cache_set, int64_t loc); + bool isBlockInvalid(int64 cache_set, int64 loc); + bool isBlockNotBusy(int64 cache_set, int64 loc); // Hook for checkpointing the contents of the cache void recordCacheContents(int cntrl, CacheRecorder* tr) const; // Set this address to most recently used void setMRU(Addr address); - // Set this entry to most recently used - void setMRU(const AbstractCacheEntry *e); - - // Functions for locking and unlocking cache lines corresponding to the - // provided address. These are required for supporting atomic memory - // accesses. These are to be used when only the address of the cache entry - // is available. In case the entry itself is available. use the functions - // provided by the AbstractCacheEntry class. + void setLocked (Addr addr, int context); void clearLocked (Addr addr); bool isLocked (Addr addr, int context); @@ -142,12 +144,12 @@ class CacheMemory : public SimObject private: // convert a Address to its location in the cache - int64_t addressToCacheSet(Addr address) const; + int64 addressToCacheSet(Addr address) const; // Given a cache tag: returns the index of the tag in a set. // returns -1 if the tag is not found. - int findTagInSet(int64_t line, Addr tag) const; - int findTagInSetIgnorePermissions(int64_t cacheSet, Addr tag) const; + int findTagInSet(int64 line, Addr tag) const; + int findTagInSetIgnorePermissions(int64 cacheSet, Addr tag) const; // Private copy constructor and assignment operator CacheMemory(const CacheMemory& obj); diff --git a/src/mem/ruby/structures/DirectoryMemory.cc b/src/mem/ruby/structures/DirectoryMemory.cc index 82388a895..b840349e1 100644 --- a/src/mem/ruby/structures/DirectoryMemory.cc +++ b/src/mem/ruby/structures/DirectoryMemory.cc @@ -37,6 +37,7 @@ using namespace std; int DirectoryMemory::m_num_directories = 0; int DirectoryMemory::m_num_directories_bits = 0; +uint64_t DirectoryMemory::m_total_size_bytes = 0; int DirectoryMemory::m_numa_high_bit = 0; DirectoryMemory::DirectoryMemory(const Params *p) @@ -59,6 +60,7 @@ DirectoryMemory::init() m_num_directories++; m_num_directories_bits = ceilLog2(m_num_directories); + m_total_size_bytes += m_size_bytes; if (m_numa_high_bit == 0) { m_numa_high_bit = RubySystem::getMemorySizeBits() - 1; diff --git a/src/mem/ruby/structures/DirectoryMemory.hh b/src/mem/ruby/structures/DirectoryMemory.hh index 98403808b..a549366d0 100644 --- a/src/mem/ruby/structures/DirectoryMemory.hh +++ b/src/mem/ruby/structures/DirectoryMemory.hh @@ -76,6 +76,7 @@ class DirectoryMemory : public SimObject static int m_num_directories; static int m_num_directories_bits; + static uint64_t m_total_size_bytes; static int m_numa_high_bit; }; diff --git a/src/mem/ruby/structures/LRUPolicy.cc b/src/mem/ruby/structures/LRUPolicy.cc index 286d19772..a1e3b277e 100644 --- a/src/mem/ruby/structures/LRUPolicy.cc +++ b/src/mem/ruby/structures/LRUPolicy.cc @@ -50,7 +50,7 @@ LRUReplacementPolicyParams::create() void -LRUPolicy::touch(int64_t set, int64_t index, Tick time) +LRUPolicy::touch(int64 set, int64 index, Tick time) { assert(index >= 0 && index < m_assoc); assert(set >= 0 && set < m_num_sets); @@ -58,11 +58,11 @@ LRUPolicy::touch(int64_t set, int64_t index, Tick time) m_last_ref_ptr[set][index] = time; } -int64_t -LRUPolicy::getVictim(int64_t set) const +int64 +LRUPolicy::getVictim(int64 set) const { Tick time, smallest_time; - int64_t smallest_index; + int64 smallest_index; smallest_index = 0; smallest_time = m_last_ref_ptr[set][0]; diff --git a/src/mem/ruby/structures/LRUPolicy.hh b/src/mem/ruby/structures/LRUPolicy.hh index 388718319..9a9c9e3eb 100644 --- a/src/mem/ruby/structures/LRUPolicy.hh +++ b/src/mem/ruby/structures/LRUPolicy.hh @@ -41,8 +41,8 @@ class LRUPolicy : public AbstractReplacementPolicy LRUPolicy(const Params * p); ~LRUPolicy(); - void touch(int64_t set, int64_t way, Tick time); - int64_t getVictim(int64_t set) const; + void touch(int64 set, int64 way, Tick time); + int64 getVictim(int64 set) const; }; #endif // __MEM_RUBY_STRUCTURES_LRUPOLICY_HH__ diff --git a/src/mem/ruby/structures/PseudoLRUPolicy.cc b/src/mem/ruby/structures/PseudoLRUPolicy.cc index a2b21a625..8eee0821b 100644 --- a/src/mem/ruby/structures/PseudoLRUPolicy.cc +++ b/src/mem/ruby/structures/PseudoLRUPolicy.cc @@ -38,7 +38,7 @@ PseudoLRUPolicy::PseudoLRUPolicy(const Params * p) // associativity cannot exceed capacity of tree representation assert(m_num_sets > 0 && m_assoc > 1 && - m_assoc <= (int64_t) sizeof(uint64_t)*4); + m_assoc <= (int64) sizeof(uint64)*4); m_trees = NULL; m_num_levels = 0; @@ -55,7 +55,7 @@ PseudoLRUPolicy::PseudoLRUPolicy(const Params * p) m_num_levels++; } assert(m_num_levels < sizeof(unsigned int)*4); - m_trees = new uint64_t[m_num_sets]; + m_trees = new uint64[m_num_sets]; for (unsigned i = 0; i < m_num_sets; i++) { m_trees[i] = 0; } @@ -75,7 +75,7 @@ PseudoLRUPolicy::~PseudoLRUPolicy() } void -PseudoLRUPolicy::touch(int64_t set, int64_t index, Tick time) +PseudoLRUPolicy::touch(int64 set, int64 index, Tick time) { assert(index >= 0 && index < m_assoc); assert(set >= 0 && set < m_num_sets); @@ -93,10 +93,10 @@ PseudoLRUPolicy::touch(int64_t set, int64_t index, Tick time) m_last_ref_ptr[set][index] = time; } -int64_t -PseudoLRUPolicy::getVictim(int64_t set) const +int64 +PseudoLRUPolicy::getVictim(int64 set) const { - int64_t index = 0; + int64 index = 0; int tree_index = 0; int node_val; diff --git a/src/mem/ruby/structures/PseudoLRUPolicy.hh b/src/mem/ruby/structures/PseudoLRUPolicy.hh index a4a388cf5..fc5add8b1 100644 --- a/src/mem/ruby/structures/PseudoLRUPolicy.hh +++ b/src/mem/ruby/structures/PseudoLRUPolicy.hh @@ -53,13 +53,13 @@ class PseudoLRUPolicy : public AbstractReplacementPolicy PseudoLRUPolicy(const Params * p); ~PseudoLRUPolicy(); - void touch(int64_t set, int64_t way, Tick time); - int64_t getVictim(int64_t set) const; + void touch(int64 set, int64 way, Tick time); + int64 getVictim(int64 set) const; private: unsigned int m_effective_assoc; /** nearest (to ceiling) power of 2 */ unsigned int m_num_levels; /** number of levels in the tree */ - uint64_t *m_trees; /** bit representation of the + uint64* m_trees; /** bit representation of the * trees, one for each set */ }; diff --git a/src/mem/ruby/structures/RubyMemoryControl.cc b/src/mem/ruby/structures/RubyMemoryControl.cc index 413850627..0521aac06 100644 --- a/src/mem/ruby/structures/RubyMemoryControl.cc +++ b/src/mem/ruby/structures/RubyMemoryControl.cc @@ -176,7 +176,7 @@ void RubyMemoryControl::init() { m_msg_counter = 0; - assert(m_tFaw <= 62); // must fit in a uint64_t shift register + assert(m_tFaw <= 62); // must fit in a uint64 shift register m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel; m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel; @@ -213,7 +213,7 @@ RubyMemoryControl::init() // m_tfaw_count keeps track of how many 1 bits are set // in each shift register. When m_tfaw_count is >= 4, // new activates are not allowed. - m_tfaw_shift = new uint64_t[m_total_ranks]; + m_tfaw_shift = new uint64[m_total_ranks]; m_tfaw_count = new int[m_total_ranks]; for (int i = 0; i < m_total_ranks; i++) { m_tfaw_shift[i] = 0; @@ -236,7 +236,7 @@ RubyMemoryControl::reset() { m_msg_counter = 0; - assert(m_tFaw <= 62); // must fit in a uint64_t shift register + assert(m_tFaw <= 62); // must fit in a uint64 shift register m_total_banks = m_banks_per_rank * m_ranks_per_dimm * m_dimms_per_channel; m_total_ranks = m_ranks_per_dimm * m_dimms_per_channel; diff --git a/src/mem/ruby/structures/RubyMemoryControl.hh b/src/mem/ruby/structures/RubyMemoryControl.hh index 376ce4d75..c68a2da6c 100644 --- a/src/mem/ruby/structures/RubyMemoryControl.hh +++ b/src/mem/ruby/structures/RubyMemoryControl.hh @@ -162,11 +162,11 @@ class RubyMemoryControl : public AbstractMemory, public Consumer // Each entry indicates number of address-bus cycles until bank // is reschedulable: - int *m_bankBusyCounter; - int *m_oldRequest; + int* m_bankBusyCounter; + int* m_oldRequest; - uint64_t *m_tfaw_shift; - int *m_tfaw_count; + uint64* m_tfaw_shift; + int* m_tfaw_count; // Each of these indicates number of address-bus cycles until // we can issue a new request of the corresponding type: @@ -182,12 +182,12 @@ class RubyMemoryControl : public AbstractMemory, public Consumer int m_ageCounter; // age of old requests; to detect starvation int m_idleCount; // watchdog timer for shutting down - MemCntrlProfiler *m_profiler_ptr; + MemCntrlProfiler* m_profiler_ptr; class MemCntrlEvent : public Event { public: - MemCntrlEvent(RubyMemoryControl *_mem_cntrl) + MemCntrlEvent(RubyMemoryControl* _mem_cntrl) { mem_cntrl = _mem_cntrl; } diff --git a/src/mem/ruby/system/CacheRecorder.cc b/src/mem/ruby/system/CacheRecorder.cc index 9568d6a88..a2ac6bdf8 100644 --- a/src/mem/ruby/system/CacheRecorder.cc +++ b/src/mem/ruby/system/CacheRecorder.cc @@ -58,6 +58,15 @@ CacheRecorder::CacheRecorder(uint8_t* uncompressed_trace, m_seq_map(seq_map), m_bytes_read(0), m_records_read(0), m_records_flushed(0), m_block_size_bytes(block_size_bytes) { + if (m_uncompressed_trace != NULL) { + if (m_block_size_bytes < RubySystem::getBlockSizeBytes()) { + // Block sizes larger than when the trace was recorded are not + // supported, as we cannot reliably turn accesses to smaller blocks + // into larger ones. + panic("Recorded cache block size (%d) < current block size (%d) !!", + m_block_size_bytes, RubySystem::getBlockSizeBytes()); + } + } } CacheRecorder::~CacheRecorder() @@ -152,13 +161,13 @@ CacheRecorder::addRecord(int cntrl, Addr data_addr, Addr pc_addr, m_records.push_back(rec); } -uint64_t -CacheRecorder::aggregateRecords(uint8_t **buf, uint64_t total_size) +uint64 +CacheRecorder::aggregateRecords(uint8_t** buf, uint64 total_size) { std::sort(m_records.begin(), m_records.end(), compareTraceRecords); int size = m_records.size(); - uint64_t current_size = 0; + uint64 current_size = 0; int record_size = sizeof(TraceRecord) + m_block_size_bytes; for (int i = 0; i < size; ++i) { diff --git a/src/mem/ruby/system/CacheRecorder.hh b/src/mem/ruby/system/CacheRecorder.hh index 44110cf9f..a4a7261f4 100644 --- a/src/mem/ruby/system/CacheRecorder.hh +++ b/src/mem/ruby/system/CacheRecorder.hh @@ -77,7 +77,7 @@ class CacheRecorder void addRecord(int cntrl, Addr data_addr, Addr pc_addr, RubyRequestType type, Tick time, DataBlock& data); - uint64_t aggregateRecords(uint8_t **data, uint64_t size); + uint64 aggregateRecords(uint8_t** data, uint64 size); /*! * Function for flushing the memory contents of the caches to the diff --git a/src/mem/ruby/system/RubySystem.py b/src/mem/ruby/system/RubySystem.py index 9ffaa5702..81a9a181b 100644 --- a/src/mem/ruby/system/RubySystem.py +++ b/src/mem/ruby/system/RubySystem.py @@ -34,6 +34,7 @@ from SimpleMemory import * class RubySystem(ClockedObject): type = 'RubySystem' cxx_header = "mem/ruby/system/System.hh" + random_seed = Param.Int(1234, "random seed used by the simulation"); randomization = Param.Bool(False, "insert random delays on message enqueue times"); block_size_bytes = Param.UInt32(64, @@ -41,13 +42,11 @@ class RubySystem(ClockedObject): memory_size_bits = Param.UInt32(64, "number of bits that a memory address requires"); - phys_mem = Param.SimpleMemory(NULL, "") - - access_backing_store = Param.Bool(False, "Use phys_mem as the functional \ - store and only use ruby for timing.") - # Profiler related configuration variables hot_lines = Param.Bool(False, "") all_instructions = Param.Bool(False, "") num_of_sequencers = Param.Int("") - number_of_virtual_networks = Param.Unsigned("") + phys_mem = Param.SimpleMemory(NULL, "") + + access_backing_store = Param.Bool(False, "Use phys_mem as the functional \ + store and only use ruby for timing.") diff --git a/src/mem/ruby/system/Sequencer.cc b/src/mem/ruby/system/Sequencer.cc index 740db7d8d..305758798 100644 --- a/src/mem/ruby/system/Sequencer.cc +++ b/src/mem/ruby/system/Sequencer.cc @@ -317,27 +317,28 @@ Sequencer::removeRequest(SequencerRequest* srequest) void Sequencer::invalidateSC(Addr address) { - AbstractCacheEntry *e = m_dataCache_ptr->lookup(address); - // The controller has lost the coherence permissions, hence the lock - // on the cache line maintained by the cache should be cleared. - if (e && e->isLocked(m_version)) { - e->clearLocked(); + RequestTable::iterator i = m_writeRequestTable.find(address); + if (i != m_writeRequestTable.end()) { + SequencerRequest* request = i->second; + // The controller has lost the coherence permissions, hence the lock + // on the cache line maintained by the cache should be cleared. + if (request->m_type == RubyRequestType_Store_Conditional) { + m_dataCache_ptr->clearLocked(address); + } } } bool Sequencer::handleLlsc(Addr address, SequencerRequest* request) { - AbstractCacheEntry *e = m_dataCache_ptr->lookup(address); - if (!e) - return true; - + // // The success flag indicates whether the LLSC operation was successful. // LL ops will always succeed, but SC may fail if the cache line is no // longer locked. + // bool success = true; if (request->m_type == RubyRequestType_Store_Conditional) { - if (!e->isLocked(m_version)) { + if (!m_dataCache_ptr->isLocked(address, m_version)) { // // For failed SC requests, indicate the failure to the cpu by // setting the extra data to zero. @@ -354,18 +355,19 @@ Sequencer::handleLlsc(Addr address, SequencerRequest* request) // // Independent of success, all SC operations must clear the lock // - e->clearLocked(); + m_dataCache_ptr->clearLocked(address); } else if (request->m_type == RubyRequestType_Load_Linked) { // // Note: To fully follow Alpha LLSC semantics, should the LL clear any // previously locked cache lines? // - e->setLocked(m_version); - } else if (e->isLocked(m_version)) { + m_dataCache_ptr->setLocked(address, m_version); + } else if ((m_dataCache_ptr->isTagPresent(address)) && + (m_dataCache_ptr->isLocked(address, m_version))) { // // Normal writes should clear the locked address // - e->clearLocked(); + m_dataCache_ptr->clearLocked(address); } return success; } @@ -496,15 +498,19 @@ Sequencer::hitCallback(SequencerRequest* srequest, DataBlock& data, const Cycles forwardRequestTime, const Cycles firstResponseTime) { - warn_once("Replacement policy updates recently became the responsibility " - "of SLICC state machines. Make sure to setMRU() near callbacks " - "in .sm files!"); - PacketPtr pkt = srequest->pkt; Addr request_address(pkt->getAddr()); + Addr request_line_address = makeLineAddress(pkt->getAddr()); RubyRequestType type = srequest->m_type; Cycles issued_time = srequest->issue_time; + // Set this cache entry to the most recently used + if (type == RubyRequestType_IFETCH) { + m_instCache_ptr->setMRU(request_line_address); + } else { + m_dataCache_ptr->setMRU(request_line_address); + } + assert(curCycle() >= issued_time); Cycles total_latency = curCycle() - issued_time; diff --git a/src/mem/ruby/system/System.cc b/src/mem/ruby/system/System.cc index cb485a47b..c00082010 100644 --- a/src/mem/ruby/system/System.cc +++ b/src/mem/ruby/system/System.cc @@ -45,6 +45,7 @@ using namespace std; +int RubySystem::m_random_seed; bool RubySystem::m_randomization; uint32_t RubySystem::m_block_size_bytes; uint32_t RubySystem::m_block_size_bits; @@ -59,6 +60,8 @@ RubySystem::RubySystem(const Params *p) : ClockedObject(p), m_access_backing_store(p->access_backing_store), m_cache_recorder(NULL) { + m_random_seed = p->random_seed; + srandom(m_random_seed); m_randomization = p->randomization; m_block_size_bytes = p->block_size_bytes; @@ -99,8 +102,8 @@ RubySystem::~RubySystem() void RubySystem::makeCacheRecorder(uint8_t *uncompressed_trace, - uint64_t cache_trace_size, - uint64_t block_size_bytes) + uint64 cache_trace_size, + uint64 block_size_bytes) { vector<Sequencer*> sequencer_map; Sequencer* sequencer_ptr = NULL; @@ -204,7 +207,7 @@ RubySystem::memWriteback() void RubySystem::writeCompressedTrace(uint8_t *raw_data, string filename, - uint64_t uncompressed_trace_size) + uint64 uncompressed_trace_size) { // Create the checkpoint file for the memory string thefile = CheckpointIn::dir() + "/" + filename.c_str(); @@ -237,7 +240,7 @@ RubySystem::serializeOld(CheckpointOut &cp) // Store the cache-block size, so we are able to restore on systems with a // different cache-block size. CacheRecorder depends on the correct // cache-block size upon unserializing. - uint64_t block_size_bytes = getBlockSizeBytes(); + uint64 block_size_bytes = getBlockSizeBytes(); SERIALIZE_SCALAR(block_size_bytes); // Check that there's a valid trace to use. If not, then memory won't be @@ -249,7 +252,7 @@ RubySystem::serializeOld(CheckpointOut &cp) // Aggregate the trace entries together into a single array uint8_t *raw_data = new uint8_t[4096]; - uint64_t cache_trace_size = m_cache_recorder->aggregateRecords(&raw_data, + uint64 cache_trace_size = m_cache_recorder->aggregateRecords(&raw_data, 4096); string cache_trace_file = name() + ".cache.gz"; writeCompressedTrace(raw_data, cache_trace_file, cache_trace_size); @@ -264,7 +267,7 @@ RubySystem::serializeOld(CheckpointOut &cp) void RubySystem::readCompressedTrace(string filename, uint8_t *&raw_data, - uint64_t &uncompressed_trace_size) + uint64& uncompressed_trace_size) { // Read the trace file gzFile compressedTrace; @@ -301,19 +304,11 @@ RubySystem::unserialize(CheckpointIn &cp) // This value should be set to the checkpoint-system's block-size. // Optional, as checkpoints without it can be run if the // checkpoint-system's block-size == current block-size. - uint64_t block_size_bytes = m_block_size_bytes; + uint64 block_size_bytes = getBlockSizeBytes(); UNSERIALIZE_OPT_SCALAR(block_size_bytes); - if (block_size_bytes < m_block_size_bytes) { - // Block sizes larger than when the trace was recorded are not - // supported, as we cannot reliably turn accesses to smaller blocks - // into larger ones. - panic("Recorded cache block size (%d) < current block size (%d) !!", - block_size_bytes, m_block_size_bytes); - } - string cache_trace_file; - uint64_t cache_trace_size = 0; + uint64 cache_trace_size = 0; UNSERIALIZE_SCALAR(cache_trace_file); UNSERIALIZE_SCALAR(cache_trace_size); diff --git a/src/mem/ruby/system/System.hh b/src/mem/ruby/system/System.hh index 70d216201..787e4f4ae 100644 --- a/src/mem/ruby/system/System.hh +++ b/src/mem/ruby/system/System.hh @@ -70,6 +70,7 @@ class RubySystem : public ClockedObject ~RubySystem(); // config accessors + static int getRandomSeed() { return m_random_seed; } static int getRandomization() { return m_randomization; } static uint32_t getBlockSizeBytes() { return m_block_size_bytes; } static uint32_t getBlockSizeBits() { return m_block_size_bits; } @@ -117,17 +118,18 @@ class RubySystem : public ClockedObject RubySystem& operator=(const RubySystem& obj); void makeCacheRecorder(uint8_t *uncompressed_trace, - uint64_t cache_trace_size, - uint64_t block_size_bytes); + uint64 cache_trace_size, + uint64 block_size_bytes); void readCompressedTrace(std::string filename, uint8_t *&raw_data, - uint64_t &uncompressed_trace_size); + uint64& uncompressed_trace_size); void writeCompressedTrace(uint8_t *raw_data, std::string file, - uint64_t uncompressed_trace_size); + uint64 uncompressed_trace_size); private: // configuration parameters + static int m_random_seed; static bool m_randomization; static uint32_t m_block_size_bytes; static uint32_t m_block_size_bits; |