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:
committed by
Bobby R. Bruce
parent
4f53451073
commit
b7ce3040de
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
protocol "CHI";
|
||||
protocol "CHI" partial_func_reads;
|
||||
|
||||
include "CHI-msg.sm";
|
||||
include "CHI-cache.sm";
|
||||
|
||||
72
src/mem/ruby/slicc_interface/ProtocolInfo.hh
Normal file
72
src/mem/ruby/slicc_interface/ProtocolInfo.hh
Normal 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__
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user