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 <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>
This commit is contained in:
@@ -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);
|
||||
|
||||
em->schedule(evt, evt_time);
|
||||
insertScheduledWakeupTime(evt_time);
|
||||
}
|
||||
|
||||
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);
|
||||
m_wakeup_ticks.insert(
|
||||
divCeil(evt_time, em->clockPeriod()) * em->clockPeriod());
|
||||
scheduleNextWakeup();
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// remove the current tick from the wakeup list, wake up, and then schedule
|
||||
// the next wakeup
|
||||
m_wakeup_ticks.erase(curr);
|
||||
wakeup();
|
||||
scheduleNextWakeup();
|
||||
}
|
||||
|
||||
@@ -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<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)
|
||||
{
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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`')
|
||||
|
||||
Reference in New Issue
Block a user