mem-ruby: add slicc stm to defer enqueueing a message
This patch enables cache controllers to make response messages in advance, store them in a per-address saved map in an output message buffer and enqueue them altogether in the future. This patch introduces new slicc statement called defer_enqueueing. This patch would help simplify the logic of state machines that deal with coalesing multiple requests from different requestors. Change-Id: I566d4004498b367764238bb251260483c5a1a5e5 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/28132 Reviewed-by: Tuan Ta <qtt2@cornell.edu> 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:
committed by
Anthony Gutierrez
parent
90332c45b5
commit
524c22041d
@@ -394,6 +394,36 @@ MessageBuffer::stallMessage(Addr addr, Tick current_time)
|
||||
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
|
||||
{
|
||||
|
||||
@@ -51,6 +51,7 @@
|
||||
#include <functional>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "base/trace.hh"
|
||||
@@ -113,6 +114,19 @@ class MessageBuffer : public SimObject
|
||||
|
||||
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);
|
||||
@@ -191,6 +205,14 @@ class MessageBuffer : public SimObject
|
||||
*/
|
||||
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
|
||||
|
||||
@@ -49,9 +49,13 @@
|
||||
//
|
||||
|
||||
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);
|
||||
|
||||
82
src/mem/slicc/ast/DeferEnqueueingStatementAST.py
Normal file
82
src/mem/slicc/ast/DeferEnqueueingStatementAST.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#
|
||||
# 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)
|
||||
@@ -33,6 +33,7 @@ from slicc.ast.CheckAllocateStatementAST import *
|
||||
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 *
|
||||
|
||||
@@ -120,6 +120,7 @@ class SLICC(Grammar):
|
||||
'void' : 'VOID',
|
||||
'new' : 'NEW',
|
||||
'OOD' : 'OOD',
|
||||
'defer_enqueueing' : 'DEFER_ENQUEUEING',
|
||||
}
|
||||
|
||||
literals = ':[]{}(),='
|
||||
@@ -583,6 +584,10 @@ class SLICC(Grammar):
|
||||
"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])
|
||||
|
||||
Reference in New Issue
Block a user