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.
This commit is contained in:
@@ -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<MessageBufferNode>());
|
||||
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<MessageBufferNode>());
|
||||
|
||||
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<MessageBufferNode>());
|
||||
|
||||
m_consumer_ptr->scheduleEventAbsolute(msgNode.m_time);
|
||||
m_consumer_ptr->
|
||||
scheduleEventAbsolute(m_receiver_ptr->clockPeriod() * nextCycle);
|
||||
(map_iter->second).pop_front();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_) {
|
||||
|
||||
@@ -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()]++;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()]++;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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<MessageBufferNode>());
|
||||
m_consumer_ptr->scheduleEventAbsolute(node.m_time);
|
||||
m_consumer_ptr->
|
||||
scheduleEventAbsolute(g_system_ptr->clockPeriod() * node.m_time);
|
||||
}
|
||||
|
||||
bool
|
||||
|
||||
Reference in New Issue
Block a user