mem-ruby: Allow same-cycle enqueue
authorTiago Muck <tiago.muck@arm.com>
Fri, 7 Jun 2019 23:16:10 +0000 (18:16 -0500)
committerTiago Mück <tiago.muck@arm.com>
Fri, 9 Oct 2020 00:07:27 +0000 (00:07 +0000)
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 <tuan.ta2@arm.com>

Change-Id: Ib194e7b4b4ee4b06da1baea17c0eb743f650dfdd
Signed-off-by: Tiago Mück <tiago.muck@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/31255
Reviewed-by: Jason Lowe-Power <power.jg@gmail.com>
Maintainer: Jason Lowe-Power <power.jg@gmail.com>
Tested-by: kokoro <noreply+kokoro@google.com>
src/mem/ruby/common/Consumer.cc
src/mem/ruby/common/Consumer.hh
src/mem/ruby/network/MessageBuffer.cc
src/mem/ruby/network/MessageBuffer.hh
src/mem/ruby/network/MessageBuffer.py

index f68ee14d0401a6c9de98f25f853ec8602050fe91..d5db71782609c42978c71c04351c1533c8f81a60 100644 (file)
@@ -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.
  *
 
 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<Tick>::iterator bit = m_scheduled_wakeups.begin();
-    set<Tick>::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();
 }
index 2e18684031e28dcbd8eef1c282fcc72eae1e32ab..2c7065bfef3069bc23656e985982f9a30b2de605 100644 (file)
@@ -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.
  *
 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<Tick> m_scheduled_wakeups;
+    std::set<Tick> m_wakeup_ticks;
+    EventFunctionWrapper m_wakeup_event;
     ClockedObject *em;
+
+    void scheduleNextWakeup();
+    void processCurrentEvent();
 };
 
+
 inline std::ostream&
 operator<<(std::ostream& out, const Consumer& obj)
 {
index fb1d734dce570bec27ffdba6c8ddbeaee1b96539..8843694bd728ca14943b12fa51b8765d1d605952 100644 (file)
@@ -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 "
index 8abf3bd63659b7de56b823794f9c6777ee45e247..3887340e561d491b1daf018136fea92cd7cf3e27 100644 (file)
@@ -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;
index a0a208fca47ee5d407200b6e88f7ae4c7c69f069..297835f1e523e5304fd2f7c0a6d714c4ba4cd885 100644 (file)
@@ -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`')