diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc Fri Sep 18 19:32:10 2015 -0500 @@ -28,8 +28,10 @@ * Authors: Niket Agarwal */ +#include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh" + +#include "debug/RubyNetwork.hh" #include "mem/ruby/network/garnet/flexible-pipeline/GarnetNetwork.hh" -#include "mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh" NetworkLink::NetworkLink(const Params *p) : ClockedObject(p), Consumer(this), m_id(p->link_id), @@ -93,6 +95,18 @@ return linkBuffer->isReady(curCycle()); } +Cycles +NetworkLink::whenReady() const +{ + return linkBuffer->whenReady(); +} + +bool +NetworkLink::isEmpty() const +{ + return linkBuffer->isEmpty(); +} + void NetworkLink::setInPort(int port) { @@ -118,6 +132,9 @@ m_link_utilized++; m_vc_load[t_flit->get_vc()]++; + + if (link_srcQueue->isReady(curCycle())) + scheduleEvent(Cycles(1)); } flit* diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/Router.cc --- a/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc Fri Sep 18 19:32:10 2015 -0500 @@ -287,8 +287,6 @@ void Router::wakeup() { - flit *t_flit; - // This is for round-robin scheduling of incoming ports int incoming_port = m_round_robin_start; m_round_robin_start++; @@ -305,7 +303,7 @@ // checking the incoming link if (m_in_link[incoming_port]->isReady()) { DPRINTF(RubyNetwork, "m_id: %d, Time: %lld\n", m_id, curCycle()); - t_flit = m_in_link[incoming_port]->peekLink(); + flit *t_flit = m_in_link[incoming_port]->peekLink(); routeCompute(t_flit, incoming_port); m_in_link[incoming_port]->consumeLink(); } diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh --- a/src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.hh Fri Sep 18 19:32:10 2015 -0500 @@ -51,6 +51,7 @@ flit *peekTopFlit(); void insert(flit *flt); void print(std::ostream& out) const; + Cycles whenReady() const; bool functionalRead(Packet *); uint32_t functionalWrite(Packet *); diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.cc --- a/src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/flitBuffer.cc Fri Sep 18 19:32:10 2015 -0500 @@ -61,6 +61,16 @@ return false; } +Cycles +flitBuffer::whenReady() const +{ + if (m_buffer.size() != 0 ) { + flit *t_flit = m_buffer.front(); + return t_flit->get_time(); + } + return Cycles(0); +} + bool flitBuffer::isFull() { diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/simple/PerfectSwitch.hh --- a/src/mem/ruby/network/simple/PerfectSwitch.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/simple/PerfectSwitch.hh Fri Sep 18 19:32:10 2015 -0500 @@ -40,7 +40,6 @@ #include #include -#include "mem/ruby/common/Consumer.hh" class MessageBuffer; class NetDest; @@ -55,7 +54,7 @@ bool operator<(const LinkOrder& l1, const LinkOrder& l2); -class PerfectSwitch : public Consumer +class PerfectSwitch { public: PerfectSwitch(SwitchID sid, Switch *, uint32_t); @@ -72,27 +71,42 @@ int getInLinks() const { return m_in.size(); } int getOutLinks() const { return m_out.size(); } - void wakeup(); - void storeEventInfo(int info); - void clearStats(); void collateStats(); void print(std::ostream& out) const; private: + class WakeupEvent : public Event + { + public: + WakeupEvent(PerfectSwitch *_p, int _port, int _vnet, + MessageBuffer *_buffer) + : Event(Default_Pri), p(_p), port(_port), vnet(_vnet), + buffer(_buffer) + {} + + void process() { p->operateMessageBuffer(buffer, port, vnet); } + private: + PerfectSwitch * const p; + const int port; + const int vnet; + MessageBuffer * const buffer; + }; + + private: // Private copy constructor and assignment operator PerfectSwitch(const PerfectSwitch& obj); 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; + Switch *m_switch; // vector of queues from the components - std::vector > m_in; - std::vector > m_out; + std::vector > m_in; + std::vector > m_out; + std::vector > m_wakeup; std::vector m_routing_table; std::vector m_link_order; @@ -101,7 +115,7 @@ int m_round_robin_start; int m_wakeups_wo_switch; - SimpleNetwork* m_network_ptr; + SimpleNetwork* m_network; std::vector m_pending_message_count; }; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/simple/PerfectSwitch.cc --- a/src/mem/ruby/network/simple/PerfectSwitch.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/simple/PerfectSwitch.cc Fri Sep 18 19:32:10 2015 -0500 @@ -49,7 +49,7 @@ } PerfectSwitch::PerfectSwitch(SwitchID sid, Switch *sw, uint32_t virt_nets) - : Consumer(sw), m_switch_id(sid), m_switch(sw) + : m_switch_id(sid), m_switch(sw) { m_round_robin_start = 0; m_wakeups_wo_switch = 0; @@ -59,7 +59,7 @@ void PerfectSwitch::init(SimpleNetwork *network_ptr) { - m_network_ptr = network_ptr; + m_network = network_ptr; for(int i = 0;i < m_virtual_networks;++i) { m_pending_message_count.push_back(0); @@ -71,12 +71,13 @@ { NodeID port = m_in.size(); m_in.push_back(in); + m_wakeup.push_back(vector(in.size(), nullptr)); for (int i = 0; i < in.size(); ++i) { if (in[i] != nullptr) { - in[i]->setConsumer(this); - in[i]->setIncomingLink(port); - in[i]->setVnet(i); + m_wakeup[port][i] = new WakeupEvent(this, port, i, in[i]); + in[i]->setEventManager(m_switch); + in[i]->setWakeupEvent(m_wakeup[port][i]); } } } @@ -101,40 +102,6 @@ } void -PerfectSwitch::operateVnet(int vnet) -{ - // This is for round-robin scheduling - int incoming = m_round_robin_start; - m_round_robin_start++; - if (m_round_robin_start >= m_in.size()) { - m_round_robin_start = 0; - } - - if(m_pending_message_count[vnet] > 0) { - // for all input ports, use round robin scheduling - for (int counter = 0; counter < m_in.size(); counter++) { - // Round robin scheduling - incoming++; - if (incoming >= m_in.size()) { - incoming = 0; - } - - // Is there a message waiting? - if (m_in[incoming].size() <= vnet) { - continue; - } - - MessageBuffer *buffer = m_in[incoming][vnet]; - if (buffer == nullptr) { - continue; - } - - operateMessageBuffer(buffer, incoming, vnet); - } - } -} - -void PerfectSwitch::operateMessageBuffer(MessageBuffer *buffer, int incoming, int vnet) { @@ -165,8 +132,8 @@ 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)) { + if (m_network->getAdaptiveRouting()) { + if (m_network->isVNetOrdered(vnet)) { // Don't adaptively route for (int out = 0; out < m_out.size(); out++) { m_link_order[out].m_link = out; @@ -191,10 +158,11 @@ } } + bool enough = true; 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]; + const NetDest &dst = m_routing_table[link]; DPRINTF(RubyNetwork, "dst: %s\n", dst); if (!msg_dsts.intersectionIsNotEmpty(dst)) @@ -207,35 +175,30 @@ // 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)); + output_link_destinations.emplace_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); + + // Check for resources + if (!m_out[link][vnet]->areNSlotsAvailable(1, current_time)) + enough = false; + + DPRINTF(RubyNetwork, "Checking if node is blocked ..." + "outgoing: %d, vnet: %d, enough: %d\n", + link, vnet, enough); } 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]; - - if (!m_out[outgoing][vnet]->areNSlotsAvailable(1, current_time)) - enough = false; - - 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)); + buffer->scheduleWakeup(m_switch->clockEdge(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 + break; } MsgPtr unmodified_msg_ptr; @@ -256,7 +219,7 @@ m_pending_message_count[vnet]--; // Enqueue it - for all outgoing queues - for (int i=0; i 0) { @@ -278,37 +241,11 @@ m_switch->cyclesToTicks(Cycles(1))); } } -} -void -PerfectSwitch::wakeup() -{ - // Give the highest numbered link priority most of the time - m_wakeups_wo_switch++; - int highest_prio_vnet = m_virtual_networks-1; - int lowest_prio_vnet = 0; - int decrementer = 1; - - // invert priorities to avoid starvation seen in the component network - if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { - m_wakeups_wo_switch = 0; - highest_prio_vnet = 0; - lowest_prio_vnet = m_virtual_networks-1; - decrementer = -1; + if (!buffer->isEmpty()) { + Tick next_evt_time = buffer->whenReady(); + buffer->scheduleWakeup(next_evt_time); } - - // For all components incoming queues - for (int vnet = highest_prio_vnet; - (vnet * decrementer) >= (decrementer * lowest_prio_vnet); - vnet -= decrementer) { - operateVnet(vnet); - } -} - -void -PerfectSwitch::storeEventInfo(int info) -{ - m_pending_message_count[info]++; } void diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/simple/Throttle.hh --- a/src/mem/ruby/network/simple/Throttle.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/simple/Throttle.hh Fri Sep 18 19:32:10 2015 -0500 @@ -42,14 +42,13 @@ #include #include -#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/network/Network.hh" #include "mem/ruby/system/RubySystem.hh" class MessageBuffer; class Switch; -class Throttle : public Consumer +class Throttle { public: Throttle(int sID, RubySystem *rs, NodeID node, Cycles link_latency, @@ -62,7 +61,7 @@ void addLinks(const std::vector& in_vec, const std::vector& out_vec); - void wakeup(); + void wakeup(Tick curTime); // The average utilization (a fraction) since last clearStats() const Stats::Scalar & getUtilization() const @@ -83,28 +82,49 @@ private: void init(NodeID node, Cycles link_latency, int link_bandwidth_multiplier, int endpoint_bandwidth); - void operateVnet(int vnet, int &bw_remainin, bool &schedule_wakeup, - MessageBuffer *in, MessageBuffer *out); + void operateVnet(int vnet, MessageBuffer *in, MessageBuffer *out); + + class WakeupEvent : public Event + { + public: + WakeupEvent(Throttle *_p, int _vnet, MessageBuffer *_in, + MessageBuffer *_out) + : Event(Default_Pri), p(_p), vnet(_vnet), in(_in), out(_out) + {} + + void process() { p->operateVnet(vnet, in, out); } + private: + Throttle * const p; + const int vnet; + MessageBuffer * const in; + MessageBuffer * const out; + }; // Private copy constructor and assignment operator Throttle(const Throttle& obj); Throttle& operator=(const Throttle& obj); - std::vector m_in; - std::vector m_out; - unsigned int m_vnets; - std::vector m_units_remaining; - const int m_switch_id; Switch *m_switch; NodeID m_node; + std::vector m_in; + std::vector m_out; + std::vector m_event; + + unsigned int m_vnets; + std::vector m_units_remaining; + int m_link_bandwidth_multiplier; Cycles m_link_latency; int m_wakeups_wo_switch; int m_endpoint_bandwidth; RubySystem *m_ruby_system; + //! Variables for tracking the bandwidth in each cycle. + int m_bw_remaining; + Cycles m_current_cycle; + // Statistical variables Stats::Scalar m_link_utilization; Stats::Vector m_msg_counts[MessageSizeType_NUM]; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/simple/Throttle.cc --- a/src/mem/ruby/network/simple/Throttle.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/simple/Throttle.cc Fri Sep 18 19:32:10 2015 -0500 @@ -50,19 +50,14 @@ 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) + : m_switch_id(sID), m_switch(em), m_node(node), m_vnets(0), + m_link_bandwidth_multiplier(link_bandwidth_multiplier), + m_link_latency(link_latency), m_wakeups_wo_switch(0), + m_endpoint_bandwidth(endpoint_bandwidth), m_ruby_system(rs), + m_bw_remaining(getLinkBandwidth()), m_current_cycle(Cycles(0)), + m_link_utilization_proxy(0) { - m_vnets = 0; - assert(link_bandwidth_multiplier > 0); - m_link_bandwidth_multiplier = link_bandwidth_multiplier; - - m_link_latency = link_latency; - m_endpoint_bandwidth = endpoint_bandwidth; - - m_wakeups_wo_switch = 0; - m_link_utilization_proxy = 0; } void @@ -74,22 +69,25 @@ for (int vnet = 0; vnet < in_vec.size(); ++vnet) { MessageBuffer *in_ptr = in_vec[vnet]; MessageBuffer *out_ptr = out_vec[vnet]; + WakeupEvent *event = new WakeupEvent(this, vnet, in_ptr, out_ptr); m_vnets++; m_units_remaining.push_back(0); m_in.push_back(in_ptr); m_out.push_back(out_ptr); + m_event.push_back(event); + + in_ptr->setEventManager(m_switch); + in_ptr->setWakeupEvent(event); // Set consumer and description - in_ptr->setConsumer(this); string desc = "[Queue to Throttle " + to_string(m_switch_id) + " " + to_string(m_node) + "]"; } } void -Throttle::operateVnet(int vnet, int &bw_remaining, bool &schedule_wakeup, - MessageBuffer *in, MessageBuffer *out) +Throttle::operateVnet(int vnet, MessageBuffer *in, MessageBuffer *out) { if (out == nullptr || in == nullptr) { return; @@ -97,8 +95,12 @@ assert(m_units_remaining[vnet] >= 0); Tick current_time = m_switch->clockEdge(); + if (m_switch->curCycle() != m_current_cycle) { + m_bw_remaining = getLinkBandwidth(); + m_current_cycle = m_switch->curCycle(); + } - while (bw_remaining > 0 && (in->isReady(current_time) || + while (m_bw_remaining > 0 && (in->isReady(current_time) || m_units_remaining[vnet] > 0) && out->areNSlotsAvailable(1, current_time)) { // See if we are done transferring the previous message on @@ -126,75 +128,24 @@ } // Calculate the amount of bandwidth we spent on this message - int diff = m_units_remaining[vnet] - bw_remaining; - m_units_remaining[vnet] = max(0, diff); - bw_remaining = max(0, -diff); - } - - if (bw_remaining > 0 && (in->isReady(current_time) || - m_units_remaining[vnet] > 0) && - !out->areNSlotsAvailable(1, current_time)) { - DPRINTF(RubyNetwork, "vnet: %d", vnet); - - // schedule me to wakeup again because I'm waiting for my - // output queue to become available - schedule_wakeup = true; - } -} - -void -Throttle::wakeup() -{ - // Limits the number of message sent to a limited number of bytes/cycle. - assert(getLinkBandwidth() > 0); - int bw_remaining = getLinkBandwidth(); - - m_wakeups_wo_switch++; - bool schedule_wakeup = false; - - // variable for deciding the direction in which to iterate - bool iteration_direction = false; - - - // invert priorities to avoid starvation seen in the component network - if (m_wakeups_wo_switch > PRIORITY_SWITCH_LIMIT) { - m_wakeups_wo_switch = 0; - iteration_direction = true; - } - - if (iteration_direction) { - for (int vnet = 0; vnet < m_vnets; ++vnet) { - operateVnet(vnet, bw_remaining, schedule_wakeup, - m_in[vnet], m_out[vnet]); - } - } else { - for (int vnet = m_vnets-1; vnet >= 0; --vnet) { - operateVnet(vnet, bw_remaining, schedule_wakeup, - m_in[vnet], m_out[vnet]); + if (m_units_remaining[vnet] <= m_bw_remaining) { + m_bw_remaining -= m_units_remaining[vnet]; + m_link_utilization_proxy += m_units_remaining[vnet]; + m_units_remaining[vnet] = 0; + } else { + m_units_remaining[vnet] -= m_bw_remaining; + m_link_utilization_proxy += m_bw_remaining; + m_bw_remaining = 0; } } - // We should only wake up when we use the bandwidth - // This is only mostly true - // assert(bw_remaining != getLinkBandwidth()); - - // Record that we used some or all of the link bandwidth this cycle - double ratio = 1.0 - (double(bw_remaining) / double(getLinkBandwidth())); - - // If ratio = 0, we used no bandwidth, if ratio = 1, we used all - m_link_utilization_proxy += ratio; - - if (bw_remaining > 0 && !schedule_wakeup) { - // We have extra bandwidth and our output buffer was - // available, so we must not have anything else to do until - // another message arrives. - DPRINTF(RubyNetwork, "%s not scheduled again\n", *this); - } else { - DPRINTF(RubyNetwork, "%s scheduled again\n", *this); - + if (in->isReady(current_time) || m_units_remaining[vnet] > 0) { // We are out of bandwidth for this cycle, so wakeup next // cycle and continue - scheduleEvent(Cycles(1)); + DPRINTF(RubyNetwork, "%s scheduled again\n", *this); + m_switch->schedule(m_event[vnet], m_switch->clockEdge(Cycles(1))); + } else if (!in->isEmpty()) { + m_switch->schedule(m_event[vnet], in->whenReady()); } } @@ -235,7 +186,8 @@ double time_delta = double(m_ruby_system->curCycle() - m_ruby_system->getStartCycle()); - m_link_utilization = 100.0 * m_link_utilization_proxy / time_delta; + m_link_utilization = 100.0 * ((m_link_utilization_proxy + / getLinkBandwidth()) / time_delta); } void diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/slicc_interface/AbstractController.hh --- a/src/mem/ruby/slicc_interface/AbstractController.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/slicc_interface/AbstractController.hh Fri Sep 18 19:32:10 2015 -0500 @@ -57,7 +57,7 @@ { return "Port rejected message based on type"; } }; -class AbstractController : public MemObject, public Consumer +class AbstractController : public MemObject { public: typedef RubyControllerParams Params; @@ -79,7 +79,6 @@ virtual AccessPermission getAccessPermission(const Addr &addr) = 0; virtual void print(std::ostream & out) const = 0; - virtual void wakeup() = 0; virtual void resetStats() = 0; virtual void regStats(); @@ -152,10 +151,14 @@ 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; Cycles m_recycle_latency; + //! Variables for tracking the number of transistions in each cycle + const int m_transitions_per_cycle; + int m_transitions_current_cycle; + Cycles m_current_cycle; + //! Counter for the number of cycles when the transitions carried out //! were equal to the maximum allowed Stats::Scalar m_fully_busy_cycles; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/slicc_interface/AbstractController.cc --- a/src/mem/ruby/slicc_interface/AbstractController.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/slicc_interface/AbstractController.cc Fri Sep 18 19:32:10 2015 -0500 @@ -35,12 +35,12 @@ #include "sim/system.hh" AbstractController::AbstractController(const Params *p) - : MemObject(p), Consumer(this), m_version(p->version), - m_clusterID(p->cluster_id), + : MemObject(p), m_version(p->version), m_clusterID(p->cluster_id), m_masterId(p->system->getMasterId(name())), m_is_blocking(false), m_number_of_TBEs(p->number_of_TBEs), + m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency), m_transitions_per_cycle(p->transitions_per_cycle), - m_buffer_size(p->buffer_size), m_recycle_latency(p->recycle_latency), + m_transitions_current_cycle(0), m_current_cycle(Cycles(0)), memoryPort(csprintf("%s.memory", name()), this, "") { } diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/slicc_interface/Message.hh --- a/src/mem/ruby/slicc_interface/Message.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/slicc_interface/Message.hh Fri Sep 18 19:32:10 2015 -0500 @@ -98,20 +98,11 @@ virtual NetDest& getDestination() { panic("getDestination() called on wrong message!"); } - int getIncomingLink() const { return incoming_link; } - void setIncomingLink(int link) { incoming_link = link; } - int getVnet() const { return vnet; } - void setVnet(int net) { vnet = net; } - private: const Tick m_time; Tick m_LastEnqueueTime; // my last enqueue time Tick m_DelayedTicks; // my delayed cycles uint64_t m_msg_counter; // FIXME, should this be a 64-bit value? - - // Variables for required network traversal - int incoming_link; - int vnet; }; inline bool diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/structures/RubyMemoryControl.hh --- a/src/mem/ruby/structures/RubyMemoryControl.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/structures/RubyMemoryControl.hh Fri Sep 18 19:32:10 2015 -0500 @@ -48,7 +48,7 @@ ////////////////////////////////////////////////////////////////////////////// -class RubyMemoryControl : public AbstractMemory, public Consumer +class RubyMemoryControl : public AbstractMemory { public: typedef RubyMemoryControlParams Params; @@ -61,7 +61,7 @@ virtual BaseSlavePort& getSlavePort(const std::string& if_name, PortID idx = InvalidPortID); DrainState drain() M5_ATTR_OVERRIDE; - void wakeup(); + void wakeup(Tick curTime); void setDescription(const std::string& name) { m_description = name; }; std::string getDescription() { return m_description; }; @@ -192,7 +192,7 @@ mem_cntrl = _mem_cntrl; } private: - void process() { mem_cntrl->wakeup(); } + void process() { mem_cntrl->wakeup(when()); } RubyMemoryControl* mem_cntrl; }; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/structures/RubyMemoryControl.cc --- a/src/mem/ruby/structures/RubyMemoryControl.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/structures/RubyMemoryControl.cc Fri Sep 18 19:32:10 2015 -0500 @@ -144,8 +144,7 @@ // CONSTRUCTOR RubyMemoryControl::RubyMemoryControl(const Params *p) - : AbstractMemory(p), Consumer(this), port(name() + ".port", *this), - m_event(this) + : AbstractMemory(p), port(name() + ".port", *this), m_event(this) { m_banks_per_rank = p->banks_per_rank; m_ranks_per_dimm = p->ranks_per_dimm; @@ -645,7 +644,7 @@ // wakeup: This function is called once per memory controller clock cycle. void -RubyMemoryControl::wakeup() +RubyMemoryControl::wakeup(Tick curTime) { DPRINTF(RubyMemory, "MemoryController wakeup\n"); // execute everything diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/structures/TimerTable.hh --- a/src/mem/ruby/structures/TimerTable.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/structures/TimerTable.hh Fri Sep 18 19:32:10 2015 -0500 @@ -35,7 +35,7 @@ #include #include "mem/ruby/common/Address.hh" -#include "mem/ruby/common/Consumer.hh" +#include "sim/eventq.hh" class TimerTable { @@ -43,12 +43,15 @@ TimerTable(); void - setConsumer(Consumer* consumer_ptr) + setEventManager(EventManager *em) { - assert(m_consumer_ptr == NULL); - m_consumer_ptr = consumer_ptr; + assert(m_event_manager == nullptr); + m_event_manager = em; } + void setWakeupEvent(Event *e) { m_wakeup_event = e; } + void scheduleWakeup(Tick t); + void setDescription(const std::string& name) { @@ -56,6 +59,7 @@ } bool isReady(Tick curTime) const; + bool isEmpty() const { return m_map.empty(); } Addr nextAddress() const; bool isSet(Addr address) const { return !!m_map.count(address); } void set(Addr address, Tick ready_time); @@ -79,9 +83,9 @@ mutable Tick m_next_time; // Only valid if m_next_valid is true mutable Addr m_next_address; // Only valid if m_next_valid is true - //! Consumer to signal a wakeup() - Consumer* m_consumer_ptr; - + //! Wakeup event + EventManager *m_event_manager; + Event *m_wakeup_event; std::string m_name; }; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/structures/TimerTable.cc --- a/src/mem/ruby/structures/TimerTable.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/structures/TimerTable.cc Fri Sep 18 19:32:10 2015 -0500 @@ -33,7 +33,7 @@ TimerTable::TimerTable() : m_next_time(0) { - m_consumer_ptr = NULL; + m_event_manager = nullptr; m_next_valid = false; m_next_address = 0; } @@ -62,14 +62,24 @@ } void +TimerTable::scheduleWakeup(Tick t) +{ + assert(m_event_manager != NULL); + if (!m_wakeup_event->scheduled()) { + m_event_manager->schedule(m_wakeup_event, t); + } else if (t < m_wakeup_event->when()) { + m_event_manager->reschedule(m_wakeup_event, t); + } +} + +void TimerTable::set(Addr address, Tick ready_time) { assert(address == makeLineAddress(address)); assert(!m_map.count(address)); m_map[address] = ready_time; - assert(m_consumer_ptr != NULL); - m_consumer_ptr->scheduleEventAbsolute(ready_time); + scheduleWakeup(ready_time); m_next_valid = false; // Don't always recalculate the next ready address diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/slicc/ast/FuncCallExprAST.py --- a/src/mem/slicc/ast/FuncCallExprAST.py Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/slicc/ast/FuncCallExprAST.py Fri Sep 18 19:32:10 2015 -0500 @@ -132,15 +132,16 @@ code(''' if (result == TransitionResult_Valid) { - counter++; + m_transitions_current_cycle++; continue; // Check the first port again } if (result == TransitionResult_ResourceStall || result == TransitionResult_ProtocolStall) { - scheduleEvent(Cycles(1)); + schedule_wakeup = true; // Cannot do anything with this transition, go check next doable transition (mostly likely of next port) + continue; } } ''') diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/slicc/ast/IfStatementAST.py --- a/src/mem/slicc/ast/IfStatementAST.py Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/slicc/ast/IfStatementAST.py Fri Sep 18 19:32:10 2015 -0500 @@ -51,14 +51,12 @@ cond_type) # Conditional - code.indent() code('if ($cond_code) {') # Then part code.indent() self.symtab.pushFrame() self.then.generate(code, return_type) self.symtab.popFrame() - code.dedent() # Else part if self.else_: code('} else {') diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/slicc/ast/InPortDeclAST.py --- a/src/mem/slicc/ast/InPortDeclAST.py Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/slicc/ast/InPortDeclAST.py Fri Sep 18 19:32:10 2015 -0500 @@ -116,8 +116,6 @@ if self.statements is not None: rcode = self.slicc.codeFormatter() - rcode.indent() - rcode.indent() self.statements.generate(rcode, None) in_port["c_code_in_port"] = str(rcode) diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/slicc/symbols/StateMachine.py --- a/src/mem/slicc/symbols/StateMachine.py Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/slicc/symbols/StateMachine.py Fri Sep 18 19:32:10 2015 -0500 @@ -196,7 +196,7 @@ port_to_buf_map = {} in_msg_bufs = {} for port in self.in_ports: - buf_name = "m_%s_ptr" % port.pairs["buffer_expr"].name + buf_name = "m_%s" % port.pairs["buffer_expr"].name msg_bufs.append(buf_name) port_to_buf_map[port] = msg_bufs.index(buf_name) if buf_name not in in_msg_bufs: @@ -270,7 +270,6 @@ #include "mem/protocol/TransitionResult.hh" #include "mem/protocol/Types.hh" -#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/slicc_interface/AbstractController.hh" #include "params/$c_ident.hh" @@ -299,7 +298,6 @@ void initNetQueues(); void print(std::ostream& out) const; - void wakeup(); void resetStats(); void regStats(); @@ -318,6 +316,23 @@ ''') code.indent() + port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) + for msg_buf in msg_bufs: + code(''' +void Wakeup_${{msg_buf}}(Tick curTime); +class ${{msg_buf}}_WakeupEvent : public Event +{ + public: + ${{msg_buf}}_WakeupEvent($c_ident *_c) + : c(_c) + {} + void process() { c->Wakeup_${{msg_buf}}(when()); } + private: + $c_ident * const c; +}; + +${{msg_buf}}_WakeupEvent *m_${{msg_buf}}_wakeup_event; +''') # added by SS for param in self.config_parameters: if param.pointer: @@ -618,9 +633,13 @@ code('${{prefetcher.code}}.setController(this);') code() - for port in self.in_ports: - # Set the queue consumers - code('${{port.code}}.setConsumer(this);') + port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) + for msg_buf in msg_bufs: + code(''' +m_${{msg_buf}}_wakeup_event = new ${{msg_buf}}_WakeupEvent(this); +${{msg_buf}}_ptr->setEventManager(this); +${{msg_buf}}_ptr->setWakeupEvent(m_${{msg_buf}}_wakeup_event); +''') # Initialize the transition profiling code() @@ -942,68 +961,63 @@ for include_path in includes: code('#include "${{include_path}}"') + code('using namespace std;') + + # InPorts port_to_buf_map, in_msg_bufs, msg_bufs = self.getBufferMaps(ident) + for msg_buf, in_ports in in_msg_bufs.items(): + code(''' +void +${ident}_Controller::Wakeup_${{msg_buf}}(Tick curTime) +{ + if (curCycle() != m_current_cycle) { + m_transitions_current_cycle = 0; + m_current_cycle = curCycle(); + } - code(''' - -using namespace std; - -void -${ident}_Controller::wakeup() -{ - int counter = 0; + bool schedule_wakeup = false; while (true) { - unsigned char rejected[${{len(msg_bufs)}}]; - memset(rejected, 0, sizeof(unsigned char)*${{len(msg_bufs)}}); + unsigned int rejected = 0; // Some cases will put us into an infinite loop without this limit - assert(counter <= m_transitions_per_cycle); - if (counter == m_transitions_per_cycle) { + assert(m_transitions_current_cycle <= m_transitions_per_cycle); + if (m_transitions_current_cycle == m_transitions_per_cycle) { // Count how often we are fully utilized m_fully_busy_cycles++; - - // Wakeup in another cycle and try again - scheduleEvent(Cycles(1)); break; } ''') - code.indent() - code.indent() + code.indent() + code.indent() - # InPorts - # - for port in self.in_ports: - code.indent() - code('// ${ident}InPort $port') - if port.pairs.has_key("rank"): - code('m_cur_in_port = ${{port.pairs["rank"]}};') - else: - code('m_cur_in_port = 0;') - if port in port_to_buf_map: - code('try {') - code.indent() - code('${{port["c_code_in_port"]}}') + for port in in_ports: + code('// ${ident}InPort $port') + if port.pairs.has_key("rank"): + code('m_cur_in_port = ${{port.pairs["rank"]}};') + else: + code('m_cur_in_port = 0;') + if port in port_to_buf_map: + code('try {') + code.indent() + code('${{port["c_code_in_port"]}}') - if port in port_to_buf_map: - code.dedent() - code(''' - } catch (const RejectException & e) { - rejected[${{port_to_buf_map[port]}}]++; - } + if port in port_to_buf_map: + code.dedent() + code(''' + } catch (const RejectException & e) { + rejected++; + } ''') code.dedent() - code('') + code.dedent() - code.dedent() - code.dedent() - code(''' + code(''' // If we got this far, we have nothing left todo or something went // wrong''') - for buf_name, ports in in_msg_bufs.items(): - if len(ports) > 1: + if len(in_ports) > 1: # only produce checks when a buffer is shared by multiple ports code(''' - if (${{buf_name}}->isReady(clockEdge()) && rejected[${{port_to_buf_map[ports[0]]}}] == ${{len(ports)}}) + if (${{msg_buf}}->isReady(clockEdge()) && rejected > 0) { // no port claimed the message on the top of this buffer panic("Runtime Error at Ruby Time: %d. " @@ -1014,10 +1028,16 @@ Cycles(1)); } ''') - code(''' + code(''' break; } + + if (!${{msg_buf}}_ptr->isEmpty() || schedule_wakeup) { + // Wakeup in another cycle and try again + ${{msg_buf}}_ptr->scheduleWakeup(clockEdge(Cycles(1))); + } } + ''') code.write(path, "%s_Wakeup.cc" % self.ident) @@ -1078,8 +1098,8 @@ code(''' ${ident}_State next_state = state; -DPRINTF(RubyGenerated, "%s, Time: %lld, state: %s, event: %s, addr: %#x\\n", - *this, curCycle(), ${ident}_State_to_string(state), +DPRINTF(RubyGenerated, "Time: %lld, state: %s, event: %s, addr: %#x\\n", + curCycle(), ${ident}_State_to_string(state), ${ident}_Event_to_string(event), addr); TransitionResult result = diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/MessageBuffer.hh --- a/src/mem/ruby/network/MessageBuffer.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/MessageBuffer.hh Fri Sep 18 19:32:10 2015 -0500 @@ -43,10 +43,10 @@ #include "debug/RubyQueue.hh" #include "mem/ruby/common/Address.hh" -#include "mem/ruby/common/Consumer.hh" #include "mem/ruby/slicc_interface/Message.hh" #include "mem/packet.hh" #include "params/MessageBuffer.hh" +#include "sim/eventq.hh" #include "sim/sim_object.hh" class MessageBuffer : public SimObject @@ -61,6 +61,7 @@ // TRUE if head of queue timestamp <= SystemTime bool isReady(Tick current_time) const; + Tick whenReady() const; void delayHead(Tick current_time, Tick delta) @@ -75,18 +76,11 @@ bool areNSlotsAvailable(unsigned int n, Tick curTime); int getPriority() { return m_priority_rank; } void setPriority(int rank) { m_priority_rank = rank; } - void setConsumer(Consumer* consumer) + void setEventManager(EventManager *c) { - DPRINTF(RubyQueue, "Setting consumer: %s\n", *consumer); - if (m_consumer != NULL) { - fatal("Trying to connect %s to MessageBuffer %s. \ - \n%s already connected. Check the cntrl_id's.\n", - *consumer, *this, *m_consumer); - } - m_consumer = consumer; + m_event_manager = c; } - - Consumer* getConsumer() { return m_consumer; } + void setWakeupEvent(Event *e) { m_wakeup_event = e; } bool getOrdered() { return m_strict_fifo; } @@ -113,22 +107,21 @@ void print(std::ostream& out) const; void clearStats() { m_not_avail_count = 0; m_msg_counter = 0; } - 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 need // to be updated with the data from the packet. // Return value indicates the number of messages that were updated. // This required for debugging the code. uint32_t functionalWrite(Packet *pkt); + void scheduleWakeup(Tick t); private: void reanalyzeList(std::list &, Tick); private: // Data Members (m_ prefix) - //! Consumer to signal a wakeup(), can be NULL - Consumer* m_consumer; + //! Wakeup event + EventManager *m_event_manager; + Event *m_wakeup_event; std::vector m_prio_heap; // use a std::map for the stalled messages as this container is @@ -156,9 +149,6 @@ int m_priority_rank; const bool m_strict_fifo; const bool m_randomization; - - int m_input_link_id; - int m_vnet_id; }; Tick random_time(); diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/MessageBuffer.cc --- a/src/mem/ruby/network/MessageBuffer.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/MessageBuffer.cc Fri Sep 18 19:32:10 2015 -0500 @@ -47,7 +47,6 @@ m_randomization(p->randomization) { m_msg_counter = 0; - m_consumer = NULL; m_size_last_time_size_checked = 0; m_size_at_cycle_start = 0; m_msgs_this_cycle = 0; @@ -55,8 +54,6 @@ m_priority_rank = 0; m_stall_msg_map.clear(); - m_input_link_id = 0; - m_vnet_id = 0; } unsigned int @@ -135,6 +132,17 @@ } void +MessageBuffer::scheduleWakeup(Tick t) +{ + assert(m_event_manager != NULL); + if (!m_wakeup_event->scheduled()) { + m_event_manager->schedule(m_wakeup_event, t); + } else if (t < m_wakeup_event->when()) { + m_event_manager->reschedule(m_wakeup_event, t); + } +} + +void MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) { // record current time incase we have a pop that also adjusts my size @@ -200,10 +208,7 @@ DPRINTF(RubyQueue, "Enqueue arrival_time: %lld, Message: %s\n", arrival_time, *(message.get())); - // Schedule the wakeup - assert(m_consumer != NULL); - m_consumer->scheduleEventAbsolute(arrival_time); - m_consumer->storeEventInfo(m_vnet_id); + scheduleWakeup(arrival_time); } Tick @@ -257,7 +262,7 @@ m_prio_heap.back() = node; push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - m_consumer->scheduleEventAbsolute(future_time); + scheduleWakeup(future_time); } void @@ -273,7 +278,7 @@ push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - m_consumer->scheduleEventAbsolute(schdTick); + scheduleWakeup(schdTick); lt.pop_front(); } } @@ -333,14 +338,9 @@ void MessageBuffer::print(ostream& out) const { - ccprintf(out, "[MessageBuffer: "); - if (m_consumer != NULL) { - ccprintf(out, " consumer-yes "); - } - vector copy(m_prio_heap); sort_heap(copy.begin(), copy.end(), greater()); - ccprintf(out, "%s] %s", copy, name()); + ccprintf(out, "%s", copy); } bool @@ -350,6 +350,12 @@ (m_prio_heap.front()->getLastEnqueueTime() <= current_time)); } +Tick +MessageBuffer::whenReady() const +{ + return m_prio_heap.front()->getLastEnqueueTime(); +} + uint32_t MessageBuffer::functionalWrite(Packet *pkt) { diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.hh Fri Sep 18 19:32:10 2015 -0500 @@ -69,6 +69,18 @@ uint32_t functionalWrite(Packet *); private: + class WakeupEvent : public Event + { + public: + WakeupEvent(NetworkInterface_d *_p) : Event(Default_Pri), p(_p) {} + + void process() { p->wakeup(); } + private: + NetworkInterface_d * const p; + }; + WakeupEvent m_wakeup_event; + + private: GarnetNetwork_d *m_net_ptr; const NodeID m_id; const int m_virtual_networks, m_vc_per_vnet, m_num_vcs; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc Fri Sep 18 19:32:10 2015 -0500 @@ -43,7 +43,7 @@ using m5::stl_helpers::deletePointers; NetworkInterface_d::NetworkInterface_d(const Params *p) - : ClockedObject(p), Consumer(this), m_id(p->id), + : ClockedObject(p), Consumer(this), m_wakeup_event(this), m_id(p->id), m_virtual_networks(p->virt_nets), m_vc_per_vnet(p->vcs_per_vnet), m_num_vcs(m_vc_per_vnet * m_virtual_networks) { @@ -111,7 +111,8 @@ for (auto& it : in) { if (it != nullptr) { - it->setConsumer(this); + it->setEventManager(this); + it->setWakeupEvent(&m_wakeup_event); } } } @@ -210,8 +211,6 @@ NetworkInterface_d::wakeup() { DPRINTF(RubyNetwork, "m_id: %d woke up at time: %lld", m_id, curCycle()); - - MsgPtr msg_ptr; Tick curTime = clockEdge(); // Checking for messages coming from the protocol @@ -223,7 +222,7 @@ } while (b->isReady(curTime)) { // Is there a message waiting - msg_ptr = b->peekMsgPtr(); + MsgPtr msg_ptr = b->peekMsgPtr(); if (flitisizeMessage(msg_ptr, vnet)) { b->dequeue(curTime); } else { @@ -233,7 +232,6 @@ } scheduleOutputLink(); - checkReschedule(); /*********** Picking messages destined for this NI **********/ @@ -274,6 +272,8 @@ } delete t_flit; } + + checkReschedule(); } /** This function looks at the NI buffers @@ -349,14 +349,22 @@ void NetworkInterface_d::checkReschedule() { + Tick min_tick = 0; + bool tick_init = false; + for (const auto& it : inNode_ptr) { if (it == nullptr) { continue; } - while (it->isReady(clockEdge())) { // Is there a message waiting - scheduleEvent(Cycles(1)); - return; + // Is there a message waiting + if (!it->isEmpty()) { + if (tick_init) { + min_tick = std::min(min_tick, it->whenReady()); + } else { + tick_init = true; + min_tick = it->whenReady(); + } } } @@ -366,6 +374,10 @@ return; } } + + if (tick_init) { + scheduleEventAbsolute(min_tick); + } } void diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.hh Fri Sep 18 19:32:10 2015 -0500 @@ -60,6 +60,8 @@ inline bool isReady(Cycles curTime) { return linkBuffer->isReady(curTime); } + bool isEmpty () const; + Cycles whenReady ()const; inline flit_d* peekLink() { return linkBuffer->peekTopFlit(); } inline flit_d* consumeLink() { return linkBuffer->getTopFlit(); } diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc Fri Sep 18 19:32:10 2015 -0500 @@ -57,6 +57,18 @@ link_srcQueue = srcQueue; } +Cycles +NetworkLink_d::whenReady() const +{ + return linkBuffer->whenReady(); +} + +bool +NetworkLink_d::isEmpty() const +{ + return linkBuffer->isEmpty(); +} + void NetworkLink_d::wakeup() { @@ -67,6 +79,9 @@ link_consumer->scheduleEventAbsolute(clockEdge(m_latency)); m_link_utilized++; m_vc_load[t_flit->get_vc()]++; + + if (link_srcQueue->isReady(curCycle())) + scheduleEvent(Cycles(1)); } } diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh --- a/src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.hh Fri Sep 18 19:32:10 2015 -0500 @@ -49,6 +49,7 @@ void print(std::ostream& out) const; bool isFull(); void setMaxSize(int maximum); + Cycles whenReady() const; flit_d * getTopFlit() diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.cc --- a/src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/fixed-pipeline/flitBuffer_d.cc Fri Sep 18 19:32:10 2015 -0500 @@ -88,3 +88,13 @@ return num_functional_writes; } + +Cycles +flitBuffer_d::whenReady() const +{ + if (m_buffer.size() != 0 ) { + flit_d *t_flit = m_buffer.front(); + return t_flit->get_time(); + } + return Cycles(0); +} diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.hh --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.hh Fri Sep 18 19:32:10 2015 -0500 @@ -74,6 +74,18 @@ void init_net_ptr(GarnetNetwork* net_ptr) { m_net_ptr = net_ptr; } private: + class WakeupEvent : public Event + { + public: + WakeupEvent(NetworkInterface *_p) : Event(Default_Pri), p(_p) {} + + void process() { p->wakeup(); } + private: + NetworkInterface * const p; + }; + WakeupEvent m_wakeup_event; + + private: GarnetNetwork *m_net_ptr; uint32_t m_virtual_networks, m_num_vcs, m_vc_per_vnet; NodeID m_id; diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc Fri Sep 18 19:32:10 2015 -0500 @@ -43,7 +43,7 @@ using m5::stl_helpers::deletePointers; NetworkInterface::NetworkInterface(const Params *p) - : ClockedObject(p), FlexibleConsumer(this) + : ClockedObject(p), FlexibleConsumer(this), m_wakeup_event(this) { m_id = p->id; m_virtual_networks = p->virt_nets; @@ -98,7 +98,8 @@ for (auto& it: in) { if (it != nullptr) { - it->setConsumer(this); + it->setEventManager(this); + it->setWakeupEvent(&m_wakeup_event); } } } @@ -233,8 +234,6 @@ void NetworkInterface::wakeup() { - MsgPtr msg_ptr; - //Checking for messages coming from the protocol // can pick up a message/cycle for each virtual net for (int vnet = 0; vnet < inNode_ptr.size(); ++vnet) { @@ -244,7 +243,7 @@ } while (b->isReady(clockEdge())) { // Is there a message waiting - msg_ptr = b->peekMsgPtr(); + MsgPtr msg_ptr = b->peekMsgPtr(); if (flitisizeMessage(msg_ptr, vnet)) { b->dequeue(clockEdge()); } else { @@ -254,7 +253,6 @@ } scheduleOutputLink(); - checkReschedule(); /*********** Picking messages destined for this NI **********/ @@ -281,6 +279,8 @@ m_net_ptr->increment_queueing_latency(queueing_delay, vnet); delete t_flit; } + + checkReschedule(); } /* This function looks at the NI buffers and if some buffer has flits which @@ -322,14 +322,22 @@ void NetworkInterface::checkReschedule() { + Tick min_tick = 0; + bool tick_init = false; + for (const auto& it : inNode_ptr) { if (it == nullptr) { continue; } - while (it->isReady(clockEdge())) { // Is there a message waiting - scheduleEvent(Cycles(1)); - return; + // Is there a message waiting + if (!it->isEmpty()) { + if (tick_init) { + min_tick = std::min(min_tick, it->whenReady()); + } else { + tick_init = true; + min_tick = it->whenReady(); + } } } @@ -339,6 +347,10 @@ return; } } + + if (tick_init) { + scheduleEventAbsolute(min_tick); + } } bool diff -r 5e6d088f2e7c -r c4c3b2f0e36b src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh Fri Sep 18 19:29:50 2015 -0500 +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.hh Fri Sep 18 19:32:10 2015 -0500 @@ -64,6 +64,8 @@ void setOutPort(int port); void wakeup(); bool isReady(); + bool isEmpty () const; + Cycles whenReady ()const; void grant_vc_link(int vc, Cycles grant_time); void release_vc_link(int vc, Cycles release_time); void request_vc_link(int vc, NetDest destination, Cycles request_time);