From 39e944546807d3fcde3d5eedc1b6a2a97458f4b1 Mon Sep 17 00:00:00 2001 From: Nilay Vaish Date: Fri, 22 Mar 2013 15:53:26 -0500 Subject: [PATCH] ruby: consumer: avoid using receiver side clock A set of patches was recently committed to allow multiple clock domains in ruby. In those patches, I had inadvertently made an incorrect use of the clocks. Suppose object A needs to schedule an event on object B. It was possible that A accesses B's clock to schedule the event. This is not possible in actual system. Hence, changes are being to the Consumer class so as to avoid such happenings. Note that in a multi eventq simulation, this can possibly lead to an incorrect simulation. There are two functions in the Consumer class that are used for scheduling events. The first function takes in the relative delay over the current time as the argument and adds the current time to it for scheduling the event. The second function takes in the absolute time (in ticks) for scheduling the event. The first function is now being moved to protected section of the class so that only objects of the derived classes can use it. All other objects will have to specify absolute time while scheduling an event for some consumer. --- src/mem/ruby/buffers/MessageBuffer.cc | 13 ++++++++----- src/mem/ruby/common/Consumer.cc | 8 ++------ src/mem/ruby/common/Consumer.hh | 4 +++- .../network/garnet/fixed-pipeline/InputUnit_d.hh | 2 +- .../garnet/fixed-pipeline/NetworkInterface_d.cc | 6 ++++-- .../network/garnet/fixed-pipeline/NetworkLink_d.cc | 2 +- .../network/garnet/fixed-pipeline/OutputUnit_d.hh | 2 +- .../ruby/network/garnet/fixed-pipeline/Router_d.cc | 6 +++--- .../garnet/flexible-pipeline/NetworkInterface.cc | 3 ++- .../network/garnet/flexible-pipeline/NetworkLink.cc | 3 ++- .../ruby/network/garnet/flexible-pipeline/Router.cc | 8 +++++--- src/mem/ruby/system/RubyMemoryControl.cc | 2 +- src/mem/ruby/system/TimerTable.cc | 3 ++- src/mem/ruby/system/WireBuffer.cc | 6 ++++-- 14 files changed, 39 insertions(+), 29 deletions(-) diff --git a/src/mem/ruby/buffers/MessageBuffer.cc b/src/mem/ruby/buffers/MessageBuffer.cc index 92c989851e..e78b99b2b2 100644 --- a/src/mem/ruby/buffers/MessageBuffer.cc +++ b/src/mem/ruby/buffers/MessageBuffer.cc @@ -231,7 +231,8 @@ MessageBuffer::enqueue(MsgPtr message, Cycles delay) // Schedule the wakeup if (m_consumer_ptr != NULL) { - m_consumer_ptr->scheduleEventAbsolute(arrival_time); + m_consumer_ptr->scheduleEventAbsolute( + arrival_time * m_receiver_ptr->clockPeriod()); m_consumer_ptr->storeEventInfo(m_vnet_id); } else { panic("No consumer: %s name: %s\n", *this, m_name); @@ -312,8 +313,8 @@ MessageBuffer::recycle() m_prio_heap.back() = node; push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - m_consumer_ptr->scheduleEventAbsolute(m_receiver_ptr->curCycle() + - m_recycle_latency); + m_consumer_ptr-> + scheduleEventAbsolute(m_receiver_ptr->clockEdge(m_recycle_latency)); } void @@ -336,7 +337,8 @@ MessageBuffer::reanalyzeMessages(const Address& addr) push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - m_consumer_ptr->scheduleEventAbsolute(msgNode.m_time); + m_consumer_ptr-> + scheduleEventAbsolute(m_receiver_ptr->clockPeriod() * nextCycle); m_stall_msg_map[addr].pop_front(); } m_stall_msg_map.erase(addr); @@ -365,7 +367,8 @@ MessageBuffer::reanalyzeAllMessages() push_heap(m_prio_heap.begin(), m_prio_heap.end(), greater()); - m_consumer_ptr->scheduleEventAbsolute(msgNode.m_time); + m_consumer_ptr-> + scheduleEventAbsolute(m_receiver_ptr->clockPeriod() * nextCycle); (map_iter->second).pop_front(); } } diff --git a/src/mem/ruby/common/Consumer.cc b/src/mem/ruby/common/Consumer.cc index b7d31ccb07..9f37357095 100644 --- a/src/mem/ruby/common/Consumer.cc +++ b/src/mem/ruby/common/Consumer.cc @@ -31,19 +31,15 @@ void Consumer::scheduleEvent(Cycles timeDelta) { - timeDelta += em->curCycle(); - scheduleEventAbsolute(timeDelta); + scheduleEventAbsolute(em->clockEdge(timeDelta)); } void -Consumer::scheduleEventAbsolute(Cycles timeAbs) +Consumer::scheduleEventAbsolute(Tick evt_time) { - Tick evt_time = em->clockPeriod() * timeAbs; if (!alreadyScheduled(evt_time)) { // This wakeup is not redundant ConsumerEvent *evt = new ConsumerEvent(this); - assert(timeAbs > em->curCycle()); - em->schedule(evt, evt_time); insertScheduledWakeupTime(evt_time); } diff --git a/src/mem/ruby/common/Consumer.hh b/src/mem/ruby/common/Consumer.hh index c1b4d70b1d..57ee69f3e8 100644 --- a/src/mem/ruby/common/Consumer.hh +++ b/src/mem/ruby/common/Consumer.hh @@ -87,8 +87,10 @@ class Consumer m_scheduled_wakeups.erase(time); } + void scheduleEventAbsolute(Tick timeAbs); + + protected: void scheduleEvent(Cycles timeDelta); - void scheduleEventAbsolute(Cycles timeAbs); private: Tick m_last_scheduled_wakeup; diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh index c188b12d69..6afb4726bd 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/InputUnit_d.hh @@ -90,7 +90,7 @@ class InputUnit_d : public Consumer { flit_d *t_flit = new flit_d(in_vc, free_signal, curTime); creditQueue->insert(t_flit); - m_credit_link->scheduleEvent(Cycles(1)); + m_credit_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1))); } inline int diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc index bdae26fd0c..e492164761 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkInterface_d.cc @@ -254,7 +254,8 @@ NetworkInterface_d::wakeup() flit_d *credit_flit = new flit_d(t_flit->get_vc(), free_signal, m_net_ptr->curCycle()); creditQueue->insert(credit_flit); - m_ni_credit_link->scheduleEvent(Cycles(1)); + m_ni_credit_link-> + scheduleEventAbsolute(m_net_ptr->clockEdge(Cycles(1))); int vnet = t_flit->get_vnet(); m_net_ptr->increment_received_flits(vnet); @@ -328,7 +329,8 @@ NetworkInterface_d::scheduleOutputLink() t_flit->set_time(m_net_ptr->curCycle() + Cycles(1)); outSrcQueue->insert(t_flit); // schedule the out link - outNetLink->scheduleEvent(Cycles(1)); + outNetLink-> + scheduleEventAbsolute(m_net_ptr->clockEdge(Cycles(1))); if (t_flit->get_type() == TAIL_ || t_flit->get_type() == HEAD_TAIL_) { diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc index afa9d63d38..d84bf8e69a 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/NetworkLink_d.cc @@ -70,7 +70,7 @@ NetworkLink_d::wakeup() flit_d *t_flit = link_srcQueue->getTopFlit(); t_flit->set_time(curCycle() + m_latency); linkBuffer->insert(t_flit); - link_consumer->scheduleEvent(m_latency); + link_consumer->scheduleEventAbsolute(clockEdge(m_latency)); m_link_utilized++; m_vc_load[t_flit->get_vc()]++; } diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.hh b/src/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.hh index 50497303c9..48bf361a58 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.hh +++ b/src/mem/ruby/network/garnet/fixed-pipeline/OutputUnit_d.hh @@ -84,7 +84,7 @@ class OutputUnit_d : public Consumer insert_flit(flit_d *t_flit) { m_out_buffer->insert(t_flit); - m_out_link->scheduleEvent(Cycles(1)); + m_out_link->scheduleEventAbsolute(m_router->clockEdge(Cycles(1))); } uint32_t functionalWrite(Packet *pkt); diff --git a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc index 44ca818024..fd4ce53890 100644 --- a/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc +++ b/src/mem/ruby/network/garnet/fixed-pipeline/Router_d.cc @@ -135,13 +135,13 @@ Router_d::route_req(flit_d *t_flit, InputUnit_d *in_unit, int invc) void Router_d::vcarb_req() { - m_vc_alloc->scheduleEvent(Cycles(1)); + m_vc_alloc->scheduleEventAbsolute(clockEdge(Cycles(1))); } void Router_d::swarb_req() { - m_sw_alloc->scheduleEvent(Cycles(1)); + m_sw_alloc->scheduleEventAbsolute(clockEdge(Cycles(1))); } void @@ -154,7 +154,7 @@ void Router_d::update_sw_winner(int inport, flit_d *t_flit) { m_switch->update_sw_winner(inport, t_flit); - m_switch->scheduleEvent(Cycles(1)); + m_switch->scheduleEventAbsolute(clockEdge(Cycles(1))); } void diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc index 79e295601e..870560af0f 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkInterface.cc @@ -321,7 +321,8 @@ NetworkInterface::scheduleOutputLink() outSrcQueue->insert(t_flit); // schedule the out link - outNetLink->scheduleEvent(Cycles(1)); + outNetLink-> + scheduleEventAbsolute(m_net_ptr->clockEdge(Cycles(1))); return; } } diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc index cdcd5a6224..9881d80631 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/NetworkLink.cc @@ -140,7 +140,8 @@ NetworkLink::wakeup() flit *t_flit = link_srcQueue->getTopFlit(); t_flit->set_time(curCycle() + m_latency); linkBuffer->insert(t_flit); - link_consumer->scheduleEvent(m_latency); + link_consumer->scheduleEventAbsolute(clockEdge(m_latency)); + m_link_utilized++; m_vc_load[t_flit->get_vc()]++; } diff --git a/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc b/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc index 98317818bc..851ababc41 100644 --- a/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc +++ b/src/mem/ruby/network/garnet/flexible-pipeline/Router.cc @@ -139,7 +139,7 @@ Router::request_vc(int in_vc, int in_port, NetDest destination, m_in_vc_state[in_port][in_vc]->setState(VC_AB_, request_time); assert(request_time >= curCycle()); if (request_time > curCycle()) - m_vc_arbiter->scheduleEventAbsolute(request_time); + m_vc_arbiter->scheduleEventAbsolute(clockPeriod() * request_time); else vc_arbitrate(); } @@ -364,7 +364,9 @@ Router::scheduleOutputLinks() m_router_buffers[port][vc_tolookat]->getTopFlit(); t_flit->set_time(curCycle() + Cycles(1)); m_out_src_queue[port]->insert(t_flit); - m_out_link[port]->scheduleEvent(Cycles(1)); + + m_out_link[port]-> + scheduleEventAbsolute(clockEdge(Cycles(1))); break; // done for this port } } @@ -400,7 +402,7 @@ Router::check_arbiter_reschedule() for (int vc = 0; vc < m_num_vcs; vc++) { if (m_in_vc_state[port][vc]->isInState(VC_AB_, curCycle() + Cycles(1))) { - m_vc_arbiter->scheduleEvent(Cycles(1)); + m_vc_arbiter->scheduleEventAbsolute(clockEdge(Cycles(1))); return; } } diff --git a/src/mem/ruby/system/RubyMemoryControl.cc b/src/mem/ruby/system/RubyMemoryControl.cc index 78fe690602..75e6e1b06e 100644 --- a/src/mem/ruby/system/RubyMemoryControl.cc +++ b/src/mem/ruby/system/RubyMemoryControl.cc @@ -384,7 +384,7 @@ RubyMemoryControl::enqueueToDirectory(MemoryNode req, Cycles latency) req.m_addr, req.m_is_mem_read ? 'R':'W', arrival_time); // schedule the wake up - m_consumer_ptr->scheduleEventAbsolute(ruby_arrival_time); + m_consumer_ptr->scheduleEventAbsolute(arrival_time); } // getBank returns an integer that is unique for each diff --git a/src/mem/ruby/system/TimerTable.cc b/src/mem/ruby/system/TimerTable.cc index d294916113..38e26e5e9e 100644 --- a/src/mem/ruby/system/TimerTable.cc +++ b/src/mem/ruby/system/TimerTable.cc @@ -75,7 +75,8 @@ TimerTable::set(const Address& address, Cycles relative_latency) Cycles ready_time = m_clockobj_ptr->curCycle() + relative_latency; m_map[address] = ready_time; assert(m_consumer_ptr != NULL); - m_consumer_ptr->scheduleEventAbsolute(ready_time); + m_consumer_ptr-> + scheduleEventAbsolute(m_clockobj_ptr->clockPeriod() * ready_time); m_next_valid = false; // Don't always recalculate the next ready address diff --git a/src/mem/ruby/system/WireBuffer.cc b/src/mem/ruby/system/WireBuffer.cc index e0458550a5..8c7c9211ee 100644 --- a/src/mem/ruby/system/WireBuffer.cc +++ b/src/mem/ruby/system/WireBuffer.cc @@ -80,7 +80,8 @@ WireBuffer::enqueue(MsgPtr message, Cycles latency) MessageBufferNode thisNode(arrival_time, m_msg_counter, message); m_message_queue.push_back(thisNode); if (m_consumer_ptr != NULL) { - m_consumer_ptr->scheduleEventAbsolute(arrival_time); + m_consumer_ptr-> + scheduleEventAbsolute(g_system_ptr->clockPeriod() * arrival_time); } else { panic("No Consumer for WireBuffer! %s\n", *this); } @@ -128,7 +129,8 @@ WireBuffer::recycle() m_message_queue.back() = node; push_heap(m_message_queue.begin(), m_message_queue.end(), greater()); - m_consumer_ptr->scheduleEventAbsolute(node.m_time); + m_consumer_ptr-> + scheduleEventAbsolute(g_system_ptr->clockPeriod() * node.m_time); } bool