m_stall_count++;
}
+void
+MessageBuffer::deferEnqueueingMessage(Addr addr, MsgPtr message)
+{
+ DPRINTF(RubyQueue, "Deferring enqueueing message: %s, Address %#x\n",
+ *(message.get()), addr);
+ (m_deferred_msg_map[addr]).push_back(message);
+}
+
+void
+MessageBuffer::enqueueDeferredMessages(Addr addr, Tick curTime, Tick delay)
+{
+ assert(!isDeferredMsgMapEmpty(addr));
+ std::vector<MsgPtr>& msg_vec = m_deferred_msg_map[addr];
+ assert(msg_vec.size() > 0);
+
+ // enqueue all deferred messages associated with this address
+ for (MsgPtr m : msg_vec) {
+ enqueue(m, curTime, delay);
+ }
+
+ msg_vec.clear();
+ m_deferred_msg_map.erase(addr);
+}
+
+bool
+MessageBuffer::isDeferredMsgMapEmpty(Addr addr) const
+{
+ return m_deferred_msg_map.count(addr) == 0;
+}
+
void
MessageBuffer::print(ostream& out) const
{
#include <functional>
#include <iostream>
#include <string>
+#include <unordered_map>
#include <vector>
#include "base/trace.hh"
void enqueue(MsgPtr message, Tick curTime, Tick delta);
+ // Defer enqueueing a message to a later cycle by putting it aside and not
+ // enqueueing it in this cycle
+ // The corresponding controller will need to explicitly enqueue the
+ // deferred message into the message buffer. Otherwise, the message will
+ // be lost.
+ void deferEnqueueingMessage(Addr addr, MsgPtr message);
+
+ // enqueue all previously deferred messages that are associated with the
+ // input address
+ void enqueueDeferredMessages(Addr addr, Tick curTime, Tick delay);
+
+ bool isDeferredMsgMapEmpty(Addr addr) const;
+
//! Updates the delay cycles of the message at the head of the queue,
//! removes it from the queue and returns its total delay.
Tick dequeue(Tick current_time, bool decrement_messages = true);
*/
StallMsgMapType m_stall_msg_map;
+ /**
+ * A map from line addresses to corresponding vectors of messages that
+ * are deferred for enqueueing. Messages in this map are waiting to be
+ * enqueued into the message buffer.
+ */
+ typedef std::unordered_map<Addr, std::vector<MsgPtr>> DeferredMsgMapType;
+ DeferredMsgMapType m_deferred_msg_map;
+
/**
* Current size of the stall map.
* Track the number of messages held in stall map lists. This is used to
//
external_type(MessageBuffer, buffer="yes", inport="yes", outport="yes");
-external_type(OutPort, primitive="yes");
external_type(Scalar, primitive="yes");
+structure(OutPort, external = "yes", primitive="yes") {
+ void enqueueDeferredMessages(Addr addr, Tick curTime, Tick delay);
+ bool isDeferredMsgMapEmpty(Addr addr);
+}
+
structure(InPort, external = "yes", primitive="yes") {
bool isReady(Tick current_time);
Tick dequeue(Tick current_time);
--- /dev/null
+#
+# Copyright (c) 2017 Advanced Micro Devices, Inc.
+# All rights reserved.
+#
+# For use for simulation and test purposes only
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice,
+# this list of conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its
+# contributors may be used to endorse or promote products derived from this
+# software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Authors: Tuan Ta
+#
+
+from slicc.ast.StatementAST import StatementAST
+from slicc.symbols import Var
+
+class DeferEnqueueingStatementAST(StatementAST):
+ def __init__(self, slicc, queue_name, type_ast, statements):
+ super(DeferEnqueueingStatementAST, self).__init__(slicc)
+
+ self.queue_name = queue_name
+ self.type_ast = type_ast
+ self.statements = statements
+
+ def __repr__(self):
+ return "[DeferEnqueueingStatementAst: %s %s %s]" % \
+ (self.queue_name, self.type_ast.ident, self.statements)
+
+ def generate(self, code, return_type):
+ code("{")
+ code.indent()
+ self.symtab.pushFrame()
+
+ msg_type = self.type_ast.type
+
+ # Add new local var to symbol table
+ v = Var(self.symtab, "out_msg", self.location, msg_type, "*out_msg",
+ self.pairs)
+ self.symtab.newSymbol(v)
+
+ # Declare message
+ code("std::shared_ptr<${{msg_type.c_ident}}> out_msg = "\
+ "std::make_shared<${{msg_type.c_ident}}>(clockEdge());")
+
+ # The other statements
+ t = self.statements.generate(code, None)
+ self.queue_name.assertType("OutPort")
+
+ code("(${{self.queue_name.var.code}}).deferEnqueueingMessage(addr, "\
+ "out_msg);")
+
+ # End scope
+ self.symtab.popFrame()
+ code.dedent()
+ code("}")
+
+ def findResources(self, resources):
+ var = self.queue_name.var
+ res_count = int(resources.get(var, 0))
+ resources[var] = str(res_count + 1)
from slicc.ast.CheckNextCycleAST import *
from slicc.ast.DeclAST import *
from slicc.ast.DeclListAST import *
+from slicc.ast.DeferEnqueueingStatementAST import *
from slicc.ast.EnqueueStatementAST import *
from slicc.ast.EnumDeclAST import *
from slicc.ast.EnumExprAST import *
'void' : 'VOID',
'new' : 'NEW',
'OOD' : 'OOD',
+ 'defer_enqueueing' : 'DEFER_ENQUEUEING',
}
literals = ':[]{}(),='
"statement : ENQUEUE '(' var ',' type ',' expr ')' statements"
p[0] = ast.EnqueueStatementAST(self, p[3], p[5], p[7], p[9])
+ def p_statement__defer_enqueueing(self, p):
+ "statement : DEFER_ENQUEUEING '(' var ',' type ')' statements"
+ p[0] = ast.DeferEnqueueingStatementAST(self, p[3], p[5], p[7])
+
def p_statement__stall_and_wait(self, p):
"statement : STALL_AND_WAIT '(' var ',' var ')' SEMI"
p[0] = ast.StallAndWaitStatementAST(self, p[3], p[5])