From b7ce3040ded7c0f9ddb024043f2587ea50a86586 Mon Sep 17 00:00:00 2001 From: Jason Lowe-Power Date: Thu, 24 Oct 2024 13:38:19 -0700 Subject: [PATCH] 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 --- src/mem/ruby/protocol/MESI_Three_Level.slicc | 2 +- .../ruby/protocol/MESI_Three_Level_HTM.slicc | 2 +- src/mem/ruby/protocol/chi/CHI.slicc | 2 +- src/mem/ruby/slicc_interface/ProtocolInfo.hh | 72 +++++++++++++++++++ src/mem/ruby/system/RubySystem.cc | 13 +++- src/mem/ruby/system/RubySystem.hh | 9 ++- src/mem/slicc/parser.py | 18 ++++- src/mem/slicc/symbols/StateMachine.py | 2 +- src/mem/slicc/symbols/SymbolTable.py | 54 ++++++++++++++ 9 files changed, 167 insertions(+), 7 deletions(-) create mode 100644 src/mem/ruby/slicc_interface/ProtocolInfo.hh diff --git a/src/mem/ruby/protocol/MESI_Three_Level.slicc b/src/mem/ruby/protocol/MESI_Three_Level.slicc index d37b937578..7bcf2ab089 100644 --- a/src/mem/ruby/protocol/MESI_Three_Level.slicc +++ b/src/mem/ruby/protocol/MESI_Three_Level.slicc @@ -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"; diff --git a/src/mem/ruby/protocol/MESI_Three_Level_HTM.slicc b/src/mem/ruby/protocol/MESI_Three_Level_HTM.slicc index 88afc2f3b2..dc85aab731 100644 --- a/src/mem/ruby/protocol/MESI_Three_Level_HTM.slicc +++ b/src/mem/ruby/protocol/MESI_Three_Level_HTM.slicc @@ -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"; diff --git a/src/mem/ruby/protocol/chi/CHI.slicc b/src/mem/ruby/protocol/chi/CHI.slicc index 4c9c191b6e..2eb3eaedba 100644 --- a/src/mem/ruby/protocol/chi/CHI.slicc +++ b/src/mem/ruby/protocol/chi/CHI.slicc @@ -1,4 +1,4 @@ -protocol "CHI"; +protocol "CHI" partial_func_reads; include "CHI-msg.sm"; include "CHI-cache.sm"; diff --git a/src/mem/ruby/slicc_interface/ProtocolInfo.hh b/src/mem/ruby/slicc_interface/ProtocolInfo.hh new file mode 100644 index 0000000000..76e9a58048 --- /dev/null +++ b/src/mem/ruby/slicc_interface/ProtocolInfo.hh @@ -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 + +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__ diff --git a/src/mem/ruby/system/RubySystem.cc b/src/mem/ruby/system/RubySystem.cc index 24cf686565..11f51161b0 100644 --- a/src/mem/ruby/system/RubySystem.cc +++ b/src/mem/ruby/system/RubySystem.cc @@ -97,12 +97,23 @@ RubySystem::registerNetwork(Network* network_ptr) } void -RubySystem::registerAbstractController(AbstractController* cntrl) +RubySystem::registerAbstractController( + AbstractController* cntrl, std::unique_ptr 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 diff --git a/src/mem/ruby/system/RubySystem.hh b/src/mem/ruby/system/RubySystem.hh index 7e18770230..4cce8b38c5 100644 --- a/src/mem/ruby/system/RubySystem.hh +++ b/src/mem/ruby/system/RubySystem.hh @@ -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 + ); 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 requestorToNetwork; std::unordered_map> netCntrls; + std::unique_ptr protocolInfo; + public: Profiler* m_profiler; CacheRecorder* m_cache_recorder; diff --git a/src/mem/slicc/parser.py b/src/mem/slicc/parser.py index f3a9ed2f11..c2bd7259a5 100644 --- a/src/mem/slicc/parser.py +++ b/src/mem/slicc/parser.py @@ -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): diff --git a/src/mem/slicc/symbols/StateMachine.py b/src/mem/slicc/symbols/StateMachine.py index 2f32a8320b..42f4c332d2 100644 --- a/src/mem/slicc/symbols/StateMachine.py +++ b/src/mem/slicc/symbols/StateMachine.py @@ -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; diff --git a/src/mem/slicc/symbols/SymbolTable.py b/src/mem/slicc/symbols/SymbolTable.py index a08f852cd8..338836d7c2 100644 --- a/src/mem/slicc/symbols/SymbolTable.py +++ b/src/mem/slicc/symbols/SymbolTable.py @@ -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)