From: Tiago Muck Date: Fri, 7 Jun 2019 23:16:10 +0000 (-0500) Subject: mem-ruby: Allow same-cycle enqueue X-Git-Tag: develop-gem5-snapshot~665 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=6ade44d50c2d04becd8ff94e9becd77a5165530d;p=gem5.git mem-ruby: Allow same-cycle enqueue Messages may be enqueued and be ready in the same cycle. Using this feature may introduce nondeterminism in the protocol and should be used in specific cases. A case study is to avoid needing an additional cycle for internal protocol triggers (e.g. the All_Acks event in src/mem/ruby/protocol/MOESI_CMP_directory-L2cache.sm). To mitigate modeling mistakes, the 'allow_zero_latency' parameter must be set for a MessageBuffer where this behavior is acceptable. This changes also updates the Consumer to schedule events according to this new behavior. The original implementation would not schedule a new wakeup event if the wakeup for the Consumer had already been executed in that cycle. Additional authors: - Tuan Ta Change-Id: Ib194e7b4b4ee4b06da1baea17c0eb743f650dfdd Signed-off-by: Tiago Mück Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31255 Reviewed-by: Jason Lowe-Power Maintainer: Jason Lowe-Power Tested-by: kokoro --- diff --git a/src/mem/ruby/common/Consumer.cc b/src/mem/ruby/common/Consumer.cc index f68ee14d0..d5db71782 100644 --- a/src/mem/ruby/common/Consumer.cc +++ b/src/mem/ruby/common/Consumer.cc @@ -1,4 +1,16 @@ /* + * Copyright (c) 2020 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 2012 Mark D. Hill and David A. Wood * All rights reserved. * @@ -30,26 +42,51 @@ using namespace std; +Consumer::Consumer(ClockedObject *_em) + : m_wakeup_event([this]{ processCurrentEvent(); }, + "Consumer Event", false), + em(_em) +{ } + void Consumer::scheduleEvent(Cycles timeDelta) { - scheduleEventAbsolute(em->clockEdge(timeDelta)); + m_wakeup_ticks.insert(em->clockEdge(timeDelta)); + scheduleNextWakeup(); } void Consumer::scheduleEventAbsolute(Tick evt_time) { - if (!alreadyScheduled(evt_time)) { - // This wakeup is not redundant - auto *evt = new EventFunctionWrapper( - [this]{ wakeup(); }, "Consumer Event", true); + m_wakeup_ticks.insert( + divCeil(evt_time, em->clockPeriod()) * em->clockPeriod()); + scheduleNextWakeup(); +} - em->schedule(evt, evt_time); - insertScheduledWakeupTime(evt_time); +void +Consumer::scheduleNextWakeup() +{ + // look for the next tick in the future to schedule + auto it = m_wakeup_ticks.lower_bound(em->clockEdge()); + if (it != m_wakeup_ticks.end()) { + Tick when = *it; + assert(when >= em->clockEdge()); + if (m_wakeup_event.scheduled() && (when < m_wakeup_event.when())) + em->reschedule(m_wakeup_event, when, true); + else if (!m_wakeup_event.scheduled()) + em->schedule(m_wakeup_event, when); } +} + +void +Consumer::processCurrentEvent() +{ + auto curr = m_wakeup_ticks.begin(); + assert(em->clockEdge() == *curr); - Tick t = em->clockEdge(); - set::iterator bit = m_scheduled_wakeups.begin(); - set::iterator eit = m_scheduled_wakeups.lower_bound(t); - m_scheduled_wakeups.erase(bit,eit); + // remove the current tick from the wakeup list, wake up, and then schedule + // the next wakeup + m_wakeup_ticks.erase(curr); + wakeup(); + scheduleNextWakeup(); } diff --git a/src/mem/ruby/common/Consumer.hh b/src/mem/ruby/common/Consumer.hh index 2e1868403..2c7065bfe 100644 --- a/src/mem/ruby/common/Consumer.hh +++ b/src/mem/ruby/common/Consumer.hh @@ -1,4 +1,16 @@ /* + * Copyright (c) 2020 ARM Limited + * All rights reserved. + * + * The license below extends only to copyright in the software and shall + * not be construed as granting a license to any other intellectual + * property including but not limited to intellectual property relating + * to a hardware implementation of the functionality of the software + * licensed hereunder. You may use the software subject to the license + * terms below provided that you ensure that this notice is replicated + * unmodified and in its entirety in all distributions of the software, + * modified or unmodified, in source code or in binary form. + * * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood * All rights reserved. * @@ -43,10 +55,7 @@ class Consumer { public: - Consumer(ClockedObject *_em) - : em(_em) - { - } + Consumer(ClockedObject *_em); virtual ~Consumer() @@ -59,13 +68,7 @@ class Consumer bool alreadyScheduled(Tick time) { - return m_scheduled_wakeups.find(time) != m_scheduled_wakeups.end(); - } - - void - insertScheduledWakeupTime(Tick time) - { - m_scheduled_wakeups.insert(time); + return m_wakeup_ticks.find(time) != m_wakeup_ticks.end(); } ClockedObject * @@ -74,15 +77,19 @@ class Consumer return em; } - void scheduleEventAbsolute(Tick timeAbs); void scheduleEvent(Cycles timeDelta); private: - std::set m_scheduled_wakeups; + std::set m_wakeup_ticks; + EventFunctionWrapper m_wakeup_event; ClockedObject *em; + + void scheduleNextWakeup(); + void processCurrentEvent(); }; + inline std::ostream& operator<<(std::ostream& out, const Consumer& obj) { diff --git a/src/mem/ruby/network/MessageBuffer.cc b/src/mem/ruby/network/MessageBuffer.cc index fb1d734dc..8843694bd 100644 --- a/src/mem/ruby/network/MessageBuffer.cc +++ b/src/mem/ruby/network/MessageBuffer.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 ARM Limited + * Copyright (c) 2019,2020 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -57,7 +57,8 @@ MessageBuffer::MessageBuffer(const Params *p) m_max_size(p->buffer_size), m_time_last_time_size_checked(0), m_time_last_time_enqueue(0), m_time_last_time_pop(0), m_last_arrival_time(0), m_strict_fifo(p->ordered), - m_randomization(p->randomization) + m_randomization(p->randomization), + m_allow_zero_latency(p->allow_zero_latency) { m_msg_counter = 0; m_consumer = NULL; @@ -172,7 +173,7 @@ MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) // Calculate the arrival time of the message, that is, the first // cycle the message can be dequeued. - assert(delta > 0); + assert((delta > 0) || m_allow_zero_latency); Tick arrival_time = 0; // random delays are inserted if either RubySystem level randomization flag @@ -193,7 +194,7 @@ MessageBuffer::enqueue(MsgPtr message, Tick current_time, Tick delta) } // Check the arrival time - assert(arrival_time > current_time); + assert(arrival_time >= current_time); if (m_strict_fifo) { if (arrival_time < m_last_arrival_time) { panic("FIFO ordering violated: %s name: %s current time: %d " diff --git a/src/mem/ruby/network/MessageBuffer.hh b/src/mem/ruby/network/MessageBuffer.hh index 8abf3bd63..3887340e5 100644 --- a/src/mem/ruby/network/MessageBuffer.hh +++ b/src/mem/ruby/network/MessageBuffer.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 ARM Limited + * Copyright (c) 2019,2020 ARM Limited * All rights reserved. * * The license below extends only to copyright in the software and shall @@ -249,6 +249,7 @@ class MessageBuffer : public SimObject int m_priority_rank; const bool m_strict_fifo; const bool m_randomization; + const bool m_allow_zero_latency; int m_input_link_id; int m_vnet_id; diff --git a/src/mem/ruby/network/MessageBuffer.py b/src/mem/ruby/network/MessageBuffer.py index a0a208fca..297835f1e 100644 --- a/src/mem/ruby/network/MessageBuffer.py +++ b/src/mem/ruby/network/MessageBuffer.py @@ -1,3 +1,15 @@ +# Copyright (c) 2020 ARM Limited +# All rights reserved. +# +# The license below extends only to copyright in the software and shall +# not be construed as granting a license to any other intellectual +# property including but not limited to intellectual property relating +# to a hardware implementation of the functionality of the software +# licensed hereunder. You may use the software subject to the license +# terms below provided that you ensure that this notice is replicated +# unmodified and in its entirety in all distributions of the software, +# modified or unmodified, in source code or in binary form. +# # Copyright (c) 2015 Mark D. Hill and David A. Wood. # All rights reserved. # @@ -39,6 +51,11 @@ class MessageBuffer(SimObject): enqueue times (enforced to have \ random delays if RubySystem \ randomization flag is True)") + allow_zero_latency = Param.Bool(False, "Allows messages to be enqueued \ + with zero latency. This is useful \ + for internall trigger queues and \ + should not be used if this msg. \ + buffer connects different objects") out_port = RequestPort("Request port to MessageBuffer receiver") master = DeprecatedParam(out_port, '`master` is now called `out_port`')