mem-ruby: Add ProtocolInfo class

Add a ProtocolInfo class that is specialized (through inheritance) for
each protocol. This class currently has the protocol's name and any
protocol-specific options (partial_func_reads is the only one so far).
Note that the SLICC language has been updated so that you can specify
the options in the `protocol` statement in the `.slicc` file.

Signed-off-by: Jason Lowe-Power <jason@lowepower.com>
This commit is contained in:
Jason Lowe-Power
2024-10-24 13:38:19 -07:00
committed by Bobby R. Bruce
parent 4f53451073
commit b7ce3040de
9 changed files with 167 additions and 7 deletions

View File

@@ -1,4 +1,4 @@
protocol "MESI_Three_Level";
protocol "MESI_Three_Level" use_secondary_store_conditional;
include "MESI_Two_Level-msg.sm";
include "MESI_Three_Level-msg.sm";
include "MESI_Three_Level-L0cache.sm";

View File

@@ -1,4 +1,4 @@
protocol "MESI_Three_Level_HTM";
protocol "MESI_Three_Level_HTM" use_secondary_store_conditional;
include "MESI_Two_Level-msg.sm";
include "MESI_Three_Level-msg.sm";
include "MESI_Three_Level_HTM-L0cache.sm";

View File

@@ -1,4 +1,4 @@
protocol "CHI";
protocol "CHI" partial_func_reads;
include "CHI-msg.sm";
include "CHI-cache.sm";

View File

@@ -0,0 +1,72 @@
/* Copyright (c) 2024 Jason Lowe-Power
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met: redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer;
* 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;
* neither the name of the copyright holders 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
* OWNER 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.
*/
#ifndef __MEM_RUBY_SLICC_INTERFACE_PROTOCOL_INFO_HH__
#define __MEM_RUBY_SLICC_INTERFACE_PROTOCOL_INFO_HH__
#include <string>
namespace gem5 {
namespace ruby {
/*
* This class is used to store information about a protocol.
* Each protocol will inherit from this class and define the values
* To add a new option, update this file and slicc/parser.py self.options
*/
class ProtocolInfo
{
private:
const std::string name;
protected:
const bool partialFuncReads;
const bool useSecondaryStoreConditional;
public:
ProtocolInfo(std::string name, bool partial_func_reads,
bool use_secondary_store_conditional) :
name(name),
partialFuncReads(partial_func_reads),
useSecondaryStoreConditional(use_secondary_store_conditional)
{
}
std::string getName() const { return name; }
bool getPartialFuncReads() const { return partialFuncReads; }
bool
getUseSecondaryStoreConditional() const
{
return useSecondaryStoreConditional;
}
};
} // namespace ruby
} // namespace gem5
#endif // __MEM_RUBY_SLICC_INTERFACE_PROTOCOL_INFO_HH__

View File

@@ -97,12 +97,23 @@ RubySystem::registerNetwork(Network* network_ptr)
}
void
RubySystem::registerAbstractController(AbstractController* cntrl)
RubySystem::registerAbstractController(
AbstractController* cntrl, std::unique_ptr<ProtocolInfo> cntl_protocol)
{
m_abs_cntrl_vec.push_back(cntrl);
MachineID id = cntrl->getMachineID();
m_abstract_controls[id.getType()][id.getNum()] = cntrl;
if (!protocolInfo) {
protocolInfo = std::move(cntl_protocol);
} else {
fatal_if(
protocolInfo->getName() != cntl_protocol->getName(),
"All controllers in a system must use the same protocol. %s != %s",
protocolInfo->getName().c_str(), cntl_protocol->getName().c_str()
);
}
}
void

View File

@@ -42,6 +42,7 @@
#include "mem/packet.hh"
#include "mem/ruby/profiler/Profiler.hh"
#include "mem/ruby/slicc_interface/AbstractController.hh"
#include "mem/ruby/slicc_interface/ProtocolInfo.hh"
#include "mem/ruby/system/CacheRecorder.hh"
#include "params/RubySystem.hh"
#include "sim/clocked_object.hh"
@@ -104,7 +105,9 @@ class RubySystem : public ClockedObject
bool functionalWrite(Packet *ptr);
void registerNetwork(Network*);
void registerAbstractController(AbstractController*);
void registerAbstractController(
AbstractController*, std::unique_ptr<ProtocolInfo>
);
void registerMachineID(const MachineID& mach_id, Network* network);
void registerRequestorIDs();
@@ -116,6 +119,8 @@ class RubySystem : public ClockedObject
schedule(e, tick);
}
const ProtocolInfo& getProtocolInfo() { return *protocolInfo; }
private:
// Private copy constructor and assignment operator
RubySystem(const RubySystem& obj);
@@ -153,6 +158,8 @@ class RubySystem : public ClockedObject
std::unordered_map<RequestorID, unsigned> requestorToNetwork;
std::unordered_map<unsigned, std::vector<AbstractController*>> netCntrls;
std::unique_ptr<ProtocolInfo> protocolInfo;
public:
Profiler* m_profiler;
CacheRecorder* m_cache_recorder;

View File

@@ -72,6 +72,12 @@ class SLICC(Grammar):
self.symtab = SymbolTable(self)
self.base_dir = base_dir
# Update slicc_interface/ProtocolInfo.cc/hh if updating this.
self.options = {
"partial_func_reads": False,
"use_secondary_store_conditional": False,
}
if not includes:
# raise error
pass
@@ -305,7 +311,7 @@ class SLICC(Grammar):
p[0] = []
def p_decl__protocol(self, p):
"decl : PROTOCOL STRING SEMI"
"decl : PROTOCOL STRING exprs SEMI"
if self.protocol:
msg = "Protocol can only be set once! Error at {}:{}\n".format(
self.current_source,
@@ -313,6 +319,16 @@ class SLICC(Grammar):
)
raise ParseError(msg)
self.protocol = p[2]
# Check for options
for option in p[3]:
assert type(option) is ast.VarExprAST
if option.name in self.options:
self.options[option.name] = True
else:
raise ParseError(
f"Unknown option '{option.name}' for protocol "
f"at {self.current_source}:{self.current_line}"
)
p[0] = None
def p_decl__include(self, p):

View File

@@ -699,7 +699,7 @@ $c_ident::$c_ident(const Params &p)
m_machineID.type = MachineType_${ident};
m_machineID.num = m_version;
p.ruby_system->m_num_controllers[MachineType_${ident}]++;
p.ruby_system->registerAbstractController(this);
p.ruby_system->registerAbstractController(this, std::make_unique<${protocol}ProtocolInfo>());
m_ruby_system = p.ruby_system;
m_in_ports = $num_in_ports;

View File

@@ -149,11 +149,65 @@ class SymbolTable:
ident = f"{self.slicc.protocol}/{ident}"
code('#include "mem/ruby/protocol/${{ident}}.hh"')
code(
f'#include "mem/ruby/protocol/{self.slicc.protocol}/{self.slicc.protocol}ProtocolInfo.hh"'
)
code.write(path, f"{self.slicc.protocol}/Types.hh")
self.writeProtocolInfo(path)
for symbol in self.sym_vec:
symbol.writeCodeFiles(path, includes)
def writeProtocolInfo(self, path):
code = self.codeFormatter()
code(
f"""
#ifndef __MEM_RUBY_PROTOCOL_{self.slicc.protocol}_{self.slicc.protocol}PROTOCOL_INFO_HH__
#define __MEM_RUBY_PROTOCOL_{self.slicc.protocol}_{self.slicc.protocol}PROTOCOL_INFO_HH__
#include "mem/ruby/slicc_interface/ProtocolInfo.hh"
namespace gem5
{{
namespace ruby
{{
namespace {self.slicc.protocol}
{{
class {self.slicc.protocol}ProtocolInfo : public ProtocolInfo
{{
public:
{self.slicc.protocol}ProtocolInfo() :
ProtocolInfo("{self.slicc.protocol}",
"""
)
options = ",\n".join(
[
f" {'true' if value else 'false'}"
for _, value in self.slicc.options.items()
]
)
code(options)
code(
f""" )
{{
}}
}};
}}
}}
}}
#endif // __MEM_RUBY_PROTOCOL_{self.slicc.protocol}_{self.slicc.protocol}PROTOCOL_INFO_HH__
"""
)
code.write(
path, f"{self.slicc.protocol}/{self.slicc.protocol}ProtocolInfo.hh"
)
def writeHTMLFiles(self, path):
makeDir(path)