From 549eb057075bdb51d7c12d84cb1763ddac180e79 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 8 May 2025 15:18:25 -0400 Subject: [PATCH 01/45] initial commit with barebones header on new element --- src/sst/elements/carcosa/faultInjectorBase.h | 55 ++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 src/sst/elements/carcosa/faultInjectorBase.h diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h new file mode 100644 index 0000000000..9ad8846155 --- /dev/null +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -0,0 +1,55 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_FAULTINJECTORBASE_H +#define SST_ELEMENTS_CARCOSA_FAULTINJECTORBASE_H + +#include "sst/core/component.h" +#include "sst/core/event.h" + +namespace SST::FaultInjectorBase { + +/** + * Base class containing required virtual functions and basic required data for + * creating fault injection on component ports + */ +class FaultInjectorBase : public SST::PortModule +{ +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "faultInjectorBase", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "Barebones PortModule used to connect fault injection logic to components" + ) + + SST_ELI_DOCUMENT_PARAMS( + // + ) + + FaultInjectorBase(Params& params); + + FaultInjectorBase() = dafault; + ~FaultInjectorBase() {} + + void eventSent(uintptr_t key, Event*& ev) override; + void interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; + + bool installOnReceive() override; + bool installOnSend() override; + +private: + void (*eventSentPtr)(uintptr_t, Event*&); + void (*interceptHandlerPtr)(uintptr_t, Event*&, bool&); +} + +} // namespace SST::FaultInjectorBase \ No newline at end of file From 62f6f4d5b0834f8efe1cec48660d47a23aed8d3a Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 8 May 2025 15:29:56 -0400 Subject: [PATCH 02/45] add files necessary for compilation --- src/sst/elements/carcosa/Makefile.am | 27 +++++++++++++++++++++ src/sst/elements/carcosa/configure.m4 | 9 +++++++ src/sst/elements/carcosa/tests/dummyTest.py | 0 3 files changed, 36 insertions(+) create mode 100644 src/sst/elements/carcosa/Makefile.am create mode 100644 src/sst/elements/carcosa/configure.m4 create mode 100644 src/sst/elements/carcosa/tests/dummyTest.py diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am new file mode 100644 index 0000000000..7a0853ee5f --- /dev/null +++ b/src/sst/elements/carcosa/Makefile.am @@ -0,0 +1,27 @@ +# -*- Makefile -*- +# +# + +AM_CPPFLAGS += \ + $(MPI_CPPFLAGS) \ + -I$(top_srcdir)/src + +compdir = $(pkglibdir) +comp_LTLIBRARIES = libcarcosa.la +libcarcosa_la_SOURCES = \ + faultInjectorBase.h + +EXTRA_DIST = \ + dummyTest.py + +sstdir = $(includedir)/sst/elements/carcosa +nobase_sst_HEADERS = \ + faultInjectorBase.h + +libcarcosa_la_LDFLAGS = -module -avoid-version +libcarcosa_la_LIBADD = + +AM_CPPFLAGS += $(HMC_FLAG) +install-exec-hook: + $(SST_REGISTER_TOOL) SST_ELEMENT_SOURCE carcosa=$(abs_srcdir) + $(SST_REGISTER_TOOL) SST_ELEMENT_TESTS carcosa=$(abs_srcdir)/tests diff --git a/src/sst/elements/carcosa/configure.m4 b/src/sst/elements/carcosa/configure.m4 new file mode 100644 index 0000000000..a47dc7ab12 --- /dev/null +++ b/src/sst/elements/carcosa/configure.m4 @@ -0,0 +1,9 @@ +dnl -*- Autoconf -*- +dnl vim:ft=config +dnl + +AC_DEFUN([SST_carcosa_CONFIG], [ + carcosa_happy="yes" + + AS_IF([test "$carcosa_happy" = "yes"], [$1], [$2]) +]) diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py new file mode 100644 index 0000000000..e69de29bb2 From 71be5f9be0fb1ceba975fb1ccdd321b0053f1e78 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 8 May 2025 15:31:34 -0400 Subject: [PATCH 03/45] fix some basic syntax issues --- src/sst/elements/carcosa/faultInjectorBase.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 9ad8846155..41e0d1cbe1 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -38,7 +38,7 @@ class FaultInjectorBase : public SST::PortModule FaultInjectorBase(Params& params); - FaultInjectorBase() = dafault; + FaultInjectorBase() = default; ~FaultInjectorBase() {} void eventSent(uintptr_t key, Event*& ev) override; @@ -50,6 +50,8 @@ class FaultInjectorBase : public SST::PortModule private: void (*eventSentPtr)(uintptr_t, Event*&); void (*interceptHandlerPtr)(uintptr_t, Event*&, bool&); -} +}; -} // namespace SST::FaultInjectorBase \ No newline at end of file +} // namespace SST::FaultInjectorBase + +#endif // SST_ELEMENTS_CARCOSA_FAULTINJECTORBASE_H \ No newline at end of file From 2a156b378960acc6b3d63a4cdff7a3d7d32ec4ee Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 8 May 2025 17:09:54 -0400 Subject: [PATCH 04/45] create impl file for baseline injector update Makefile.am to include impl file fix serialization to stop compiler errors and warnings --- src/sst/elements/carcosa/Makefile.am | 1 + src/sst/elements/carcosa/faultInjectorBase.cc | 60 +++++++++++++++++++ src/sst/elements/carcosa/faultInjectorBase.h | 55 ++++++++++++++--- 3 files changed, 109 insertions(+), 7 deletions(-) create mode 100644 src/sst/elements/carcosa/faultInjectorBase.cc diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 7a0853ee5f..0ea4b4d1e7 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -9,6 +9,7 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la libcarcosa_la_SOURCES = \ + faultInjectorBase.cc \ faultInjectorBase.h EXTRA_DIST = \ diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc new file mode 100644 index 0000000000..04e31b0577 --- /dev/null +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -0,0 +1,60 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "faultInjectorBase.h" + +using namespace SST::Carcosa; + +/********** FaultInjectorBase **********/ + +FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() +{ +#ifdef DEBUG + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n") +#endif + std::string install_dir = params.find("installDirection", "Receive"); + + if ( install_dir != "Receive" ) { + if ( install_dir == "Send" ) { + installDirection_ = installDirection::Send; + } else if ( install_dir == "Both" ) { + installDirection_ = installDirection::Both; + } else { + installDirection_ = installDirection::Receive; + } + } +#ifdef DEBUG + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir); +#endif + + injectionProbability_ = params.find("injectionProbability", "0.5"); + if ( injectionProbability_ < 0.0 || injectionProbability_ > 1.0 ) { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInjection probability outside of bounds. Must be in the following range: [0.0,1.0].\n"); + } +#ifdef DEBUG + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); +#endif +} + +void +FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) +{ + faultLogic(ev); +} + +void +FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) +{ + // do not cancel delivery by default + cancel = false; + + faultLogic(ev); +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 41e0d1cbe1..e6a5d08e87 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -14,11 +14,20 @@ #include "sst/core/component.h" #include "sst/core/event.h" +#include "sst/elements/memHierarchy/memEvent.h" -namespace SST::FaultInjectorBase { +namespace SST::Carcosa { + +// NOTE: currently unsure if BOTH is actually valid +enum installDirection { + Send = 0, + Receive, + Both, + Invalid +}; /** - * Base class containing required virtual functions and basic required data for + * Base class containing required functions and basic data for * creating fault injection on component ports */ class FaultInjectorBase : public SST::PortModule @@ -33,7 +42,8 @@ class FaultInjectorBase : public SST::PortModule ) SST_ELI_DOCUMENT_PARAMS( - // + {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, + {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."} ) FaultInjectorBase(Params& params); @@ -44,12 +54,43 @@ class FaultInjectorBase : public SST::PortModule void eventSent(uintptr_t key, Event*& ev) override; void interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; - bool installOnReceive() override; - bool installOnSend() override; + bool installOnReceive() override + { + switch (installDirection_) { + case Send: + return false; + case Receive: + case Both: + default: + return true; + } + } + bool installOnSend() override + { + switch (installDirection_) { + case Send: + case Both: + return true; + case Receive: + default: + return false; + } + } private: - void (*eventSentPtr)(uintptr_t, Event*&); - void (*interceptHandlerPtr)(uintptr_t, Event*&, bool&); + void (*faultLogic)(Event*&); + + installDirection installDirection_ = installDirection::Receive; + double injectionProbability_ = 0.5; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + SST_SER(installDirection_); + SST_SER(injectionProbability_); + } + ImplementSerializable(SST::Carcosa::FaultInjectorBase) }; } // namespace SST::FaultInjectorBase From 84f2e18153dbb2c60c3a7c0614e68da3c933dc01 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 8 May 2025 17:21:59 -0400 Subject: [PATCH 05/45] add enum for basic logic selection --- src/sst/elements/carcosa/faultInjectorBase.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index e6a5d08e87..93879d2c40 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -26,6 +26,16 @@ enum installDirection { Invalid }; +// Enum to select basic fault injection logic or indicate a custom input +enum injectorLogic { + StuckAt = 0, + RandomFlip, + RandomDrop, + CorruptRegion, + CorruptAddr, + Custom +}; + /** * Base class containing required functions and basic data for * creating fault injection on component ports From d0fef34b49a6676bfca812ec10329bf2d0deb9c2 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 22 May 2025 16:35:10 -0400 Subject: [PATCH 06/45] block out empty basic fault functions build parameter reader for fault type add parameter for choosing fault type add parameter for stuckAtFault inputs --- src/sst/elements/carcosa/faultInjectorBase.cc | 65 +++++++++++++++++-- src/sst/elements/carcosa/faultInjectorBase.h | 39 +++++++++-- 2 files changed, 93 insertions(+), 11 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 04e31b0577..54d2801a25 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -25,8 +25,8 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() if ( install_dir != "Receive" ) { if ( install_dir == "Send" ) { installDirection_ = installDirection::Send; - } else if ( install_dir == "Both" ) { - installDirection_ = installDirection::Both; + //} else if ( install_dir == "Both" ) { + // installDirection_ = installDirection::Both; } else { installDirection_ = installDirection::Receive; } @@ -42,12 +42,33 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif + + string faultType = params.find("faultType", ""); + + if ( faultType == "stuckAt" ) { + stuckAtInit(params); + faultLogic = &FaultInjectorBase::stuckAtFault; + } else if ( faultType == "randomFlip" ) { + faultLogic = &FaultInjectorBase::randomFlipFault; + } else if ( faultType == "randomDrop" ) { + faultLogic = &FaultInjectorBase::randomDropFault; + } else if ( faultType == "corruptMemRegion" ) { + faultLogic = &FaultInjectorBase::corruptRegionFault; + } else if ( faultType == "custom" ) { + faultLogic = &FaultInjectorBase::customFault; // placeholder + } else { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInvalid fault type selected. Valid options are stuckAt, RandomFlip, randomDrop, corruptRegion, and custom.\n"); + } + +#ifdef DEBUG + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: %s\n", faultType); +#endif } void FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { - faultLogic(ev); + (this->*(faultLogic))(ev); } void @@ -56,5 +77,41 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) // do not cancel delivery by default cancel = false; - faultLogic(ev); + (this->*(faultLogic))(ev); +} + +void +FaultInjectorBase::stuckAtFault(Event*& ev) +{ + // +} + +void +FaultInjectorBase::stuckAtInit(SST::Params& params) +{ + // TODO: devise a way to input and read data from the python into the stuckAtMap +} + +void +FaultInjectorBase::randomFlipFault(Event*& ev) +{ + // +} + +void +FaultInjectorBase::randomDropFault(Event*& ev) +{ + // +} + +void +FaultInjectorBase::corruptMemRegionFault(Event*& ev) +{ + // +} + +void +FaultInjectorBase::customFault(Event*& ev) +{ + // } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 93879d2c40..8dcfc3570f 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -15,6 +15,8 @@ #include "sst/core/component.h" #include "sst/core/event.h" #include "sst/elements/memHierarchy/memEvent.h" +#include +#include namespace SST::Carcosa { @@ -22,7 +24,7 @@ namespace SST::Carcosa { enum installDirection { Send = 0, Receive, - Both, + //Both, Invalid }; @@ -31,8 +33,7 @@ enum injectorLogic { StuckAt = 0, RandomFlip, RandomDrop, - CorruptRegion, - CorruptAddr, + CorruptMemRegion, Custom }; @@ -53,7 +54,9 @@ class FaultInjectorBase : public SST::PortModule SST_ELI_DOCUMENT_PARAMS( {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, - {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."} + {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, + {"faultType", "The type of fault to be injected. Options are stuckAt, randomFlip, randomDrop, corruptMemRegion, and custom."}, + {"stuckAtAddrs", "Map of addresses and bits that are stuck, along with the values of those stuck bits."} ) FaultInjectorBase(Params& params); @@ -70,7 +73,7 @@ class FaultInjectorBase : public SST::PortModule case Send: return false; case Receive: - case Both: + //case Both: default: return true; } @@ -79,7 +82,7 @@ class FaultInjectorBase : public SST::PortModule { switch (installDirection_) { case Send: - case Both: + //case Both: return true; case Receive: default: @@ -88,19 +91,41 @@ class FaultInjectorBase : public SST::PortModule } private: - void (*faultLogic)(Event*&); + void (SST::Carcosa::FaultInjectorBase::* faultLogic)(Event*&); installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; + // map of addr->{bit, value} for saving stuck bit values + std::map>> stuckAtMap; + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` SST_SER(installDirection_); SST_SER(injectionProbability_); + SST_SER(stuckAtMap); } ImplementSerializable(SST::Carcosa::FaultInjectorBase) + + /** + * Read event payload and perform the following: + * - If stuckAtMap.at(addr) exists, compare all listed bits with payload value + * - If payload value does not match mapped value, add bit to flip mask + * - Once all stored bit values have been compared, use flip mask to modify address data + */ + void stuckAtFault(Event*& ev); + + void stuckAtInit(SST::Params& params); + + void randomFlipFault(Event*& ev); + + void randomDropFault(Event*& ev); + + void corruptMemRegionFault(Event*& ev); + + void customFault(Event*& ev); }; } // namespace SST::FaultInjectorBase From c307c1f05ffb6af0a6ed39d31baa091fab256de0 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 3 Jul 2025 14:32:00 -0400 Subject: [PATCH 07/45] split fault logic code off into subclasses -- only stuck-at is currently skeletoned, but I will add the rest soon --- src/sst/elements/carcosa/Makefile.am | 8 ++- src/sst/elements/carcosa/faultInjectorBase.cc | 12 ++-- src/sst/elements/carcosa/faultInjectorBase.h | 24 ------- .../carcosa/faultlogic/stuckAtFault.cc | 30 +++++++++ .../carcosa/faultlogic/stuckAtFault.h | 66 +++++++++++++++++++ 5 files changed, 106 insertions(+), 34 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/stuckAtFault.cc create mode 100644 src/sst/elements/carcosa/faultlogic/stuckAtFault.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 0ea4b4d1e7..2cf65133ca 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -8,9 +8,11 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la -libcarcosa_la_SOURCES = \ - faultInjectorBase.cc \ - faultInjectorBase.h +libcarcosa_la_SOURCES = \ + faultInjectorBase.cc \ + faultInjectorBase.h \ + faultlogic/stuckAtFault.cc \ + faultlogic/stuckAtFault.h EXTRA_DIST = \ dummyTest.py diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 54d2801a25..364752b095 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -42,7 +42,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - + /* string faultType = params.find("faultType", ""); if ( faultType == "stuckAt" ) { @@ -59,10 +59,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() } else { getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInvalid fault type selected. Valid options are stuckAt, RandomFlip, randomDrop, corruptRegion, and custom.\n"); } - -#ifdef DEBUG - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: %s\n", faultType); -#endif + */ } void @@ -79,7 +76,7 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) (this->*(faultLogic))(ev); } - +/** void FaultInjectorBase::stuckAtFault(Event*& ev) { @@ -114,4 +111,5 @@ void FaultInjectorBase::customFault(Event*& ev) { // -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 8dcfc3570f..3f9d8238e1 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -55,8 +55,6 @@ class FaultInjectorBase : public SST::PortModule SST_ELI_DOCUMENT_PARAMS( {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, - {"faultType", "The type of fault to be injected. Options are stuckAt, randomFlip, randomDrop, corruptMemRegion, and custom."}, - {"stuckAtAddrs", "Map of addresses and bits that are stuck, along with the values of those stuck bits."} ) FaultInjectorBase(Params& params); @@ -96,36 +94,14 @@ class FaultInjectorBase : public SST::PortModule installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; - // map of addr->{bit, value} for saving stuck bit values - std::map>> stuckAtMap; - void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` SST_SER(installDirection_); SST_SER(injectionProbability_); - SST_SER(stuckAtMap); } ImplementSerializable(SST::Carcosa::FaultInjectorBase) - - /** - * Read event payload and perform the following: - * - If stuckAtMap.at(addr) exists, compare all listed bits with payload value - * - If payload value does not match mapped value, add bit to flip mask - * - Once all stored bit values have been compared, use flip mask to modify address data - */ - void stuckAtFault(Event*& ev); - - void stuckAtInit(SST::Params& params); - - void randomFlipFault(Event*& ev); - - void randomDropFault(Event*& ev); - - void corruptMemRegionFault(Event*& ev); - - void customFault(Event*& ev); }; } // namespace SST::FaultInjectorBase diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc new file mode 100644 index 0000000000..3939e575a5 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -0,0 +1,30 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "stuckAtFault.h" + +using namespace SST::Carcosa; + +/********** StuckAtFault **********/ + +StuckAtFault::StuckAtFault(Params& params) : FaultInjectorBase(params) +{ + // assign fault logic function + this->faultLogic = &StuckAtFault::fault; + +#ifdef DEBUG + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); +#endif +} + +void fault(Event&* ev) { + // see comment in header file +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h new file mode 100644 index 0000000000..ef7838261b --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -0,0 +1,66 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULT_H +#define SST_ELEMENTS_CARCOSA_STUCKATFAULT_H + +#include "../faultInjectorBase.h" + +namespace SST::Carcosa { + +class StuckAtFault : public SST::Carcosa::FaultInjectorBase +{ +public: + SST_ELI_REGISTER_PORTMODULE( + StuckAtFault, + "carcosa", + "stuckAtFault", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "Basic PortModule to enable a stuck bit hardware fault" + ) + + SST_ELI_DOCUMENT_PARAMS( + {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, + {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, + {"stuckAtAddrs", "Map of addresses and bits that are stuck, along with the values of those stuck bits."} + ) + + StuckAtFault(Params& params); + + StuckAtFault() = default; + ~StuckAtFault() {} +private: + + // map of addr->{bit, value} for saving stuck bit values + std::map>> stuckAtMap; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + SST_SER(installDirection_); + SST_SER(injectionProbability_); + SST_SER(stuckAtMap); + } + ImplementSerializable(SST::Carcosa::StuckAtFault) + + /** + * Read event payload and perform the following: + * - If stuckAtMap.at(addr) exists, compare all listed bits with payload value + * - If payload value does not match mapped value, add bit to flip mask + * - Once all stored bit values have been compared, use flip mask to modify address data + */ + void fault(Event*& ev); +}; + +} + +#endif // SST_ELEMENTS_CARCOSA_STUCKATFAULT_H \ No newline at end of file From aad5d2aabc7f053463984b44da255c331affebfb Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 3 Jul 2025 16:33:54 -0400 Subject: [PATCH 08/45] add another layer of abstraction so that the fault itself is its own class--need to fix some compiler issues and skeletonize the other faults --- src/sst/elements/carcosa/Makefile.am | 2 + src/sst/elements/carcosa/faultInjectorBase.cc | 24 ++---------- src/sst/elements/carcosa/faultInjectorBase.h | 13 ++++--- .../elements/carcosa/faultlogic/faultBase.cc | 19 +++++++++ .../elements/carcosa/faultlogic/faultBase.h | 32 +++++++++++++++ .../carcosa/faultlogic/stuckAtFault.cc | 7 +--- .../carcosa/faultlogic/stuckAtFault.h | 39 +++++-------------- 7 files changed, 76 insertions(+), 60 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.cc create mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 2cf65133ca..567b1e8484 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -11,6 +11,8 @@ comp_LTLIBRARIES = libcarcosa.la libcarcosa_la_SOURCES = \ faultInjectorBase.cc \ faultInjectorBase.h \ + faultlogic/faultBase.cc \ + faultlogic/faultBase.h \ faultlogic/stuckAtFault.cc \ faultlogic/stuckAtFault.h diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 364752b095..ee7fbe7ed5 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -42,30 +42,14 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - /* - string faultType = params.find("faultType", ""); - - if ( faultType == "stuckAt" ) { - stuckAtInit(params); - faultLogic = &FaultInjectorBase::stuckAtFault; - } else if ( faultType == "randomFlip" ) { - faultLogic = &FaultInjectorBase::randomFlipFault; - } else if ( faultType == "randomDrop" ) { - faultLogic = &FaultInjectorBase::randomDropFault; - } else if ( faultType == "corruptMemRegion" ) { - faultLogic = &FaultInjectorBase::corruptRegionFault; - } else if ( faultType == "custom" ) { - faultLogic = &FaultInjectorBase::customFault; // placeholder - } else { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInvalid fault type selected. Valid options are stuckAt, RandomFlip, randomDrop, corruptRegion, and custom.\n"); - } - */ + + fault = new StuckAtFault(params); } void FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { - (this->*(faultLogic))(ev); + fault->faultLogic(ev); } void @@ -74,7 +58,7 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) // do not cancel delivery by default cancel = false; - (this->*(faultLogic))(ev); + fault->faultLogic(ev); } /** void diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 3f9d8238e1..0757636664 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -15,8 +15,8 @@ #include "sst/core/component.h" #include "sst/core/event.h" #include "sst/elements/memHierarchy/memEvent.h" -#include -#include +#include "faultlogic/faultBase.h" +#include "faultlogic/stuckAtFault.h" namespace SST::Carcosa { @@ -60,7 +60,9 @@ class FaultInjectorBase : public SST::PortModule FaultInjectorBase(Params& params); FaultInjectorBase() = default; - ~FaultInjectorBase() {} + ~FaultInjectorBase() { + delete fault; + } void eventSent(uintptr_t key, Event*& ev) override; void interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; @@ -88,8 +90,8 @@ class FaultInjectorBase : public SST::PortModule } } -private: - void (SST::Carcosa::FaultInjectorBase::* faultLogic)(Event*&); +protected: + FaultBase* fault; installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; @@ -98,6 +100,7 @@ class FaultInjectorBase : public SST::PortModule { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` + SST_SER(fault); SST_SER(installDirection_); SST_SER(injectionProbability_); } diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc new file mode 100644 index 0000000000..b8ee851c93 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/faultBase.cc @@ -0,0 +1,19 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "faultBase.h" + +using namespace SST::Carcosa; + +FaultBase::FaultBase(Params& params) +{ + // what do we need in here? +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h new file mode 100644 index 0000000000..84e46a7e1b --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -0,0 +1,32 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_FAULTBASE_H +#define SST_ELEMENTS_CARCOSA_FAULTBASE_H + +#include "sst/core/component.h" +#include "sst/core/event.h" +#include "sst/elements/memHierarchy/memEvent.h" + +namespace SST::Carcosa { + +class FaultBase { +public: + FaultBase(Params& params); + + FaultBase() = default; + ~FaultBase() {} + + virtual void faultLogic(Event*& ev) = 0; +}; +} + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 3939e575a5..4fad2dbd6f 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -15,16 +15,13 @@ using namespace SST::Carcosa; /********** StuckAtFault **********/ -StuckAtFault::StuckAtFault(Params& params) : FaultInjectorBase(params) +StuckAtFault::StuckAtFault(Params& params) : FaultBase(params) { - // assign fault logic function - this->faultLogic = &StuckAtFault::fault; - #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); #endif } -void fault(Event&* ev) { +void faultLogic(Event&* ev) { // see comment in header file } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index ef7838261b..cadb5b5b4e 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -12,45 +12,20 @@ #ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULT_H #define SST_ELEMENTS_CARCOSA_STUCKATFAULT_H -#include "../faultInjectorBase.h" +#include "faultBase.h" +#include +#include namespace SST::Carcosa { -class StuckAtFault : public SST::Carcosa::FaultInjectorBase +class StuckAtFault : public SST::Carcosa::FaultBase { public: - SST_ELI_REGISTER_PORTMODULE( - StuckAtFault, - "carcosa", - "stuckAtFault", - SST_ELI_ELEMENT_VERSION(0, 1, 0), - "Basic PortModule to enable a stuck bit hardware fault" - ) - - SST_ELI_DOCUMENT_PARAMS( - {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, - {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, - {"stuckAtAddrs", "Map of addresses and bits that are stuck, along with the values of those stuck bits."} - ) StuckAtFault(Params& params); StuckAtFault() = default; ~StuckAtFault() {} -private: - - // map of addr->{bit, value} for saving stuck bit values - std::map>> stuckAtMap; - - void serialize_order(SST::Core::Serialization::serializer& ser) override - { - SST::PortModule::serialize_order(ser); - // serialize parameters like `SST_SER()` - SST_SER(installDirection_); - SST_SER(injectionProbability_); - SST_SER(stuckAtMap); - } - ImplementSerializable(SST::Carcosa::StuckAtFault) /** * Read event payload and perform the following: @@ -58,7 +33,11 @@ class StuckAtFault : public SST::Carcosa::FaultInjectorBase * - If payload value does not match mapped value, add bit to flip mask * - Once all stored bit values have been compared, use flip mask to modify address data */ - void fault(Event*& ev); + void faultLogic(Event*& ev) override; +protected: + + // map of addr->{bit, value} for saving stuck bit values + std::map>> stuckAtMap; }; } From 491038abbc8d3450419df1aae8c36f19c3292d53 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 3 Jul 2025 17:23:02 -0400 Subject: [PATCH 09/45] add todo note to faultBase.h --- src/sst/elements/carcosa/faultInjectorBase.cc | 2 +- src/sst/elements/carcosa/faultlogic/faultBase.h | 11 +++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index ee7fbe7ed5..796a6dec50 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -43,7 +43,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - fault = new StuckAtFault(params); + fault = new faultBase(params); } void diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index 84e46a7e1b..f90eaeec27 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -18,14 +18,21 @@ namespace SST::Carcosa { + /** TODO: + * Parameters for switching between interface-driven and normal instantiation + * A way to read in data to choose which logic to use + * - Might be possible to parameterize the entirety of the logic, but would be easier if I can + * build a "library" of functions that are loaded dynamically + */ + class FaultBase { public: FaultBase(Params& params); FaultBase() = default; ~FaultBase() {} - - virtual void faultLogic(Event*& ev) = 0; + + virtual void faultLogic(Event*& ev); }; } From 2aa8bba84d4503501d89da2e0d3d6efd822d100e Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 4 Sep 2025 14:56:38 -0400 Subject: [PATCH 10/45] fix compile errors NOT arising from serialization --- src/sst/elements/carcosa/faultInjectorBase.cc | 4 +--- src/sst/elements/carcosa/faultInjectorBase.h | 3 --- src/sst/elements/carcosa/faultlogic/stuckAtFault.cc | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 796a6dec50..46cdd4d5ae 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -25,8 +25,6 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() if ( install_dir != "Receive" ) { if ( install_dir == "Send" ) { installDirection_ = installDirection::Send; - //} else if ( install_dir == "Both" ) { - // installDirection_ = installDirection::Both; } else { installDirection_ = installDirection::Receive; } @@ -43,7 +41,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - fault = new faultBase(params); + fault = new FaultBase(params); } void diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 0757636664..7135610176 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -24,7 +24,6 @@ namespace SST::Carcosa { enum installDirection { Send = 0, Receive, - //Both, Invalid }; @@ -73,7 +72,6 @@ class FaultInjectorBase : public SST::PortModule case Send: return false; case Receive: - //case Both: default: return true; } @@ -82,7 +80,6 @@ class FaultInjectorBase : public SST::PortModule { switch (installDirection_) { case Send: - //case Both: return true; case Receive: default: diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 4fad2dbd6f..a81b25a793 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -22,6 +22,6 @@ StuckAtFault::StuckAtFault(Params& params) : FaultBase(params) #endif } -void faultLogic(Event&* ev) { +void faultLogic(SST::Event*& ev) { // see comment in header file } \ No newline at end of file From 9e763fbd40e87b4c43eb38bd8e8dd840f930029d Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 4 Sep 2025 15:17:06 -0400 Subject: [PATCH 11/45] sidestep serialization compile issue --- src/sst/elements/carcosa/faultInjectorBase.cc | 39 +------------------ src/sst/elements/carcosa/faultInjectorBase.h | 6 +-- .../elements/carcosa/faultlogic/faultBase.h | 9 +++++ 3 files changed, 13 insertions(+), 41 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 46cdd4d5ae..3f4dbbbcbd 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -57,41 +57,4 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) cancel = false; fault->faultLogic(ev); -} -/** -void -FaultInjectorBase::stuckAtFault(Event*& ev) -{ - // -} - -void -FaultInjectorBase::stuckAtInit(SST::Params& params) -{ - // TODO: devise a way to input and read data from the python into the stuckAtMap -} - -void -FaultInjectorBase::randomFlipFault(Event*& ev) -{ - // -} - -void -FaultInjectorBase::randomDropFault(Event*& ev) -{ - // -} - -void -FaultInjectorBase::corruptMemRegionFault(Event*& ev) -{ - // -} - -void -FaultInjectorBase::customFault(Event*& ev) -{ - // -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 7135610176..16366366bc 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -63,8 +63,8 @@ class FaultInjectorBase : public SST::PortModule delete fault; } - void eventSent(uintptr_t key, Event*& ev) override; - void interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; + void virtual eventSent(uintptr_t key, Event*& ev) override; + void virtual interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; bool installOnReceive() override { @@ -97,7 +97,7 @@ class FaultInjectorBase : public SST::PortModule { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` - SST_SER(fault); + // SST_SER(fault); SST_SER(installDirection_); SST_SER(injectionProbability_); } diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index f90eaeec27..e868fd631f 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -33,6 +33,15 @@ class FaultBase { ~FaultBase() {} virtual void faultLogic(Event*& ev); + +protected: + // TODO: Figure out how to properly set up serialization for this + // void serialize_order(SST::Core::Serialization::serializer& ser) + // { + // SST::PortModule::serialize_order(ser); + // // serialize parameters like `SST_SER() + // } + // ImplementSerializable(SST::Carcosa::FaultBase) }; } From 43184d4760770e1e800df24de172829269620c34 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 5 Sep 2025 16:41:40 -0400 Subject: [PATCH 12/45] I have defeated the compiler --- src/sst/elements/carcosa/Makefile.am | 2 - src/sst/elements/carcosa/faultInjectorBase.cc | 22 +++++++- src/sst/elements/carcosa/faultInjectorBase.h | 53 +++++++++++++++++-- .../carcosa/faultlogic/corruptMemRegion.h | 0 .../elements/carcosa/faultlogic/faultBase.cc | 19 ------- .../elements/carcosa/faultlogic/faultBase.h | 48 ----------------- .../elements/carcosa/faultlogic/randomDrop.h | 0 .../elements/carcosa/faultlogic/randomFlip.h | 0 .../carcosa/faultlogic/stuckAtFault.cc | 9 ++-- .../carcosa/faultlogic/stuckAtFault.h | 8 +-- 10 files changed, 79 insertions(+), 82 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/corruptMemRegion.h delete mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.cc delete mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.h create mode 100644 src/sst/elements/carcosa/faultlogic/randomDrop.h create mode 100644 src/sst/elements/carcosa/faultlogic/randomFlip.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 567b1e8484..2cf65133ca 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -11,8 +11,6 @@ comp_LTLIBRARIES = libcarcosa.la libcarcosa_la_SOURCES = \ faultInjectorBase.cc \ faultInjectorBase.h \ - faultlogic/faultBase.cc \ - faultlogic/faultBase.h \ faultlogic/stuckAtFault.cc \ faultlogic/stuckAtFault.h diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 3f4dbbbcbd..e9eefd54d0 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -9,10 +9,28 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include "faultInjectorBase.h" +#include +#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/core/params.h" using namespace SST::Carcosa; +/************** FaultBase **************/ + +FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : _injector(injector) +{ + // what do we need in here? +} + +SST::MemHierarchy::MemEventBase* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { + SST::MemHierarchy::MemEventBase* mem_ev = dynamic_cast(ev); + + if (mem_ev == nullptr) { + _injector->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); + } + return mem_ev; +} + /********** FaultInjectorBase **********/ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() @@ -41,7 +59,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - fault = new FaultBase(params); + fault = new FaultBase(params, this); } void diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 16366366bc..7e7be8d35c 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -12,14 +12,17 @@ #ifndef SST_ELEMENTS_CARCOSA_FAULTINJECTORBASE_H #define SST_ELEMENTS_CARCOSA_FAULTINJECTORBASE_H -#include "sst/core/component.h" +#include "sst/core/portModule.h" #include "sst/core/event.h" +#include "sst/core/output.h" #include "sst/elements/memHierarchy/memEvent.h" -#include "faultlogic/faultBase.h" -#include "faultlogic/stuckAtFault.h" namespace SST::Carcosa { +class FaultInjectorBase; + +/********** FaultInjectorBase **********/ + // NOTE: currently unsure if BOTH is actually valid enum installDirection { Send = 0, @@ -43,6 +46,38 @@ enum injectorLogic { class FaultInjectorBase : public SST::PortModule { public: + /************** FaultBase **************/ + + /** TODO: + * Parameters for switching between interface-driven and normal instantiation + * A way to read in data to choose which logic to use + * - Might be possible to parameterize the entirety of the logic, but would be easier if I can + * build a "library" of functions that are loaded dynamically + */ + + class FaultBase { + public: + FaultBase(Params& params, FaultInjectorBase* injector); + + FaultBase() = default; + ~FaultBase() {} + + virtual void faultLogic(Event*& ev) {} + + SST::MemHierarchy::MemEventBase* convertMemEvent(Event*& ev); + + protected: + + FaultInjectorBase* _injector = nullptr; + // TODO: Figure out how to properly set up serialization for this + // void serialize_order(SST::Core::Serialization::serializer& ser) + // { + // SST::PortModule::serialize_order(ser); + // // serialize parameters like `SST_SER() + // } + // ImplementSerializable(SST::Carcosa::FaultBase) + }; + SST_ELI_REGISTER_PORTMODULE( FaultInjectorBase, "carcosa", @@ -56,6 +91,12 @@ class FaultInjectorBase : public SST::PortModule {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, ) + // SST_ELI_DOCUMENT_STATISTICS( + // // Trigger Statistics + // {"EventsArrived", "Number of events that passed through the fault injector", "count", 1}, + // {"FaultsTriggered", "Number of events that triggered a fault", "count", 1} + // ) + FaultInjectorBase(Params& params); FaultInjectorBase() = default; @@ -87,6 +128,8 @@ class FaultInjectorBase : public SST::PortModule } } + SST::MemHierarchy::MemEventBase*& convertMemEvent(Event*& ev); + protected: FaultBase* fault; @@ -102,6 +145,10 @@ class FaultInjectorBase : public SST::PortModule SST_SER(injectionProbability_); } ImplementSerializable(SST::Carcosa::FaultInjectorBase) + + // Statistics + // Statistic stat_eventsArrived; + // Statistic stat_faultsTriggered; }; } // namespace SST::FaultInjectorBase diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h b/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc deleted file mode 100644 index b8ee851c93..0000000000 --- a/src/sst/elements/carcosa/faultlogic/faultBase.cc +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright 2009-2025 NTESS. Under the terms -// of Contract DE-NA0003525 with NTESS, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2025, NTESS -// All rights reserved. -// -// This file is part of the SST software package. For license -// information, see the LICENSE file in the top level directory of the -// distribution. - -#include "faultBase.h" - -using namespace SST::Carcosa; - -FaultBase::FaultBase(Params& params) -{ - // what do we need in here? -} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h deleted file mode 100644 index e868fd631f..0000000000 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2009-2025 NTESS. Under the terms -// of Contract DE-NA0003525 with NTESS, the U.S. -// Government retains certain rights in this software. -// -// Copyright (c) 2009-2025, NTESS -// All rights reserved. -// -// This file is part of the SST software package. For license -// information, see the LICENSE file in the top level directory of the -// distribution. - -#ifndef SST_ELEMENTS_CARCOSA_FAULTBASE_H -#define SST_ELEMENTS_CARCOSA_FAULTBASE_H - -#include "sst/core/component.h" -#include "sst/core/event.h" -#include "sst/elements/memHierarchy/memEvent.h" - -namespace SST::Carcosa { - - /** TODO: - * Parameters for switching between interface-driven and normal instantiation - * A way to read in data to choose which logic to use - * - Might be possible to parameterize the entirety of the logic, but would be easier if I can - * build a "library" of functions that are loaded dynamically - */ - -class FaultBase { -public: - FaultBase(Params& params); - - FaultBase() = default; - ~FaultBase() {} - - virtual void faultLogic(Event*& ev); - -protected: - // TODO: Figure out how to properly set up serialization for this - // void serialize_order(SST::Core::Serialization::serializer& ser) - // { - // SST::PortModule::serialize_order(ser); - // // serialize parameters like `SST_SER() - // } - // ImplementSerializable(SST::Carcosa::FaultBase) -}; -} - -#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomDrop.h b/src/sst/elements/carcosa/faultlogic/randomDrop.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/faultlogic/randomFlip.h b/src/sst/elements/carcosa/faultlogic/randomFlip.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index a81b25a793..b15d182b56 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -9,19 +9,20 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include "stuckAtFault.h" +#include "sst/elements/carcosa/faultlogic/stuckAtFault.h" using namespace SST::Carcosa; /********** StuckAtFault **********/ -StuckAtFault::StuckAtFault(Params& params) : FaultBase(params) +StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); #endif } -void faultLogic(SST::Event*& ev) { - // see comment in header file +void StuckAtFault::faultLogic(SST::Event*& ev) { + // Convert to memEvent + SST::MemHierarchy::MemEventBase* mem_ev = this->convertMemEvent(ev); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index cadb5b5b4e..a879b5b1a9 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -12,17 +12,17 @@ #ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULT_H #define SST_ELEMENTS_CARCOSA_STUCKATFAULT_H -#include "faultBase.h" +#include "sst/elements/carcosa/faultInjectorBase.h" #include #include namespace SST::Carcosa { -class StuckAtFault : public SST::Carcosa::FaultBase +class StuckAtFault : public FaultInjectorBase::FaultBase { public: - StuckAtFault(Params& params); + StuckAtFault(Params& params, FaultInjectorBase* injector); StuckAtFault() = default; ~StuckAtFault() {} @@ -40,6 +40,6 @@ class StuckAtFault : public SST::Carcosa::FaultBase std::map>> stuckAtMap; }; -} +} // namespace SST::Carcosa #endif // SST_ELEMENTS_CARCOSA_STUCKATFAULT_H \ No newline at end of file From 8aae8208f58afcff70847974252b19dc867541ab Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 5 Sep 2025 16:54:49 -0400 Subject: [PATCH 13/45] use correct memEvent and add some base logic -- need to figure out how to determine message direction --- src/sst/elements/carcosa/faultInjectorBase.cc | 4 ++-- src/sst/elements/carcosa/faultInjectorBase.h | 2 +- src/sst/elements/carcosa/faultlogic/stuckAtFault.cc | 10 +++++++++- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index e9eefd54d0..9976123b6f 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -22,8 +22,8 @@ FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injec // what do we need in here? } -SST::MemHierarchy::MemEventBase* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { - SST::MemHierarchy::MemEventBase* mem_ev = dynamic_cast(ev); +SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); if (mem_ev == nullptr) { _injector->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 7e7be8d35c..8e3121aa75 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -64,7 +64,7 @@ class FaultInjectorBase : public SST::PortModule virtual void faultLogic(Event*& ev) {} - SST::MemHierarchy::MemEventBase* convertMemEvent(Event*& ev); + SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); protected: diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index b15d182b56..a4bc3d1f39 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -24,5 +24,13 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB void StuckAtFault::faultLogic(SST::Event*& ev) { // Convert to memEvent - SST::MemHierarchy::MemEventBase* mem_ev = this->convertMemEvent(ev); + SST::MemHierarchy::MemEvent* mem_ev = this->convertMemEvent(ev); + + // check for the addr in question in the fault map + if (stuckAtMap.count(mem_ev->getAddr()) >= 1) { + // need to determine direction message is going + std::string dst = mem_ev->getDst(); + std::string src = mem_ev->getSrc(); + // how can these compared in a standard way? + } } \ No newline at end of file From 1f03f6587e976fec8b90bf6056becb27dff24ab5 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 11 Sep 2025 16:20:04 -0400 Subject: [PATCH 14/45] prototype stuckAtFault written--currently untested (and very ugly) --- src/sst/elements/carcosa/faultInjectorBase.cc | 42 ++++++ src/sst/elements/carcosa/faultInjectorBase.h | 22 ++- .../carcosa/faultlogic/stuckAtFault.cc | 125 +++++++++++++++++- .../carcosa/faultlogic/stuckAtFault.h | 31 ++++- 4 files changed, 210 insertions(+), 10 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 9976123b6f..03aa0a684a 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -22,6 +22,10 @@ FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injec // what do we need in here? } +SST::Output& FaultInjectorBase::FaultBase::getSimulationOutput() { + return _injector->getSimulationOutput(); +} + SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); @@ -31,6 +35,44 @@ SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event return mem_ev; } +dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { + return convertMemEvent(ev)->getPayload(); +} + +void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { +#ifdef DEBUG + _injector->getSimulationOutput().debug(_L10_, "Payload before replacement:\n"); + for (int i: convertMemEvent(ev)->getPayload()) { + _injector->getSimulationOutput().debug(_L10_, "%d\t"); + } + _injector->getSimulationOutput().debug(_L10_, "\n"); +#endif + convertMemEvent(ev)->setPayload(newPayload); + +#ifdef DEBUG + _injector->getSimulationOutput().debug(_L10_, "Payload after replacement:\n"); + for (int i: convertMemEvent(ev)->getPayload()) { + _injector->getSimulationOutput().debug(_L10_, "%d\t"); + } + _injector->getSimulationOutput().debug(_L10_, "\n"); +#endif +} + +FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemEventCommandType(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); + if (mem_ev->isDataRequest()) { + return FaultBase::memEventType::DataRequest; + } else if (mem_ev->isResponse()) { + return FaultBase::memEventType::Response; + } else if (mem_ev->isWriteback()) { + return FaultBase::memEventType::Writeback; + } else if (mem_ev->isRoutedByAddress()) { + return FaultBase::memEventType::RoutedByAddr; + } else { + return FaultBase::memEventType::Invalid; + } +} + /********** FaultInjectorBase **********/ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 8e3121aa75..fa9c8cc9df 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -19,11 +19,12 @@ namespace SST::Carcosa { +typedef std::vector dataVec; + class FaultInjectorBase; /********** FaultInjectorBase **********/ -// NOTE: currently unsure if BOTH is actually valid enum installDirection { Send = 0, Receive, @@ -57,6 +58,15 @@ class FaultInjectorBase : public SST::PortModule class FaultBase { public: + + enum memEventType { + DataRequest = 0, + Response, + Writeback, + RoutedByAddr, + Invalid + }; + FaultBase(Params& params, FaultInjectorBase* injector); FaultBase() = default; @@ -64,8 +74,16 @@ class FaultInjectorBase : public SST::PortModule virtual void faultLogic(Event*& ev) {} + SST::Output& getSimulationOutput(); + SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); + dataVec& getMemEventPayload(Event*& ev); + + void setMemEventPayload(Event*& ev, dataVec newPayload); + + memEventType getMemEventCommandType(Event*& ev); + protected: FaultInjectorBase* _injector = nullptr; @@ -128,8 +146,6 @@ class FaultInjectorBase : public SST::PortModule } } - SST::MemHierarchy::MemEventBase*& convertMemEvent(Event*& ev); - protected: FaultBase* fault; diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index a4bc3d1f39..992690d837 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -20,17 +20,132 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB #ifdef DEBUG getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); #endif + // read in masks + // parameter format: {masks: ["addr, byte, zeroMask, oneMask"]} + std::vector paramVecStr; + params.find_array("masks", paramVecStr); + + std::vector paramVec = convertString(paramVecStr); + // build maps + for (auto param = paramVec.begin(); param != paramVec.end(); param++) { + Addr addr = param->addr; + int byte = param->byte; + uint8_t zeroMask = param->zeroMask; + uint8_t oneMask = param->oneMask; + if ((int)(zeroMask & oneMask) > 0) { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Masks contain overlapping values. Addr: 0x%zu, " + "byte: %d\n", addr, byte); + } + // check for vector in each map before creating it + if (stuckAtZeroMask.count(addr) == 1) { + stuckAtZeroMask.at(addr).push_back(make_pair(byte, zeroMask)); + } else { + auto maskVec = stuckAtZeroMask.emplace(make_pair(addr, std::vector>())); + if (maskVec.second) { + maskVec.first->second.push_back(make_pair(byte, zeroMask)); + } else { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); + } + } +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "Finished inserting zero-masks for 0x%zu.\n", addr); +#endif + if (stuckAtOneMask.count(addr) == 1) { + stuckAtOneMask.at(addr).push_back(make_pair(byte, oneMask)); + } else { + auto maskVec = stuckAtOneMask.emplace(make_pair(addr, std::vector>())); + if (maskVec.second) { + maskVec.first->second.push_back(make_pair(byte, oneMask)); + } else { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); + } + } +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "Finished inserting one-masks for 0x%zu.\n", addr); +#endif + } } void StuckAtFault::faultLogic(SST::Event*& ev) { // Convert to memEvent SST::MemHierarchy::MemEvent* mem_ev = this->convertMemEvent(ev); + Addr addr = mem_ev->getAddr(); + // check for the addr in question in the fault map - if (stuckAtMap.count(mem_ev->getAddr()) >= 1) { - // need to determine direction message is going - std::string dst = mem_ev->getDst(); - std::string src = mem_ev->getSrc(); - // how can these compared in a standard way? + if (stuckAtZeroMask.count(addr) == 1 || stuckAtOneMask.count(addr) == 1) { +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "Addr 0x%x found in stuck map.\n", addr); +#endif + // replace data if necessary + dataVec payload = this->getMemEventPayload(ev); + + uint8_t mask = 0b00000000; +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "Begin zero mask for address: 0x%zu\n", addr); +#endif + if (stuckAtZeroMask.count(addr) == 1) { + for (auto maskPair: stuckAtZeroMask.at(addr)) { + mask = maskPair.second; +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + maskPair.first, (int)payload[maskPair.first], (int) mask, + (int)(payload[maskPair.first] &= (!mask))); +#endif + payload[maskPair.first] &= (!mask); + } + } +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "End zero mask for address: 0x%zu\n", addr); + getSimulationOutput().debug(_L10_, "Begin one mask for address: 0x%zu\n", addr); +#endif + if (stuckAtOneMask.count(addr) == 1) { + for (auto maskPair: stuckAtOneMask.at(addr)) { + mask = maskPair.second; +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + maskPair.first, (int)payload[maskPair.first], (int) mask, + (int)(payload[maskPair.first] |= mask)); +#endif + payload[maskPair.first] |= mask; + } +#ifdef DEBUG + getSimulationOutput().debug(_L10_, "End one mask for address: 0x%zu\n", addr); +#endif + } + + // replace payload + this->setMemEventPayload(ev, payload); + } +} + +std::vector StuckAtFault::convertString(std::vector& paramVecString) { + std::vector paramVec; + + for (auto param = paramVecString.begin(); param != paramVecString.end(); param++) { + // disassemble string + std::stringstream stream; + Addr addr; int byte; uint8_t zeroMask, oneMask; + stream.str(*param); + stream >> addr; + if (stream.peek() == ',') { + stream.ignore(); + } + stream >> byte; + if (stream.peek() == ',') { + stream.ignore(); + } + stream >> zeroMask; + if (stream.peek() == ',') { + stream.ignore(); + } + stream >> oneMask; + if (stream.peek() == ',') { + stream.ignore(); + } + // insert maskParam + paramVec.push_back({addr, byte, zeroMask, oneMask}); } + + return paramVec; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index a879b5b1a9..cbf3e1a46c 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -15,9 +15,25 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include #include +#include +#include namespace SST::Carcosa { +typedef std::vector dataVec; +typedef SST::MemHierarchy::Addr Addr; + +/** + * This fault is used to simulate a stuck bit fault. + * To ensure correct operation, make sure that the port module + * using this fault is attached at every point where the data + * for this bit could be read. For example, a stuck bit in the L2 + * cache would need a port module with this fault installed on all + * input OR all output ports to the L2; if the simulator has forwarding enabled, + * but the actual system being simulated does not do the forwarding from memory + * directly into the L1 or the core (bypassing L2 ops in simulation), it may be + * advisable to also place these port modules on the ports used to forward these events. + */ class StuckAtFault : public FaultInjectorBase::FaultBase { public: @@ -36,8 +52,19 @@ class StuckAtFault : public FaultInjectorBase::FaultBase void faultLogic(Event*& ev) override; protected: - // map of addr->{bit, value} for saving stuck bit values - std::map>> stuckAtMap; + // map of addr->{byte, mask} for saving stuck bit values + std::map>> stuckAtZeroMask; + // add stuckAtOneMask + std::map>> stuckAtOneMask; + + typedef struct maskParam { + Addr addr; + int byte; + uint8_t zeroMask; + uint8_t oneMask; + } maskParam_t; + + std::vector convertString(std::vector& paramVecStr); }; } // namespace SST::Carcosa From a55a25489a47e342551cabd73d0afa06c5656d33 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 15 Sep 2025 15:49:48 -0400 Subject: [PATCH 15/45] something is DEFINITELY broken here --- src/sst/elements/carcosa/faultInjectorBase.cc | 15 +- .../carcosa/faultlogic/stuckAtFault.cc | 21 +- src/sst/elements/carcosa/tests/dummyTest.py | 571 ++++++++++++++++++ 3 files changed, 591 insertions(+), 16 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 03aa0a684a..26a80c085d 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -12,6 +12,7 @@ #include #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" +#include "sst/elements/carcosa/faultlogic/stuckAtFault.h" using namespace SST::Carcosa; @@ -40,7 +41,7 @@ dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { } void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ _injector->getSimulationOutput().debug(_L10_, "Payload before replacement:\n"); for (int i: convertMemEvent(ev)->getPayload()) { _injector->getSimulationOutput().debug(_L10_, "%d\t"); @@ -49,7 +50,7 @@ void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPay #endif convertMemEvent(ev)->setPayload(newPayload); -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ _injector->getSimulationOutput().debug(_L10_, "Payload after replacement:\n"); for (int i: convertMemEvent(ev)->getPayload()) { _injector->getSimulationOutput().debug(_L10_, "%d\t"); @@ -77,8 +78,8 @@ FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemE FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() { -#ifdef DEBUG - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n") +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n"); #endif std::string install_dir = params.find("installDirection", "Receive"); @@ -89,7 +90,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() installDirection_ = installDirection::Receive; } } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir); #endif @@ -97,11 +98,11 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() if ( injectionProbability_ < 0.0 || injectionProbability_ > 1.0 ) { getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInjection probability outside of bounds. Must be in the following range: [0.0,1.0].\n"); } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); #endif - fault = new FaultBase(params, this); + fault = new StuckAtFault(params, this);//FaultBase(params, this); } void diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 992690d837..f2e9a3a675 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -17,7 +17,7 @@ using namespace SST::Carcosa; StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); #endif // read in masks @@ -47,7 +47,7 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); } } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "Finished inserting zero-masks for 0x%zu.\n", addr); #endif if (stuckAtOneMask.count(addr) == 1) { @@ -60,7 +60,7 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); } } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "Finished inserting one-masks for 0x%zu.\n", addr); #endif } @@ -74,20 +74,20 @@ void StuckAtFault::faultLogic(SST::Event*& ev) { // check for the addr in question in the fault map if (stuckAtZeroMask.count(addr) == 1 || stuckAtOneMask.count(addr) == 1) { -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "Addr 0x%x found in stuck map.\n", addr); #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); uint8_t mask = 0b00000000; -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "Begin zero mask for address: 0x%zu\n", addr); #endif if (stuckAtZeroMask.count(addr) == 1) { for (auto maskPair: stuckAtZeroMask.at(addr)) { mask = maskPair.second; -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", maskPair.first, (int)payload[maskPair.first], (int) mask, (int)(payload[maskPair.first] &= (!mask))); @@ -95,21 +95,21 @@ void StuckAtFault::faultLogic(SST::Event*& ev) { payload[maskPair.first] &= (!mask); } } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "End zero mask for address: 0x%zu\n", addr); getSimulationOutput().debug(_L10_, "Begin one mask for address: 0x%zu\n", addr); #endif if (stuckAtOneMask.count(addr) == 1) { for (auto maskPair: stuckAtOneMask.at(addr)) { mask = maskPair.second; -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", maskPair.first, (int)payload[maskPair.first], (int) mask, (int)(payload[maskPair.first] |= mask)); #endif payload[maskPair.first] |= mask; } -#ifdef DEBUG +#ifdef __SST_DEBUG_OUTPUT__ getSimulationOutput().debug(_L10_, "End one mask for address: 0x%zu\n", addr); #endif } @@ -143,6 +143,9 @@ std::vector StuckAtFault::convertString(std::vector 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + cpu_l2cache.addPortModule("highlink","carcosa.faultInjectorBase", { + "installDirection": "Send", + "injectionProbability": 1, + "masks": ["10, 3, 11110000, 00001111"], + "debug" : 1, + "debug_level": 10 + }) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + From ddcfc2e2683d1a4cd1408e68c186481c7f582c0d Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Tue, 16 Sep 2025 16:50:07 -0400 Subject: [PATCH 16/45] stuckAtFault appears functional -- testing likely required, and there's still no dynamic way to change what fault logic is in use --- src/sst/elements/carcosa/faultInjectorBase.cc | 39 ++++++++++----- src/sst/elements/carcosa/faultInjectorBase.h | 8 +++- .../carcosa/faultlogic/stuckAtFault.cc | 48 ++++++++++--------- .../carcosa/faultlogic/stuckAtFault.h | 1 + src/sst/elements/carcosa/tests/dummyTest.py | 15 ++++-- 5 files changed, 70 insertions(+), 41 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 26a80c085d..105292e2c4 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -9,7 +9,6 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" #include "sst/elements/carcosa/faultlogic/stuckAtFault.h" @@ -23,8 +22,12 @@ FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injec // what do we need in here? } -SST::Output& FaultInjectorBase::FaultBase::getSimulationOutput() { - return _injector->getSimulationOutput(); +SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { + return _injector->out_; +} + +SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { + return _injector->dbg_; } SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { @@ -33,6 +36,10 @@ SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event if (mem_ev == nullptr) { _injector->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); } + +#ifdef __SST_DEBUG_OUTPUT__ + _injector->dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); +#endif return mem_ev; } @@ -42,20 +49,20 @@ dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(_L10_, "Payload before replacement:\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Payload before replacement:\n"); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(_L10_, "%d\t"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "%d\t"); } - _injector->getSimulationOutput().debug(_L10_, "\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\n"); #endif convertMemEvent(ev)->setPayload(newPayload); #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(_L10_, "Payload after replacement:\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Payload after replacement:\n"); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(_L10_, "%d\t"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "%d\t"); } - _injector->getSimulationOutput().debug(_L10_, "\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\n"); #endif } @@ -78,8 +85,14 @@ FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemE FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() { + out_ = new Output(); + out_->init("", params.find("verbose", 1), 0, Output::STDOUT); + + dbg_ = new Output(); + dbg_->init("", params.find("debug_level", 1), 0, (Output::output_location_t)params.find("debug", 0)); + #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n"); + dbg_->debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n"); #endif std::string install_dir = params.find("installDirection", "Receive"); @@ -91,15 +104,15 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() } } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir); + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); #endif injectionProbability_ = params.find("injectionProbability", "0.5"); if ( injectionProbability_ < 0.0 || injectionProbability_ > 1.0 ) { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "\tInjection probability outside of bounds. Must be in the following range: [0.0,1.0].\n"); + out_->fatal(CALL_INFO_LONG, -1, "\tInjection probability outside of bounds. Must be in the following range: [0.0,1.0].\n"); } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %d\n", injectionProbability_); + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif fault = new StuckAtFault(params, this);//FaultBase(params, this); diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index fa9c8cc9df..af6dfaada0 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -16,6 +16,7 @@ #include "sst/core/event.h" #include "sst/core/output.h" #include "sst/elements/memHierarchy/memEvent.h" +#include namespace SST::Carcosa { @@ -74,7 +75,9 @@ class FaultInjectorBase : public SST::PortModule virtual void faultLogic(Event*& ev) {} - SST::Output& getSimulationOutput(); + SST::Output*& getSimulationOutput(); + + SST::Output*& getSimulationDebug(); SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); @@ -152,6 +155,9 @@ class FaultInjectorBase : public SST::PortModule installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; + SST::Output* out_; + SST::Output* dbg_; + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index f2e9a3a675..5c3b1d5514 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -18,7 +18,7 @@ using namespace SST::Carcosa; StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\Fault Type: Stuck-At Fault"); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault Type: Stuck-At Fault\n"); #endif // read in masks // parameter format: {masks: ["addr, byte, zeroMask, oneMask"]} @@ -33,35 +33,35 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB uint8_t zeroMask = param->zeroMask; uint8_t oneMask = param->oneMask; if ((int)(zeroMask & oneMask) > 0) { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Masks contain overlapping values. Addr: 0x%zu, " + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Masks contain overlapping values. Addr: 0x%zx, " "byte: %d\n", addr, byte); } // check for vector in each map before creating it if (stuckAtZeroMask.count(addr) == 1) { stuckAtZeroMask.at(addr).push_back(make_pair(byte, zeroMask)); } else { - auto maskVec = stuckAtZeroMask.emplace(make_pair(addr, std::vector>())); - if (maskVec.second) { - maskVec.first->second.push_back(make_pair(byte, zeroMask)); + auto addrVecPair = stuckAtZeroMask.emplace(make_pair(addr, std::vector>())); + if (addrVecPair.second) { + addrVecPair.first->second.push_back(make_pair(byte, zeroMask)); } else { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); } } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "Finished inserting zero-masks for 0x%zu.\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Finished inserting zero-masks for 0x%zx.\n", addr); #endif if (stuckAtOneMask.count(addr) == 1) { stuckAtOneMask.at(addr).push_back(make_pair(byte, oneMask)); } else { - auto maskVec = stuckAtOneMask.emplace(make_pair(addr, std::vector>())); - if (maskVec.second) { - maskVec.first->second.push_back(make_pair(byte, oneMask)); + auto addrVecPair = stuckAtOneMask.emplace(make_pair(addr, std::vector>())); + if (addrVecPair.second) { + addrVecPair.first->second.push_back(make_pair(byte, oneMask)); } else { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Failed to insert mask.\n"); } } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "Finished inserting one-masks for 0x%zu.\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Finished inserting one-masks for 0x%zx.\n", addr); #endif } } @@ -75,20 +75,20 @@ void StuckAtFault::faultLogic(SST::Event*& ev) { // check for the addr in question in the fault map if (stuckAtZeroMask.count(addr) == 1 || stuckAtOneMask.count(addr) == 1) { #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "Addr 0x%x found in stuck map.\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Addr 0x%zx found in stuck map.\n", addr); #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); uint8_t mask = 0b00000000; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "Begin zero mask for address: 0x%zu\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin zero mask for address: 0x%zx\n", addr); #endif if (stuckAtZeroMask.count(addr) == 1) { for (auto maskPair: stuckAtZeroMask.at(addr)) { mask = maskPair.second; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", maskPair.first, (int)payload[maskPair.first], (int) mask, (int)(payload[maskPair.first] &= (!mask))); #endif @@ -96,21 +96,21 @@ void StuckAtFault::faultLogic(SST::Event*& ev) { } } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "End zero mask for address: 0x%zu\n", addr); - getSimulationOutput().debug(_L10_, "Begin one mask for address: 0x%zu\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End zero mask for address: 0x%zx\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin one mask for address: 0x%zx\n", addr); #endif if (stuckAtOneMask.count(addr) == 1) { for (auto maskPair: stuckAtOneMask.at(addr)) { mask = maskPair.second; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", maskPair.first, (int)payload[maskPair.first], (int) mask, (int)(payload[maskPair.first] |= mask)); #endif payload[maskPair.first] |= mask; } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "End one mask for address: 0x%zu\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End one mask for address: 0x%zx\n", addr); #endif } @@ -125,7 +125,7 @@ std::vector StuckAtFault::convertString(std::vector> addr; if (stream.peek() == ',') { @@ -135,16 +135,18 @@ std::vector StuckAtFault::convertString(std::vector> zeroMask; + stream >> zeroMaskStr; + zeroMask = static_cast(std::bitset<8>(zeroMaskStr).to_ulong()); if (stream.peek() == ',') { stream.ignore(); } - stream >> oneMask; + stream >> oneMaskStr; + oneMask = static_cast(std::bitset<8>(oneMaskStr).to_ulong()); if (stream.peek() == ',') { stream.ignore(); } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationOutput().debug(_L10_, "Masks for addr 0x%zu, byte %d: %d %d", addr, byte, (int)zeroMask, (int)oneMask); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Masks for addr 0x%zx, byte %d: %d %d\n", addr, byte, (int)zeroMask, (int)oneMask); #endif // insert maskParam paramVec.push_back({addr, byte, zeroMask, oneMask}); diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index cbf3e1a46c..9b54dfab12 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -17,6 +17,7 @@ #include #include #include +#include namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index aca42255d2..c005dd8931 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -69,7 +69,7 @@ sst.setStatisticLoadLevel(4) sst.setStatisticOutput("sst.statOutputConsole") -full_exe_name = "../../vanadis/tests/small/basic-io/hello-world/riscv64/hello-world"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) exe_name= full_exe_name.split("/")[-1] verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) @@ -381,11 +381,18 @@ def build( self, prefix, nodeId, cpuId ): cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") cpu_l2cache.addParams( l2cacheParams ) cpu_l2cache.addPortModule("highlink","carcosa.faultInjectorBase", { - "installDirection": "Send", + "installDirection": "Receive", "injectionProbability": 1, - "masks": ["10, 3, 11110000, 00001111"], + "masks": ["11264, 3, 11110000, 00001111"], "debug" : 1, - "debug_level": 10 + "debug_level": 1 + }) + cpu_l2cache.addPortModule("lowlink","carcosa.faultInjectorBase", { + "installDirection": "Receive", + "injectionProbability": 1, + "masks": ["11264, 3, 11110000, 00001111"], + "debug" : 1, + "debug_level": 1 }) # L2 cache mem interface From c7e44a25b6c83c7c7327fb47ac75c6af87bcae7c Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 18 Sep 2025 15:49:20 -0400 Subject: [PATCH 17/45] corruptMemRegion written compiler is giving me errors that the exact same code didn't give in the last fault--will test when this is resolved --- src/sst/elements/carcosa/Makefile.am | 18 +++-- src/sst/elements/carcosa/faultInjectorBase.cc | 16 ++-- src/sst/elements/carcosa/faultInjectorBase.h | 2 + .../carcosa/faultlogic/corruptMemRegion.cc | 76 +++++++++++++++++++ .../carcosa/faultlogic/corruptMemRegion.h | 61 +++++++++++++++ src/sst/elements/carcosa/tests/dummyTest.py | 21 ++--- 6 files changed, 165 insertions(+), 29 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 2cf65133ca..37c11fa7a7 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -8,18 +8,22 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la -libcarcosa_la_SOURCES = \ - faultInjectorBase.cc \ - faultInjectorBase.h \ - faultlogic/stuckAtFault.cc \ - faultlogic/stuckAtFault.h +libcarcosa_la_SOURCES = \ + faultInjectorBase.cc \ + faultInjectorBase.h \ + faultlogic/stuckAtFault.cc \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemRegion.cc \ + faultlogic/corruptMemRegion.h EXTRA_DIST = \ dummyTest.py sstdir = $(includedir)/sst/elements/carcosa -nobase_sst_HEADERS = \ - faultInjectorBase.h +nobase_sst_HEADERS = \ + faultInjectorBase.h \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemRegion.h libcarcosa_la_LDFLAGS = -module -avoid-version libcarcosa_la_LIBADD = diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 105292e2c4..b3bf0fb74f 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -11,7 +11,7 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" -#include "sst/elements/carcosa/faultlogic/stuckAtFault.h" +#include "sst/elements/carcosa/faultlogic/corruptMemRegion.h" using namespace SST::Carcosa; @@ -49,20 +49,20 @@ dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Payload before replacement:\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "%d\t"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif convertMemEvent(ev)->setPayload(newPayload); #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "Payload after replacement:\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "%d\t"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 1, 0, "\n"); + _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif } @@ -115,7 +115,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - fault = new StuckAtFault(params, this);//FaultBase(params, this); + fault = new CorruptMemRegion(params, this);//FaultBase(params, this); } void diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index af6dfaada0..f7efb63d72 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -110,6 +110,8 @@ class FaultInjectorBase : public SST::PortModule SST_ELI_DOCUMENT_PARAMS( {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, + {"debug", "Integer determining if debug should be active. 0 disables, 1 sends output to STDOUT, 2 to STDERR. Default = 0"}, + {"debug_level", "Integer determining verbosity of debug output. 1 enables basic text output, 2 enables signficant activity output."} ) // SST_ELI_DOCUMENT_STATISTICS( diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc b/src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc new file mode 100644 index 0000000000..33aa559cd3 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc @@ -0,0 +1,76 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/faultlogic/corruptMemRegion.h" + +using namespace SST::Carcosa; + +CorruptMemRegion::CorruptMemRegion(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault type: Corrupt Memory Region\n"); +#endif + // read in data regions + std::vector regionVec; + + // parameter format: {"regions": ["start_addr0, end_addr0", "start_addr1, end_addr1",...]} + params.find_array("regions", regionVec); + + // process entries into region + for (std::string region: regionVec) { + std::pair region_pair = convertString(region); + + // check validity + if (region_pair.first > region_pair.second) { + getSimulationOutput()->fatal(CALL_INFO_LONG, 1, 0, "Invalid corruption region: [0x%zx, 0x%zx].\n", + region_pair.first, region_pair.second); + } + + corruptionRegions.push_back(region_pair); +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Inserted corruption region: [0x%zx, 0x%zx]\n", + region_pair.first, region_pair.second); +#endif + } + distribution = std::uniform_int_distribution(0,255); +} + +void CorruptMemRegion::faultLogic(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); + + Addr ev_addr = mem_ev->getAddr(); + for (auto& region: corruptionRegions) { + if ((ev_addr >= region.first) || (ev_addr <= region.second)) { + dataVec new_payload(8); + for (uint8_t& byte: new_payload) { + byte = distribution(generator); + } + setMemEventPayload(ev, new_payload); + break; + } + } +} + +std::pair CorruptMemRegion::convertString(std::string& region) { + std::stringstream ss(region); + uint64_t addr0, addr1; + + ss >> std::hex >> addr0; + if (ss.peek() == ','){ + ss.ignore(); + } + ss >> std::hex >> addr1; + + #ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Extracted region pair: [0x%zu, 0x%zx]\n", + addr0, addr1); + #endif + return make_pair(addr0, addr1); +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h b/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h index e69de29bb2..3eb10bad14 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h @@ -0,0 +1,61 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H +#define SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H + +#include "sst/elements/carcosa/faultInjectorBase.h" +#include +#include +#include +#include +#include + +namespace SST::Carcosa { + +typedef std::vector dataVec; +typedef SST::MemHierarchy::Addr Addr; + +/** + * This fault is intended to be placed on the input/output ports + * of memory components such as DRAM or HBM. Events that pass through + * it, and whose data addresses fall within the ranges set in this + * module's parameters, will have their payloads randomly altered + * to simulate corruption in the affected region of memory. + */ +class CorruptMemRegion : public FaultInjectorBase::FaultBase +{ +public: + + CorruptMemRegion(Params& params, FaultInjectorBase* injector); + + CorruptMemRegion() = default; + ~CorruptMemRegion() {} + + /** + * 1. Read in event + * 2. Test if event is in specified region + * 3. Corrupt event payload if necessary + * 4. Replace payload + */ + void faultLogic(Event*& ev) override; +protected: + + std::vector> corruptionRegions; + + std::default_random_engine generator; + std::uniform_int_distribution distribution; + + std::pair convertString(std::string& region); +}; // CorruptMemRegion +} // namespace SST::Carcosa + +#endif // SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H \ No newline at end of file diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index c005dd8931..520a50330d 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -380,20 +380,6 @@ def build( self, prefix, nodeId, cpuId ): # L2 cache cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") cpu_l2cache.addParams( l2cacheParams ) - cpu_l2cache.addPortModule("highlink","carcosa.faultInjectorBase", { - "installDirection": "Receive", - "injectionProbability": 1, - "masks": ["11264, 3, 11110000, 00001111"], - "debug" : 1, - "debug_level": 1 - }) - cpu_l2cache.addPortModule("lowlink","carcosa.faultInjectorBase", { - "installDirection": "Receive", - "injectionProbability": 1, - "masks": ["11264, 3, 11110000, 00001111"], - "debug" : 1, - "debug_level": 1 - }) # L2 cache mem interface l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") @@ -510,6 +496,13 @@ def addParamsPrefix(prefix,params): # node memory controller memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) +memctrl.addPortModule("highlink", "carcosa.faultInjectorBase", { + "intallDirection": "Receive", + "injectionProbability": 1. + "debug" : 1, + "debug_level": 2, + "regions": ["ABCDEFAB, DEADBEEF"] +}) # node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") From 072837fadfe20e6eb308e3f53f812b2ce94e0696 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 18 Sep 2025 16:44:05 -0400 Subject: [PATCH 18/45] COMPILER DEFEATED --- src/sst/elements/carcosa/Makefile.am | 6 +++--- src/sst/elements/carcosa/faultInjectorBase.cc | 4 ++-- .../{corruptMemRegion.cc => corruptMemFault.cc} | 8 ++++---- .../{corruptMemRegion.h => corruptMemFault.h} | 16 ++++++++-------- src/sst/elements/carcosa/tests/dummyTest.py | 2 +- 5 files changed, 18 insertions(+), 18 deletions(-) rename src/sst/elements/carcosa/faultlogic/{corruptMemRegion.cc => corruptMemFault.cc} (88%) rename src/sst/elements/carcosa/faultlogic/{corruptMemRegion.h => corruptMemFault.h} (80%) diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 37c11fa7a7..4ed93f9377 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -13,8 +13,8 @@ libcarcosa_la_SOURCES = \ faultInjectorBase.h \ faultlogic/stuckAtFault.cc \ faultlogic/stuckAtFault.h \ - faultlogic/corruptMemRegion.cc \ - faultlogic/corruptMemRegion.h + faultlogic/corruptMemFault.cc \ + faultlogic/corruptMemFault.h EXTRA_DIST = \ dummyTest.py @@ -23,7 +23,7 @@ sstdir = $(includedir)/sst/elements/carcosa nobase_sst_HEADERS = \ faultInjectorBase.h \ faultlogic/stuckAtFault.h \ - faultlogic/corruptMemRegion.h + faultlogic/corruptMemFault.h libcarcosa_la_LDFLAGS = -module -avoid-version libcarcosa_la_LIBADD = diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index b3bf0fb74f..a48c9b2d0d 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -11,7 +11,7 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" -#include "sst/elements/carcosa/faultlogic/corruptMemRegion.h" +#include "sst/elements/carcosa/faultlogic/corruptMemFault.h" using namespace SST::Carcosa; @@ -115,7 +115,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - fault = new CorruptMemRegion(params, this);//FaultBase(params, this); + fault = new CorruptMemFault(params, this);//FaultBase(params, this); } void diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc similarity index 88% rename from src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc rename to src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index 33aa559cd3..3208140d4b 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -9,11 +9,11 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include "sst/elements/carcosa/faultlogic/corruptMemRegion.h" +#include "sst/elements/carcosa/faultlogic/corruptMemFault.h" using namespace SST::Carcosa; -CorruptMemRegion::CorruptMemRegion(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { +CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault type: Corrupt Memory Region\n"); #endif @@ -42,7 +42,7 @@ CorruptMemRegion::CorruptMemRegion(Params& params, FaultInjectorBase* injector) distribution = std::uniform_int_distribution(0,255); } -void CorruptMemRegion::faultLogic(Event*& ev) { +void CorruptMemFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); Addr ev_addr = mem_ev->getAddr(); @@ -58,7 +58,7 @@ void CorruptMemRegion::faultLogic(Event*& ev) { } } -std::pair CorruptMemRegion::convertString(std::string& region) { +std::pair CorruptMemFault::convertString(std::string& region) { std::stringstream ss(region); uint64_t addr0, addr1; diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h similarity index 80% rename from src/sst/elements/carcosa/faultlogic/corruptMemRegion.h rename to src/sst/elements/carcosa/faultlogic/corruptMemFault.h index 3eb10bad14..b591f9ebdd 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemRegion.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -9,8 +9,8 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H -#define SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H +#ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H +#define SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H #include "sst/elements/carcosa/faultInjectorBase.h" #include @@ -31,14 +31,14 @@ typedef SST::MemHierarchy::Addr Addr; * module's parameters, will have their payloads randomly altered * to simulate corruption in the affected region of memory. */ -class CorruptMemRegion : public FaultInjectorBase::FaultBase +class CorruptMemFault : public FaultInjectorBase::FaultBase { public: - CorruptMemRegion(Params& params, FaultInjectorBase* injector); + CorruptMemFault(Params& params, FaultInjectorBase* injector); - CorruptMemRegion() = default; - ~CorruptMemRegion() {} + CorruptMemFault() = default; + ~CorruptMemFault() {} /** * 1. Read in event @@ -55,7 +55,7 @@ class CorruptMemRegion : public FaultInjectorBase::FaultBase std::uniform_int_distribution distribution; std::pair convertString(std::string& region); -}; // CorruptMemRegion +}; // CorruptMemFault } // namespace SST::Carcosa -#endif // SST_ELEMENTS_CARCOSA_CORRUPTMEMREGION_H \ No newline at end of file +#endif // SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H \ No newline at end of file diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index 520a50330d..c005af3527 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -498,7 +498,7 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) memctrl.addPortModule("highlink", "carcosa.faultInjectorBase", { "intallDirection": "Receive", - "injectionProbability": 1. + "injectionProbability": 1, "debug" : 1, "debug_level": 2, "regions": ["ABCDEFAB, DEADBEEF"] From 7338bb68b446dd17f592bcb4899601fd8962d4db Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 29 Sep 2025 14:56:18 -0400 Subject: [PATCH 19/45] randomFlip files added randomDrop prototype complete--untested --- src/sst/elements/carcosa/Makefile.am | 12 ++- src/sst/elements/carcosa/faultInjectorBase.cc | 73 +++++++++++++------ src/sst/elements/carcosa/faultInjectorBase.h | 36 ++++++--- .../carcosa/faultlogic/randomDropFault.cc | 29 ++++++++ .../carcosa/faultlogic/randomDropFault.h | 36 +++++++++ .../carcosa/faultlogic/randomFlipFault.cc | 22 ++++++ .../carcosa/faultlogic/randomFlipFault.h | 30 ++++++++ .../carcosa/faultlogic/stuckAtFault.cc | 3 + 8 files changed, 204 insertions(+), 37 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/randomDropFault.cc create mode 100644 src/sst/elements/carcosa/faultlogic/randomDropFault.h create mode 100644 src/sst/elements/carcosa/faultlogic/randomFlipFault.cc create mode 100644 src/sst/elements/carcosa/faultlogic/randomFlipFault.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 4ed93f9377..95c064678d 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -13,8 +13,12 @@ libcarcosa_la_SOURCES = \ faultInjectorBase.h \ faultlogic/stuckAtFault.cc \ faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.cc \ - faultlogic/corruptMemFault.h + faultlogic/corruptMemFault.cc \ + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.cc \ + faultlogic/randomDropFault.h \ + faultlogic/randomFlipFault.cc \ + faultlogic/randomFlipFault.h EXTRA_DIST = \ dummyTest.py @@ -23,7 +27,9 @@ sstdir = $(includedir)/sst/elements/carcosa nobase_sst_HEADERS = \ faultInjectorBase.h \ faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.h + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.h \ + faultlogic/randomFlipFault.h libcarcosa_la_LDFLAGS = -module -avoid-version libcarcosa_la_LIBADD = diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index a48c9b2d0d..b5939eacff 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -17,28 +17,48 @@ using namespace SST::Carcosa; /************** FaultBase **************/ -FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : _injector(injector) +FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : injector_(injector) { - // what do we need in here? + // initialize random distribution + distribution_ = std::uniform_real_distribution(0,1); } SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { - return _injector->out_; + return injector_->out_; } SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { - return _injector->dbg_; + return injector_->dbg_; +} + +installDirection FaultInjectorBase::FaultBase::setInstallDirection(std::string param) { + if ( param != "Receive" ) { + if ( param == "Send" ) { + if (std::find(valid_installation_.begin(), valid_installation_.end(), installDirection::Send) != valid_installation_.end()) { + return installDirection::Send; + } else { + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); + } + } else { + if (std::find(valid_installation_.begin(), valid_installation_.end(), installDirection::Receive) != valid_installation_.end()) { + return installDirection::Receive; + } else { + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); + } + } + } + return installDirection::Invalid; } SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); if (mem_ev == nullptr) { - _injector->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); + injector_->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); } #ifdef __SST_DEBUG_OUTPUT__ - _injector->dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); + injector_->dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); #endif return mem_ev; } @@ -49,20 +69,20 @@ dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif convertMemEvent(ev)->setPayload(newPayload); #ifdef __SST_DEBUG_OUTPUT__ - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - _injector->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); + injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif } @@ -81,6 +101,11 @@ FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemE } } +bool FaultInjectorBase::FaultBase::doInjection() { + double rand_val = distribution_(generator_); + return rand_val <= injector_->getInjectionProb(); +} + /********** FaultInjectorBase **********/ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() @@ -94,18 +119,6 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n"); #endif - std::string install_dir = params.find("installDirection", "Receive"); - - if ( install_dir != "Receive" ) { - if ( install_dir == "Send" ) { - installDirection_ = installDirection::Send; - } else { - installDirection_ = installDirection::Receive; - } - } -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); -#endif injectionProbability_ = params.find("injectionProbability", "0.5"); if ( injectionProbability_ < 0.0 || injectionProbability_ > 1.0 ) { @@ -116,6 +129,17 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #endif fault = new CorruptMemFault(params, this);//FaultBase(params, this); + + std::string install_dir = params.find("installDirection", "Receive"); + installDirection_ = fault->setInstallDirection(install_dir); + + if (installDirection_ == installDirection::Invalid) { + out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid!\n"); + } + +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); +#endif } void @@ -129,6 +153,7 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) { // do not cancel delivery by default cancel = false; + cancel_ = &cancel; fault->faultLogic(ev); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index f7efb63d72..8bb6824b4c 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -17,6 +17,9 @@ #include "sst/core/output.h" #include "sst/elements/memHierarchy/memEvent.h" #include +#include +#include +#include namespace SST::Carcosa { @@ -32,15 +35,6 @@ enum installDirection { Invalid }; -// Enum to select basic fault injection logic or indicate a custom input -enum injectorLogic { - StuckAt = 0, - RandomFlip, - RandomDrop, - CorruptMemRegion, - Custom -}; - /** * Base class containing required functions and basic data for * creating fault injection on component ports @@ -79,6 +73,8 @@ class FaultInjectorBase : public SST::PortModule SST::Output*& getSimulationDebug(); + installDirection setInstallDirection(std::string param); + SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); dataVec& getMemEventPayload(Event*& ev); @@ -87,9 +83,15 @@ class FaultInjectorBase : public SST::PortModule memEventType getMemEventCommandType(Event*& ev); + bool doInjection(); + protected: - FaultInjectorBase* _injector = nullptr; + FaultInjectorBase* injector_ = nullptr; + + std::vector valid_installation_; + std::default_random_engine generator_; + std::uniform_real_distribution distribution_; // TODO: Figure out how to properly set up serialization for this // void serialize_order(SST::Core::Serialization::serializer& ser) // { @@ -151,9 +153,23 @@ class FaultInjectorBase : public SST::PortModule } } + double getInjectionProb() { + return injectionProbability_; + } + + void cancelDelivery() { + *cancel_ = true; + } + + installDirection getInstallDirection() { + return installDirection_; + } + protected: FaultBase* fault; + bool* cancel_; + installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc new file mode 100644 index 0000000000..31045f56f2 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -0,0 +1,29 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/faultlogic/randomDropFault.h" + +using namespace SST::Carcosa; + +RandomDropFault::RandomDropFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { + // +} + +void RandomDropFault::faultLogic(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); + + if (this->doInjection()) { + delete mem_ev; + if (injector_->getInstallDirection() == installDirection::Receive) { + injector_->cancelDelivery(); + } + } +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.h b/src/sst/elements/carcosa/faultlogic/randomDropFault.h new file mode 100644 index 0000000000..d26dd2697e --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.h @@ -0,0 +1,36 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_RANDOMDROPFAULT_H +#define SST_ELEMENTS_CARCOSA_RANDOMDROPFAULT_H + +#include "sst/elements/carcosa/faultInjectorBase.h" +#include +#include + +namespace SST::Carcosa { + +class RandomDropFault : public FaultInjectorBase::FaultBase { +public: + RandomDropFault(Params& params, FaultInjectorBase* injector); + + RandomDropFault() = default; + ~RandomDropFault() {} + + void faultLogic(Event*& ev) override; +protected: + std::default_random_engine generator; + std::uniform_real_distribution distribution; +}; // RandomDropFault + +} // namespace SST::Carcosa + +#endif // SST_ELEMENTS_CARCOSA_RANDOMDROPFAULT_H \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc new file mode 100644 index 0000000000..d285a0b237 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -0,0 +1,22 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/faultlogic/randomFlipFault.h" + +using namespace SST::Carcosa; + +RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { + // +} + +void RandomFlipFault::faultLogic() { + // +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h new file mode 100644 index 0000000000..479771fe16 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -0,0 +1,30 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULT_H +#define SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULT_H + +#include "sst/elements/carcosa/faultInjectorBase.h" + +namespace SST::Carcosa { + +class RandomFlipFault : public FaultInjectorBase::FaultBase { +public: + RandomFlipFault(Params& params, FaultInjectorBase* injector); + + RandomFlipFault() = default; + ~RandomFlipFault() {} + + void faultLogic(Event*& ev) override; +}; // RandomFlipFault +} + +#endif // SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULT_H \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 5c3b1d5514..6e2e98c568 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -20,6 +20,9 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault Type: Stuck-At Fault\n"); #endif + // set valid install direction + valid_installation_.push_back(installDirection::Send); + valid_installation_.push_back(installDirection::Receive); // read in masks // parameter format: {masks: ["addr, byte, zeroMask, oneMask"]} std::vector paramVecStr; From fe572d76863d15037a8376031f3f01aa2099caac Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 29 Sep 2025 14:58:00 -0400 Subject: [PATCH 20/45] fix faultlogic parameters on randomFlip --- src/sst/elements/carcosa/faultlogic/randomFlipFault.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index d285a0b237..d3a30bfa99 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -17,6 +17,6 @@ RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : // } -void RandomFlipFault::faultLogic() { +void RandomFlipFault::faultLogic(Event*& ev) { // } \ No newline at end of file From 7616b286ea6fc15c5be73340f2ebddaddaece24e Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 2 Oct 2025 14:25:07 -0400 Subject: [PATCH 21/45] all basic faults built need to refine other aspects (such as payload printing) --- src/sst/elements/carcosa/faultInjectorBase.cc | 48 +++++++++---------- src/sst/elements/carcosa/faultInjectorBase.h | 15 +++++- .../carcosa/faultlogic/corruptMemFault.cc | 1 + .../carcosa/faultlogic/randomDropFault.cc | 2 +- .../carcosa/faultlogic/randomDropFault.h | 6 +-- .../carcosa/faultlogic/randomFlipFault.cc | 23 ++++++++- .../carcosa/faultlogic/randomFlipFault.h | 9 ++++ .../carcosa/faultlogic/stuckAtFault.cc | 3 +- src/sst/elements/carcosa/tests/dummyTest.py | 3 +- 9 files changed, 74 insertions(+), 36 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index b5939eacff..27b681fc40 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -11,7 +11,7 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" -#include "sst/elements/carcosa/faultlogic/corruptMemFault.h" +#include "sst/elements/carcosa/faultlogic/randomFlipFault.h" using namespace SST::Carcosa; @@ -23,28 +23,26 @@ FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injec distribution_ = std::uniform_real_distribution(0,1); } -SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { +inline SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { return injector_->out_; } -SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { +inline SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { return injector_->dbg_; } installDirection FaultInjectorBase::FaultBase::setInstallDirection(std::string param) { - if ( param != "Receive" ) { - if ( param == "Send" ) { - if (std::find(valid_installation_.begin(), valid_installation_.end(), installDirection::Send) != valid_installation_.end()) { - return installDirection::Send; - } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); - } + if ( param == "Receive" ) { + if (valid_installation_[0]) { + return installDirection::Receive; } else { - if (std::find(valid_installation_.begin(), valid_installation_.end(), installDirection::Receive) != valid_installation_.end()) { - return installDirection::Receive; - } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); - } + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); + } + } else if ( param == "Send" ) { + if (valid_installation_[1]) { + return installDirection::Send; + } else { + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); } } return installDirection::Invalid; @@ -63,26 +61,26 @@ SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event return mem_ev; } -dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { +inline dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { return convertMemEvent(ev)->getPayload(); } void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { #ifdef __SST_DEBUG_OUTPUT__ - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif convertMemEvent(ev)->setPayload(newPayload); #ifdef __SST_DEBUG_OUTPUT__ - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); for (int i: convertMemEvent(ev)->getPayload()) { - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); } - injector_->getSimulationOutput().debug(CALL_INFO_LONG, 2, 0, "]\n"); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif } @@ -101,7 +99,7 @@ FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemE } } -bool FaultInjectorBase::FaultBase::doInjection() { +inline bool FaultInjectorBase::FaultBase::doInjection() { double rand_val = distribution_(generator_); return rand_val <= injector_->getInjectionProb(); } @@ -128,13 +126,13 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - fault = new CorruptMemFault(params, this);//FaultBase(params, this); + fault = new RandomFlipFault(params, this);//FaultBase(params, this); std::string install_dir = params.find("installDirection", "Receive"); installDirection_ = fault->setInstallDirection(install_dir); if (installDirection_ == installDirection::Invalid) { - out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid!\n"); + out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); } #ifdef __SST_DEBUG_OUTPUT__ diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 8bb6824b4c..af76d2ded3 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -89,9 +89,22 @@ class FaultInjectorBase : public SST::PortModule FaultInjectorBase* injector_ = nullptr; - std::vector valid_installation_; + bool valid_installation_[2] = {false, false}; std::default_random_engine generator_; std::uniform_real_distribution distribution_; + + void toggleReceiveValid() { + valid_installation_[0] = true; + } + + void toggleSendValid() { + valid_installation_[1] = true; + } + + void toggleSendReceiveValid() { + valid_installation_[0] = true; + valid_installation_[1] = true; + } // TODO: Figure out how to properly set up serialization for this // void serialize_order(SST::Core::Serialization::serializer& ser) // { diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index 3208140d4b..ed1a2c44ee 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -14,6 +14,7 @@ using namespace SST::Carcosa; CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { + toggleSendReceiveValid(); #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault type: Corrupt Memory Region\n"); #endif diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc index 31045f56f2..05879ca98e 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -14,7 +14,7 @@ using namespace SST::Carcosa; RandomDropFault::RandomDropFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { - // + toggleReceiveValid(); } void RandomDropFault::faultLogic(Event*& ev) { diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.h b/src/sst/elements/carcosa/faultlogic/randomDropFault.h index d26dd2697e..2758d2a748 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.h @@ -15,9 +15,12 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include #include +#include namespace SST::Carcosa { +typedef std::vector dataVec; + class RandomDropFault : public FaultInjectorBase::FaultBase { public: RandomDropFault(Params& params, FaultInjectorBase* injector); @@ -26,9 +29,6 @@ class RandomDropFault : public FaultInjectorBase::FaultBase { ~RandomDropFault() {} void faultLogic(Event*& ev) override; -protected: - std::default_random_engine generator; - std::uniform_real_distribution distribution; }; // RandomDropFault } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index d3a30bfa99..e4d69c1a17 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -14,9 +14,28 @@ using namespace SST::Carcosa; RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { - // + this->int_distribution = uniform_int_distribution(0,8); + toggleSendReceiveValid(); } void RandomFlipFault::faultLogic(Event*& ev) { - // + // check if this is the proper event type and get payload if it is + dataVec payload = getMemEventPayload(ev); + // determine if injection occurs + if (this->doInjection()) { + std::pair lucky_number = pickByteAndBit(); + uint8_t byte = payload[lucky_number.first]; + uint8_t mask = static_cast(1) << (lucky_number.second); + payload[lucky_number.first] = byte ^ mask; + setMemEventPayload(ev, payload); + } +} + +inline std::pair RandomFlipFault::pickByteAndBit() { + uint32_t byte = int_distribution(int_generator); + uint32_t bit = int_distribution(int_generator); +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Flipping bit %d in byte %d.\n", (int)bit, (int)byte); +#endif + return make_pair(byte, bit); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h index 479771fe16..b654228b4a 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -24,6 +24,15 @@ class RandomFlipFault : public FaultInjectorBase::FaultBase { ~RandomFlipFault() {} void faultLogic(Event*& ev) override; +protected: + std::default_random_engine int_generator; + std::uniform_int_distribution int_distribution; + + /** + * Randomly choose which bit in which byte to flip + * @return (byte, bit) + */ + inline std::pair pickByteAndBit(); }; // RandomFlipFault } diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 6e2e98c568..f4fd12ec22 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -21,8 +21,7 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault Type: Stuck-At Fault\n"); #endif // set valid install direction - valid_installation_.push_back(installDirection::Send); - valid_installation_.push_back(installDirection::Receive); + toggleSendReceiveValid(); // read in masks // parameter format: {masks: ["addr, byte, zeroMask, oneMask"]} std::vector paramVecStr; diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index c005af3527..14512b1cd6 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -500,8 +500,7 @@ def addParamsPrefix(prefix,params): "intallDirection": "Receive", "injectionProbability": 1, "debug" : 1, - "debug_level": 2, - "regions": ["ABCDEFAB, DEADBEEF"] + "debug_level": 2 }) # node memory controller backend From a04017a6a93993fb34215170e4da4b82e91f4f99 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 2 Oct 2025 14:25:45 -0400 Subject: [PATCH 22/45] add missed file --- src/sst/elements/carcosa/faultInjectorBase.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index af76d2ded3..9f9c18d38e 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -69,21 +69,21 @@ class FaultInjectorBase : public SST::PortModule virtual void faultLogic(Event*& ev) {} - SST::Output*& getSimulationOutput(); + inline SST::Output*& getSimulationOutput(); - SST::Output*& getSimulationDebug(); + inline SST::Output*& getSimulationDebug(); installDirection setInstallDirection(std::string param); SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); - dataVec& getMemEventPayload(Event*& ev); + inline dataVec& getMemEventPayload(Event*& ev); void setMemEventPayload(Event*& ev, dataVec newPayload); memEventType getMemEventCommandType(Event*& ev); - bool doInjection(); + inline bool doInjection(); protected: From e3527e3ca5ed4751056611c75e9627db42311b7d Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 2 Oct 2025 14:57:53 -0400 Subject: [PATCH 23/45] remove inlining add debug output to event dropper need to compare event drop logic to scott's portmodule example (just to make sure I'm not breaking anything on accident) --- src/sst/elements/carcosa/faultInjectorBase.cc | 12 ++++++------ src/sst/elements/carcosa/faultInjectorBase.h | 8 ++++---- .../elements/carcosa/faultlogic/randomDropFault.cc | 3 +++ 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 27b681fc40..4f22bfdebc 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -11,7 +11,7 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" -#include "sst/elements/carcosa/faultlogic/randomFlipFault.h" +#include "sst/elements/carcosa/faultlogic/randomDropFault.h" using namespace SST::Carcosa; @@ -23,11 +23,11 @@ FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injec distribution_ = std::uniform_real_distribution(0,1); } -inline SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { +SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { return injector_->out_; } -inline SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { +SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { return injector_->dbg_; } @@ -61,7 +61,7 @@ SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event return mem_ev; } -inline dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { +dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { return convertMemEvent(ev)->getPayload(); } @@ -99,7 +99,7 @@ FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemE } } -inline bool FaultInjectorBase::FaultBase::doInjection() { +bool FaultInjectorBase::FaultBase::doInjection() { double rand_val = distribution_(generator_); return rand_val <= injector_->getInjectionProb(); } @@ -126,7 +126,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - fault = new RandomFlipFault(params, this);//FaultBase(params, this); + fault = new RandomDropFault(params, this);//FaultBase(params, this); std::string install_dir = params.find("installDirection", "Receive"); installDirection_ = fault->setInstallDirection(install_dir); diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 9f9c18d38e..af76d2ded3 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -69,21 +69,21 @@ class FaultInjectorBase : public SST::PortModule virtual void faultLogic(Event*& ev) {} - inline SST::Output*& getSimulationOutput(); + SST::Output*& getSimulationOutput(); - inline SST::Output*& getSimulationDebug(); + SST::Output*& getSimulationDebug(); installDirection setInstallDirection(std::string param); SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); - inline dataVec& getMemEventPayload(Event*& ev); + dataVec& getMemEventPayload(Event*& ev); void setMemEventPayload(Event*& ev, dataVec newPayload); memEventType getMemEventCommandType(Event*& ev); - inline bool doInjection(); + bool doInjection(); protected: diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc index 05879ca98e..459204014f 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -25,5 +25,8 @@ void RandomDropFault::faultLogic(Event*& ev) { if (injector_->getInstallDirection() == installDirection::Receive) { injector_->cancelDelivery(); } +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Event dropped.\n"); +#endif } } \ No newline at end of file From af1f5ddcf9717a783193fa6bca47723aa32b1af7 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 3 Oct 2025 16:32:16 -0400 Subject: [PATCH 24/45] major refactor skeletonized--time to make it work --- src/sst/elements/carcosa/Makefile.am | 36 ++-- src/sst/elements/carcosa/faultInjectorBase.cc | 175 +++++++----------- src/sst/elements/carcosa/faultInjectorBase.h | 125 +++++-------- .../carcosa/faultlogic/corruptMemFault.h | 2 +- .../elements/carcosa/faultlogic/faultBase.cc | 59 ++++++ .../elements/carcosa/faultlogic/faultBase.h | 51 +++++ .../carcosa/faultlogic/randomDropFault.h | 2 +- .../carcosa/faultlogic/randomFlipFault.cc | 1 + .../carcosa/faultlogic/randomFlipFault.h | 2 +- .../carcosa/faultlogic/stuckAtFault.cc | 4 +- .../carcosa/faultlogic/stuckAtFault.h | 2 +- .../corruptMemFaultInjector.cc} | 0 .../corruptMemFaultInjector.h} | 0 .../injectors/randomDropFaultInjector.cc | 0 .../injectors/randomDropFaultInjector.h | 0 .../injectors/randomFlipFaultInjector.cc | 0 .../injectors/randomFlipFaultInjector.h | 0 .../carcosa/injectors/stuckAtFaultInjector.cc | 33 ++++ .../carcosa/injectors/stuckAtFaultInjector.h | 45 +++++ src/sst/elements/carcosa/tests/dummyTest.py | 5 +- 20 files changed, 334 insertions(+), 208 deletions(-) create mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.cc create mode 100644 src/sst/elements/carcosa/faultlogic/faultBase.h rename src/sst/elements/carcosa/{faultlogic/randomDrop.h => injectors/corruptMemFaultInjector.cc} (100%) rename src/sst/elements/carcosa/{faultlogic/randomFlip.h => injectors/corruptMemFaultInjector.h} (100%) create mode 100644 src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc create mode 100644 src/sst/elements/carcosa/injectors/randomDropFaultInjector.h create mode 100644 src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc create mode 100644 src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h create mode 100644 src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc create mode 100644 src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 95c064678d..9c5bcb198f 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -8,27 +8,33 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la -libcarcosa_la_SOURCES = \ - faultInjectorBase.cc \ - faultInjectorBase.h \ - faultlogic/stuckAtFault.cc \ - faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.cc \ - faultlogic/corruptMemFault.h \ - faultlogic/randomDropFault.cc \ - faultlogic/randomDropFault.h \ - faultlogic/randomFlipFault.cc \ +libcarcosa_la_SOURCES = \ + faultInjectorBase.cc \ + faultInjectorBase.h \ + injectors/stuckAtFaultInjector.cc \ + injectors/stuckAtFaultInjector.h \ + faultlogic/faultBase.cc \ + faultlogic/faultBase.h \ + faultlogic/stuckAtFault.cc \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemFault.cc \ + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.cc \ + faultlogic/randomDropFault.h \ + faultlogic/randomFlipFault.cc \ faultlogic/randomFlipFault.h EXTRA_DIST = \ dummyTest.py sstdir = $(includedir)/sst/elements/carcosa -nobase_sst_HEADERS = \ - faultInjectorBase.h \ - faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.h \ - faultlogic/randomDropFault.h \ +nobase_sst_HEADERS = \ + faultInjectorBase.h \ + injectors/stuckAtFaultInjector.h \ + faultlogic/faultBase.h \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.h \ faultlogic/randomFlipFault.h libcarcosa_la_LDFLAGS = -module -avoid-version diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 4f22bfdebc..99df6bca00 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -11,99 +11,9 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include "sst/core/params.h" -#include "sst/elements/carcosa/faultlogic/randomDropFault.h" using namespace SST::Carcosa; -/************** FaultBase **************/ - -FaultInjectorBase::FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : injector_(injector) -{ - // initialize random distribution - distribution_ = std::uniform_real_distribution(0,1); -} - -SST::Output*& FaultInjectorBase::FaultBase::getSimulationOutput() { - return injector_->out_; -} - -SST::Output*& FaultInjectorBase::FaultBase::getSimulationDebug() { - return injector_->dbg_; -} - -installDirection FaultInjectorBase::FaultBase::setInstallDirection(std::string param) { - if ( param == "Receive" ) { - if (valid_installation_[0]) { - return installDirection::Receive; - } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); - } - } else if ( param == "Send" ) { - if (valid_installation_[1]) { - return installDirection::Send; - } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); - } - } - return installDirection::Invalid; -} - -SST::MemHierarchy::MemEvent* FaultInjectorBase::FaultBase::convertMemEvent(Event*& ev) { - SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); - - if (mem_ev == nullptr) { - injector_->getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); - } - -#ifdef __SST_DEBUG_OUTPUT__ - injector_->dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); -#endif - return mem_ev; -} - -dataVec& FaultInjectorBase::FaultBase::getMemEventPayload(Event*& ev) { - return convertMemEvent(ev)->getPayload(); -} - -void FaultInjectorBase::FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { -#ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); - for (int i: convertMemEvent(ev)->getPayload()) { - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); - } - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); -#endif - convertMemEvent(ev)->setPayload(newPayload); - -#ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); - for (int i: convertMemEvent(ev)->getPayload()) { - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); - } - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); -#endif -} - -FaultInjectorBase::FaultBase::memEventType FaultInjectorBase::FaultBase::getMemEventCommandType(Event*& ev) { - SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); - if (mem_ev->isDataRequest()) { - return FaultBase::memEventType::DataRequest; - } else if (mem_ev->isResponse()) { - return FaultBase::memEventType::Response; - } else if (mem_ev->isWriteback()) { - return FaultBase::memEventType::Writeback; - } else if (mem_ev->isRoutedByAddress()) { - return FaultBase::memEventType::RoutedByAddr; - } else { - return FaultBase::memEventType::Invalid; - } -} - -bool FaultInjectorBase::FaultBase::doInjection() { - double rand_val = distribution_(generator_); - return rand_val <= injector_->getInjectionProb(); -} - /********** FaultInjectorBase **********/ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() @@ -125,25 +35,29 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - - fault = new RandomDropFault(params, this);//FaultBase(params, this); - - std::string install_dir = params.find("installDirection", "Receive"); - installDirection_ = fault->setInstallDirection(install_dir); - - if (installDirection_ == installDirection::Invalid) { - out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); - } - -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); -#endif + // init randomizer + distribution_ = std::uniform_real_distribution(0,1); } void FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { - fault->faultLogic(ev); + if (doInjection()){ +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->(CALL_INFO_LONG, 1, 0, "Injection triggered.\n") +#endif + if (fault) { + fault->faultLogic(ev); + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } + } +#ifdef __SST_DEBUG_OUTPUT__ + else { + dbg_->(CALL_INFO_LONG, 1, 0, "Injection skipped.\n") + } +#endif + } void @@ -153,5 +67,56 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) cancel = false; cancel_ = &cancel; - fault->faultLogic(ev); + if (doInjection()){ +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->(CALL_INFO_LONG, 1, 0, "Injection triggered.\n") +#endif + if (fault) { + fault->faultLogic(ev); + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } + } +#ifdef __SST_DEBUG_OUTPUT__ + else { + dbg_->(CALL_INFO_LONG, 1, 0, "Injection skipped.\n") + } +#endif +} + +bool FaultInjectorBase::doInjection() { + double rand_val = distribution_(generator_); + return rand_val <= injector_->getInjectionProb(); +} + +void FaultInjectorBase::setInstallDirection(std::string param) { + if ( param == "Receive" ) { + if (valid_installation_[0]) { + installDirection_= installDirection::Receive; + } else { + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); + } + } else if ( param == "Send" ) { + if (valid_installation_[1]) { + installDirection_ = return installDirection::Send; + } else { + injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); + } + } + installDirection_= installDirection::Invalid; +} + +FaultInjectorBase::memEventType FaultInjectorBase::getMemEventCommandType(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); + if (mem_ev->isDataRequest()) { + return FaultBase::memEventType::DataRequest; + } else if (mem_ev->isResponse()) { + return FaultBase::memEventType::Response; + } else if (mem_ev->isWriteback()) { + return FaultBase::memEventType::Writeback; + } else if (mem_ev->isRoutedByAddress()) { + return FaultBase::memEventType::RoutedByAddr; + } else { + return FaultBase::memEventType::Invalid; + } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index af76d2ded3..b948d34f2e 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -16,6 +16,7 @@ #include "sst/core/event.h" #include "sst/core/output.h" #include "sst/elements/memHierarchy/memEvent.h" +#include "sst/elements/carcosa/faultlogic/faultBase.h" #include #include #include @@ -24,8 +25,7 @@ namespace SST::Carcosa { typedef std::vector dataVec; - -class FaultInjectorBase; +class FaultBase; /********** FaultInjectorBase **********/ @@ -42,84 +42,13 @@ enum installDirection { class FaultInjectorBase : public SST::PortModule { public: - /************** FaultBase **************/ - - /** TODO: - * Parameters for switching between interface-driven and normal instantiation - * A way to read in data to choose which logic to use - * - Might be possible to parameterize the entirety of the logic, but would be easier if I can - * build a "library" of functions that are loaded dynamically - */ - - class FaultBase { - public: - - enum memEventType { - DataRequest = 0, - Response, - Writeback, - RoutedByAddr, - Invalid - }; - - FaultBase(Params& params, FaultInjectorBase* injector); - - FaultBase() = default; - ~FaultBase() {} - - virtual void faultLogic(Event*& ev) {} - - SST::Output*& getSimulationOutput(); - - SST::Output*& getSimulationDebug(); - - installDirection setInstallDirection(std::string param); - - SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); - - dataVec& getMemEventPayload(Event*& ev); - - void setMemEventPayload(Event*& ev, dataVec newPayload); - - memEventType getMemEventCommandType(Event*& ev); - - bool doInjection(); - - protected: - - FaultInjectorBase* injector_ = nullptr; - - bool valid_installation_[2] = {false, false}; - std::default_random_engine generator_; - std::uniform_real_distribution distribution_; - - void toggleReceiveValid() { - valid_installation_[0] = true; - } - - void toggleSendValid() { - valid_installation_[1] = true; - } - - void toggleSendReceiveValid() { - valid_installation_[0] = true; - valid_installation_[1] = true; - } - // TODO: Figure out how to properly set up serialization for this - // void serialize_order(SST::Core::Serialization::serializer& ser) - // { - // SST::PortModule::serialize_order(ser); - // // serialize parameters like `SST_SER() - // } - // ImplementSerializable(SST::Carcosa::FaultBase) - }; SST_ELI_REGISTER_PORTMODULE( FaultInjectorBase, "carcosa", "faultInjectorBase", SST_ELI_ELEMENT_VERSION(0, 1, 0), - "Barebones PortModule used to connect fault injection logic to components" + "Base PortModule class used to connect fault injection logic to components" ) SST_ELI_DOCUMENT_PARAMS( @@ -139,7 +68,9 @@ class FaultInjectorBase : public SST::PortModule FaultInjectorBase() = default; ~FaultInjectorBase() { - delete fault; + if (fault) { + delete fault; + } } void virtual eventSent(uintptr_t key, Event*& ev) override; @@ -178,16 +109,50 @@ class FaultInjectorBase : public SST::PortModule return installDirection_; } -protected: - FaultBase* fault; + enum memEventType { + DataRequest = 0, + Response, + Writeback, + RoutedByAddr, + Invalid + }; - bool* cancel_; + SST::Output* getOutput() { + return out_; + } - installDirection installDirection_ = installDirection::Receive; - double injectionProbability_ = 0.5; + SST::Output* getDebug() { + return dbg_; + } +protected: SST::Output* out_; SST::Output* dbg_; + FaultBase* fault = nullptr; + bool* cancel_; + installDirection installDirection_ = installDirection::Receive; + double injectionProbability_ = 0.5; + std::default_random_engine generator_; + std::uniform_real_distribution distribution_; + bool valid_installation_[2] = {false, false}; + + void toggleReceiveValid() { + valid_installation_[0] = true; + } + + void toggleSendValid() { + valid_installation_[1] = true; + } + + void toggleSendReceiveValid() { + valid_installation_[0] = true; + valid_installation_[1] = true; + } + + installDirection setInstallDirection(std::string param); + bool doInjection(); + memEventType getMemEventCommandType(Event*& ev); + void serialize_order(SST::Core::Serialization::serializer& ser) override { diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index b591f9ebdd..8f0ea5c489 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H #define SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/faultlogic/faultBase.h" #include #include #include diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc new file mode 100644 index 0000000000..245a6a29fb --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/faultBase.cc @@ -0,0 +1,59 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/faultlogic/faultBase.h" + +using namespace SST::Carcosa; + +FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : injector_(injector) { + // +} + +bool FaultBase::faultLogic(Event*& ev) { + // +} + +SST::MemHierarchy::MemEvent* FaultBase::convertMemEvent(Event*& ev) { + SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); + + if (mem_ev == nullptr) { + getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); + } + +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); +#endif + return mem_ev; +} + +dataVec& FaultBase::getMemEventPayload(Event*& ev) { + return convertMemEvent(ev)->getPayload(); +} + +void FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); + for (int i: getMemEventPayload(ev)) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + } + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); +#endif + convertMemEvent(ev)->setPayload(newPayload); + +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); + for (int i: getMemEventPayload(ev)) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + } + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); +#endif +} + diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h new file mode 100644 index 0000000000..ed14635c83 --- /dev/null +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -0,0 +1,51 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_FAULTBASE_H +#define SST_ELEMENTS_CARCOSA_FAULTBASE_H + +#include "sst/elements/carcosa/faultInjectorBase.h" +#include +#include +#include + +namespace SST::Carcosa { + +typedef std::vector dataVec; + +class FaultBase { +public: + FaultBase(Params& params, FaultInjectorBase* injector); + + FaultBase() = default; + ~FaultBase() {} + + virtual bool faultLogic(Event*& ev); + + SST::Output*& getSimulationOutput() { + return injector_->getOutput(); + } + + SST::Output*& getSimulationDebug() { + return injector_->getDebug(); + } + + SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); + + dataVec& getMemEventPayload(Event*& ev); + + void setMemEventPayload(Event*& ev, dataVec newPayload); +protected: + FaultInjectorBase* injector_ = nullptr; +}; // class FaultBase +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.h b/src/sst/elements/carcosa/faultlogic/randomDropFault.h index 2758d2a748..6ed8059e31 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_RANDOMDROPFAULT_H #define SST_ELEMENTS_CARCOSA_RANDOMDROPFAULT_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/faultlogic/faultBase.h" #include #include #include diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index e4d69c1a17..0ab7da1426 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -21,6 +21,7 @@ RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : void RandomFlipFault::faultLogic(Event*& ev) { // check if this is the proper event type and get payload if it is dataVec payload = getMemEventPayload(ev); + //getSimulationOutput()->output(CALL_INFO_LONG, 1, 0, "Payload size: %d\n", payload.size()); // determine if injection occurs if (this->doInjection()) { std::pair lucky_number = pickByteAndBit(); diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h index b654228b4a..1a1c3c546a 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULT_H #define SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULT_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/faultlogic/faultBase.h" namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index f4fd12ec22..3d396285ab 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -129,11 +129,11 @@ std::vector StuckAtFault::convertString(std::vector> addr; + stream >> std::hex >> addr; if (stream.peek() == ',') { stream.ignore(); } - stream >> byte; + stream >> std::dec >> byte; if (stream.peek() == ',') { stream.ignore(); } diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index 9b54dfab12..e7a20682b4 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULT_H #define SST_ELEMENTS_CARCOSA_STUCKATFAULT_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/faultlogic/faultBase.h" #include #include #include diff --git a/src/sst/elements/carcosa/faultlogic/randomDrop.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc similarity index 100% rename from src/sst/elements/carcosa/faultlogic/randomDrop.h rename to src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc diff --git a/src/sst/elements/carcosa/faultlogic/randomFlip.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h similarity index 100% rename from src/sst/elements/carcosa/faultlogic/randomFlip.h rename to src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc new file mode 100644 index 0000000000..9d9fa8e540 --- /dev/null +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc @@ -0,0 +1,33 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/injectors/stuckAtFaultInjector.h" +#include "sst/elements/carcosa/faultlogic/stuckAtFault.h" + +using namespace SST::Carcosa; + +StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params) { + // create fault + fault = new StuckAtFault(params, this); + // toggle valid installation direction + toggleSendReceiveValid(); + + std::string install_dir = params.find("installDirection", "Receive"); + installDirection_ = setInstallDirection(install_dir); + + if (installDirection_ == installDirection::Invalid) { + out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); + } + +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); +#endif +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h new file mode 100644 index 0000000000..eeccea51f9 --- /dev/null +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -0,0 +1,45 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULTINJECTOR_H +#define SST_ELEMENTS_CARCOSA_STUCKATFAULTINJECTOR_H + +#include "sst/elements/carcosa/faultInjectorBase.h" +#include + +namepace SST::Carcosa { + +class StuckAtFaultInjector : public FaultInjectorBase { +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "StuckAtFaultInjector", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "PortModule class used to simulate a stuck bit within a given component" + ) + + SST_ELI_DOCUMENT_PARAMS( + {"masks", "String array formatted as [\"addr0, byte0, zeroMask0, oneMask0\",...,\"addrN, byteN, zeroMaskN, oneMaskN\"]." \ + "Addresses are expected to be in hexadecimal, and masks are 8 bit strings."}, + ) + + StuckAtFaultInjector(Params& params); + + StuckAtFaultInjector() = default; + ~StuckAtFaultInjector() {} +protected: + // +}; // class StuckAtFaultInjector + +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index 14512b1cd6..b2d7d7baba 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -496,9 +496,10 @@ def addParamsPrefix(prefix,params): # node memory controller memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) -memctrl.addPortModule("highlink", "carcosa.faultInjectorBase", { +memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { "intallDirection": "Receive", - "injectionProbability": 1, + #"injectionProbability": 0.25, + "masks": ["DEADBEEF, 3, 10101010, 01010101"], "debug" : 1, "debug_level": 2 }) From 1c89ea4c7a038767d23ff604e51fee60be20126c Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 3 Oct 2025 16:45:56 -0400 Subject: [PATCH 25/45] large number of compile errors fixed--many more to fix on monday :) --- src/sst/elements/carcosa/faultInjectorBase.cc | 10 +++++----- src/sst/elements/carcosa/faultlogic/corruptMemFault.cc | 2 +- src/sst/elements/carcosa/faultlogic/corruptMemFault.h | 4 ++-- src/sst/elements/carcosa/faultlogic/faultBase.cc | 2 +- src/sst/elements/carcosa/faultlogic/faultBase.h | 4 ++-- src/sst/elements/carcosa/faultlogic/randomDropFault.cc | 2 +- src/sst/elements/carcosa/faultlogic/randomDropFault.h | 4 ++-- src/sst/elements/carcosa/faultlogic/randomFlipFault.cc | 2 +- src/sst/elements/carcosa/faultlogic/randomFlipFault.h | 4 ++-- src/sst/elements/carcosa/faultlogic/stuckAtFault.cc | 2 +- src/sst/elements/carcosa/faultlogic/stuckAtFault.h | 4 ++-- 11 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 99df6bca00..204cc242b3 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -109,14 +109,14 @@ void FaultInjectorBase::setInstallDirection(std::string param) { FaultInjectorBase::memEventType FaultInjectorBase::getMemEventCommandType(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); if (mem_ev->isDataRequest()) { - return FaultBase::memEventType::DataRequest; + return FaultInjectorBase::memEventType::DataRequest; } else if (mem_ev->isResponse()) { - return FaultBase::memEventType::Response; + return FaultInjectorBase::memEventType::Response; } else if (mem_ev->isWriteback()) { - return FaultBase::memEventType::Writeback; + return FaultInjectorBase::memEventType::Writeback; } else if (mem_ev->isRoutedByAddress()) { - return FaultBase::memEventType::RoutedByAddr; + return FaultInjectorBase::memEventType::RoutedByAddr; } else { - return FaultBase::memEventType::Invalid; + return FaultInjectorBase::memEventType::Invalid; } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index ed1a2c44ee..63c1535988 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -43,7 +43,7 @@ CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : distribution = std::uniform_int_distribution(0,255); } -void CorruptMemFault::faultLogic(Event*& ev) { +bool CorruptMemFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); Addr ev_addr = mem_ev->getAddr(); diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index 8f0ea5c489..8b7ef1101c 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -31,7 +31,7 @@ typedef SST::MemHierarchy::Addr Addr; * module's parameters, will have their payloads randomly altered * to simulate corruption in the affected region of memory. */ -class CorruptMemFault : public FaultInjectorBase::FaultBase +class CorruptMemFault : public FaultBase { public: @@ -46,7 +46,7 @@ class CorruptMemFault : public FaultInjectorBase::FaultBase * 3. Corrupt event payload if necessary * 4. Replace payload */ - void faultLogic(Event*& ev) override; + bool faultLogic(Event*& ev) override; protected: std::vector> corruptionRegions; diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc index 245a6a29fb..61873b5a11 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.cc +++ b/src/sst/elements/carcosa/faultlogic/faultBase.cc @@ -18,7 +18,7 @@ FaultBase::FaultBase(Params& params, FaultInjectorBase* injector) : injector_(in } bool FaultBase::faultLogic(Event*& ev) { - // + return true; } SST::MemHierarchy::MemEvent* FaultBase::convertMemEvent(Event*& ev) { diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index ed14635c83..15c1b17b66 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -30,11 +30,11 @@ class FaultBase { virtual bool faultLogic(Event*& ev); - SST::Output*& getSimulationOutput() { + SST::Output* getSimulationOutput() { return injector_->getOutput(); } - SST::Output*& getSimulationDebug() { + SST::Output* getSimulationDebug() { return injector_->getDebug(); } diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc index 459204014f..aa9e1c00ea 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -17,7 +17,7 @@ RandomDropFault::RandomDropFault(Params& params, FaultInjectorBase* injector) : toggleReceiveValid(); } -void RandomDropFault::faultLogic(Event*& ev) { +bool RandomDropFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); if (this->doInjection()) { diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.h b/src/sst/elements/carcosa/faultlogic/randomDropFault.h index 6ed8059e31..12c3c42079 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.h @@ -21,14 +21,14 @@ namespace SST::Carcosa { typedef std::vector dataVec; -class RandomDropFault : public FaultInjectorBase::FaultBase { +class RandomDropFault : public FaultBase { public: RandomDropFault(Params& params, FaultInjectorBase* injector); RandomDropFault() = default; ~RandomDropFault() {} - void faultLogic(Event*& ev) override; + bool faultLogic(Event*& ev) override; }; // RandomDropFault } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index 0ab7da1426..3d1814ce02 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -18,7 +18,7 @@ RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : toggleSendReceiveValid(); } -void RandomFlipFault::faultLogic(Event*& ev) { +bool RandomFlipFault::faultLogic(Event*& ev) { // check if this is the proper event type and get payload if it is dataVec payload = getMemEventPayload(ev); //getSimulationOutput()->output(CALL_INFO_LONG, 1, 0, "Payload size: %d\n", payload.size()); diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h index 1a1c3c546a..3498f72f0c 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -16,14 +16,14 @@ namespace SST::Carcosa { -class RandomFlipFault : public FaultInjectorBase::FaultBase { +class RandomFlipFault : public FaultBase { public: RandomFlipFault(Params& params, FaultInjectorBase* injector); RandomFlipFault() = default; ~RandomFlipFault() {} - void faultLogic(Event*& ev) override; + bool faultLogic(Event*& ev) override; protected: std::default_random_engine int_generator; std::uniform_int_distribution int_distribution; diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 3d396285ab..c7d3923c14 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -68,7 +68,7 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB } } -void StuckAtFault::faultLogic(SST::Event*& ev) { +bool StuckAtFault::faultLogic(SST::Event*& ev) { // Convert to memEvent SST::MemHierarchy::MemEvent* mem_ev = this->convertMemEvent(ev); diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index e7a20682b4..08e8b73a32 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -35,7 +35,7 @@ typedef SST::MemHierarchy::Addr Addr; * directly into the L1 or the core (bypassing L2 ops in simulation), it may be * advisable to also place these port modules on the ports used to forward these events. */ -class StuckAtFault : public FaultInjectorBase::FaultBase +class StuckAtFault : public FaultBase { public: @@ -50,7 +50,7 @@ class StuckAtFault : public FaultInjectorBase::FaultBase * - If payload value does not match mapped value, add bit to flip mask * - Once all stored bit values have been compared, use flip mask to modify address data */ - void faultLogic(Event*& ev) override; + bool faultLogic(Event*& ev) override; protected: // map of addr->{byte, mask} for saving stuck bit values From 84acc3990ad4931c68e06d1d660020af17e26e54 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 6 Oct 2025 16:47:25 -0400 Subject: [PATCH 26/45] most compilation issues fixed need to do 2 things: 1. change fault** into vec[fault*] and rewrite affected code 2. figure out better way to pass valid installation directions to injectors --- src/sst/elements/carcosa/Makefile.am | 54 +++++---- .../carcosa/faultlogic/corruptMemFault.cc | 1 - .../elements/carcosa/faultlogic/faultBase.cc | 12 +- .../elements/carcosa/faultlogic/faultBase.h | 10 +- .../carcosa/faultlogic/randomDropFault.cc | 14 +-- .../carcosa/faultlogic/randomFlipFault.cc | 14 +-- .../carcosa/faultlogic/stuckAtFault.cc | 2 - .../injectors/corruptMemFaultInjector.cc | 21 ++++ .../injectors/corruptMemFaultInjector.h | 43 +++++++ .../carcosa/injectors/doubleFaultInjector.cc | 110 ++++++++++++++++++ .../carcosa/injectors/doubleFaultInjector.h | 50 ++++++++ .../injectors/randomDropFaultInjector.cc | 21 ++++ .../injectors/randomDropFaultInjector.h | 42 +++++++ .../injectors/randomFlipFaultInjector.cc | 21 ++++ .../injectors/randomFlipFaultInjector.h | 42 +++++++ .../carcosa/injectors/stuckAtFaultInjector.cc | 18 +-- .../carcosa/injectors/stuckAtFaultInjector.h | 2 +- 17 files changed, 412 insertions(+), 65 deletions(-) create mode 100644 src/sst/elements/carcosa/injectors/doubleFaultInjector.cc create mode 100644 src/sst/elements/carcosa/injectors/doubleFaultInjector.h diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 9c5bcb198f..8b97ad8137 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -8,33 +8,45 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la -libcarcosa_la_SOURCES = \ - faultInjectorBase.cc \ - faultInjectorBase.h \ - injectors/stuckAtFaultInjector.cc \ - injectors/stuckAtFaultInjector.h \ - faultlogic/faultBase.cc \ - faultlogic/faultBase.h \ - faultlogic/stuckAtFault.cc \ - faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.cc \ - faultlogic/corruptMemFault.h \ - faultlogic/randomDropFault.cc \ - faultlogic/randomDropFault.h \ - faultlogic/randomFlipFault.cc \ +libcarcosa_la_SOURCES = \ + faultInjectorBase.cc \ + faultInjectorBase.h \ + injectors/stuckAtFaultInjector.cc \ + injectors/stuckAtFaultInjector.h \ + injectors/corruptMemFaultInjector.cc \ + injectors/corruptMemFaultInjector.h \ + injectors/randomDropFaultInjector.cc \ + injectors/randomDropFaultInjector.h \ + injectors/randomFlipFaultInjector.cc \ + injectors/randomFlipFaultInjector.h \ + injectors/doubleFaultInjector.cc \ + injectors/doubleFaultInjector.h \ + faultlogic/faultBase.cc \ + faultlogic/faultBase.h \ + faultlogic/stuckAtFault.cc \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemFault.cc \ + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.cc \ + faultlogic/randomDropFault.h \ + faultlogic/randomFlipFault.cc \ faultlogic/randomFlipFault.h EXTRA_DIST = \ dummyTest.py sstdir = $(includedir)/sst/elements/carcosa -nobase_sst_HEADERS = \ - faultInjectorBase.h \ - injectors/stuckAtFaultInjector.h \ - faultlogic/faultBase.h \ - faultlogic/stuckAtFault.h \ - faultlogic/corruptMemFault.h \ - faultlogic/randomDropFault.h \ +nobase_sst_HEADERS = \ + faultInjectorBase.h \ + injectors/stuckAtFaultInjector.h \ + injectors/corruptMemFaultInjector.h \ + injectors/randomDropFaultInjector.h \ + injectors/randomFlipFaultInjector.h \ + injectors/doubleFaultInjector.h \ + faultlogic/faultBase.h \ + faultlogic/stuckAtFault.h \ + faultlogic/corruptMemFault.h \ + faultlogic/randomDropFault.h \ faultlogic/randomFlipFault.h libcarcosa_la_LDFLAGS = -module -avoid-version diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index 63c1535988..bde17e3112 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -14,7 +14,6 @@ using namespace SST::Carcosa; CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { - toggleSendReceiveValid(); #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault type: Corrupt Memory Region\n"); #endif diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc index 61873b5a11..1973544e57 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.cc +++ b/src/sst/elements/carcosa/faultlogic/faultBase.cc @@ -21,15 +21,23 @@ bool FaultBase::faultLogic(Event*& ev) { return true; } +SST::Output* FaultBase::getSimulationOutput() { + return injector_->getOutput(); +} + +SST::Output* FaultBase::getSimulationDebug() { + return injector_->getDebug(); +} + SST::MemHierarchy::MemEvent* FaultBase::convertMemEvent(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = dynamic_cast(ev); if (mem_ev == nullptr) { - getSimulationOutput().fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Attempting to inject mem fault on a non-MemEvent type.\n"); } #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); #endif return mem_ev; } diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index 15c1b17b66..d9a761701d 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -21,6 +21,8 @@ namespace SST::Carcosa { typedef std::vector dataVec; +class FaultInjectorBase; + class FaultBase { public: FaultBase(Params& params, FaultInjectorBase* injector); @@ -30,13 +32,9 @@ class FaultBase { virtual bool faultLogic(Event*& ev); - SST::Output* getSimulationOutput() { - return injector_->getOutput(); - } + SST::Output* getSimulationOutput(); - SST::Output* getSimulationDebug() { - return injector_->getDebug(); - } + SST::Output* getSimulationDebug(); SST::MemHierarchy::MemEvent* convertMemEvent(Event*& ev); diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc index aa9e1c00ea..db9981b626 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -14,19 +14,17 @@ using namespace SST::Carcosa; RandomDropFault::RandomDropFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { - toggleReceiveValid(); + // } bool RandomDropFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); - if (this->doInjection()) { - delete mem_ev; - if (injector_->getInstallDirection() == installDirection::Receive) { - injector_->cancelDelivery(); - } + delete mem_ev; + if (injector_->getInstallDirection() == installDirection::Receive) { + injector_->cancelDelivery(); + } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Event dropped.\n"); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Event dropped.\n"); #endif - } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index 3d1814ce02..11c35af241 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -15,21 +15,17 @@ using namespace SST::Carcosa; RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { this->int_distribution = uniform_int_distribution(0,8); - toggleSendReceiveValid(); } bool RandomFlipFault::faultLogic(Event*& ev) { // check if this is the proper event type and get payload if it is dataVec payload = getMemEventPayload(ev); //getSimulationOutput()->output(CALL_INFO_LONG, 1, 0, "Payload size: %d\n", payload.size()); - // determine if injection occurs - if (this->doInjection()) { - std::pair lucky_number = pickByteAndBit(); - uint8_t byte = payload[lucky_number.first]; - uint8_t mask = static_cast(1) << (lucky_number.second); - payload[lucky_number.first] = byte ^ mask; - setMemEventPayload(ev, payload); - } + std::pair lucky_number = pickByteAndBit(); + uint8_t byte = payload[lucky_number.first]; + uint8_t mask = static_cast(1) << (lucky_number.second); + payload[lucky_number.first] = byte ^ mask; + setMemEventPayload(ev, payload); } inline std::pair RandomFlipFault::pickByteAndBit() { diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index c7d3923c14..1d6d52ff19 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -20,8 +20,6 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault Type: Stuck-At Fault\n"); #endif - // set valid install direction - toggleSendReceiveValid(); // read in masks // parameter format: {masks: ["addr, byte, zeroMask, oneMask"]} std::vector paramVecStr; diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc index e69de29bb2..431602f4d2 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc @@ -0,0 +1,21 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/injectors/corruptMemFaultInjector.h" +#include "sst/elements/carcosa/faultlogic/corruptMemFault.h" + +using namespace SST::Carcosa; + +CorruptMemFaultInjector::CorruptMemFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { + // create fault + fault = new FaultBase*; + *fault = new CorruptMemFault(params, this); +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index e69de29bb2..855e4258f6 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -0,0 +1,43 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULTINJECTOR_H +#define SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULTINJECTOR_H + +#include "sst/elements/carcosa/faultInjectorBase.h" + +namespace SST::Carcosa { + +class CorruptMemFaultInjector : public FaultInjectorBase { +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "CorruptMemFaultInjector", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "PortModule class used to simulate a whole memory region being corrupted" + ) + + SST_ELI_DOCUMENT_PARAMS( + {"regions", "Formatted as an array of strings: [\"start_addr0, end_addr0\", \"start_addr1, end_addr1\",...,\"start_addrN, end_addrN\"]. Addresses expected in hexadecimal."} + ) + + CorruptMemFaultInjector(Params& params); + + CorruptMemFaultInjector() = default; + ~CorruptMemFaultInjector() {} +protected: + // +}; // class CorruptMemFaultInjector + +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc new file mode 100644 index 0000000000..e32cbb4d32 --- /dev/null +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc @@ -0,0 +1,110 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/injectors/doubleFaultInjector.h" +#include "sst/elements/carcosa/faultlogic/randomFlipFault.h" +#include "sst/elements/carcosa/faultlogic/randomDropFault.h" + +using namespace SST::Carcosa; + +DoubleFaultInjector::DoubleFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { + // create fault + fault = new FaultBase*[2]; + fault[0] = new RandomDropFault(params, this); + fault[1] = new RandomFlipFault(params, this); + + // read flipvsdrop param + flipVsDropProb_ = params.find("flipVsDropProb", 0.5); + distribution_ = std::uniform_real_distribution(0,1); +} + +DoubleFaultInjector::~DoubleFaultInjector() { + if (fault) { + if (fault[0]) { + delete fault[0]; + } + if (fault[1]) { + delete fault[1]; + } + delete fault; + } +} + +void DoubleFaultInjector::eventSent(uintptr_t key, Event*& ev) { + if (doInjection()){ +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); +#endif + if (!fault) { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } + FaultBase* triggered_fault = nullptr; + if (distribution_(generator_) <= flipVsDropProb_) { + // do flip +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); +#endif + triggered_fault = fault[1]; + } else { + // do drop +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); +#endif + triggered_fault = fault[0]; + } + if (triggered_fault) { + triggered_fault->faultLogic(ev); + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } + } +#ifdef __SST_DEBUG_OUTPUT__ + else { + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); + } +#endif +} + +void DoubleFaultInjector::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) { + // do not cancel delivery by default + cancel = false; + cancel_ = &cancel; + + if (doInjection()){ +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); +#endif + FaultBase* triggered_fault = nullptr; + if (distribution_(generator_) <= flipVsDropProb_) { + // do flip +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); +#endif + triggered_fault = fault[1]; + } else { + // do drop +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); +#endif + triggered_fault = fault[0]; + } + if (triggered_fault) { + triggered_fault->faultLogic(ev); + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } + } +#ifdef __SST_DEBUG_OUTPUT__ + else { + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); + } +#endif +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h new file mode 100644 index 0000000000..f3beeb1cc7 --- /dev/null +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -0,0 +1,50 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_DOUBLEFAULTINJECTOR_H +#define SST_ELEMENTS_CARCOSA_DOUBLEFAULTINJECTOR_H + +#include "sst/elements/carcosa/faultInjectorBase.h" +#include + +namespace SST::Carcosa { + +class DoubleFaultInjector : public FaultInjectorBase { +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "DoubleFaultInjector", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "PortModule class used to simulate a data transfer lost at random OR a random bit flip in transit" + ) + + SST_ELI_DOCUMENT_PARAMS( + {"flipVsDropProb", "The probability that a flip will be chosen over a drop when a fault is injected"} + ) + + DoubleFaultInjector(Params& params); + + DoubleFaultInjector() = default; + ~DoubleFaultInjector(); + + void virtual eventSent(uintptr_t key, Event*& ev) override; + void virtual interceptHandler(uintptr_t key, Event*& ev, bool& cancel) override; +protected: + double flipVsDropProb_; + + std::default_random_engine generator_; + std::uniform_real_distribution distribution_; +}; // class DoubleFaultInjector + +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index e69de29bb2..08e7d439a5 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -0,0 +1,21 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/injectors/randomDropFaultInjector.h" +#include "sst/elements/carcosa/faultlogic/randomDropFault.h" + +using namespace SST::Carcosa; + +RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjectorBase(params, RECEIVE_VALID) { + // create fault + fault = new FaultBase*; + *fault = new RandomDropFault(params, this); +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index e69de29bb2..85a7ca67b7 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -0,0 +1,42 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_RANDOMDROPFAULTINJECTOR_H +#define SST_ELEMENTS_CARCOSA_RANDOMDROPFAULTINJECTOR_H + +#include "sst/elements/carcosa/faultInjectorBase.h" + +namespace SST::Carcosa { + +class RandomDropFaultInjector : public FaultInjectorBase { +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "RandomFlipFaultInjector", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "PortModule class used to simulate a data transfer lost at random" + ) + + SST_ELI_DOCUMENT_PARAMS( + ) + + RandomDropFaultInjector(Params& params); + + RandomDropFaultInjector() = default; + ~RandomDropFaultInjector() {} +protected: + // +}; // class RandomDropFaultInjector + +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc index e69de29bb2..77e9909266 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc @@ -0,0 +1,21 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#include "sst/elements/carcosa/injectors/randomFlipFaultInjector.h" +#include "sst/elements/carcosa/faultlogic/randomFlipFault.h" + +using namespace SST::Carcosa; + +RandomFlipFaultInjector::RandomFlipFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { + // create fault + fault = new FaultBase*; + *fault = new RandomFlipFault(params, this); +} \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index e69de29bb2..e1f3a5776f 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -0,0 +1,42 @@ +// Copyright 2009-2025 NTESS. Under the terms +// of Contract DE-NA0003525 with NTESS, the U.S. +// Government retains certain rights in this software. +// +// Copyright (c) 2009-2025, NTESS +// All rights reserved. +// +// This file is part of the SST software package. For license +// information, see the LICENSE file in the top level directory of the +// distribution. + +#ifndef SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULTINJECTOR_H +#define SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULTINJECTOR_H + +#include "sst/elements/carcosa/faultInjectorBase.h" + +namespace SST::Carcosa { + +class RandomFlipFaultInjector : public FaultInjectorBase { +public: + SST_ELI_REGISTER_PORTMODULE( + FaultInjectorBase, + "carcosa", + "RandomFlipFaultInjector", + SST_ELI_ELEMENT_VERSION(0, 1, 0), + "PortModule class used to simulate a random bit flip when transferring data" + ) + + SST_ELI_DOCUMENT_PARAMS( + ) + + RandomFlipFaultInjector(Params& params); + + RandomFlipFaultInjector() = default; + ~RandomFlipFaultInjector() {} +protected: + // +}; // class RandomFlipFaultInjector + +} // namespace SST::Carcosa + +#endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc index 9d9fa8e540..4f2fa39c84 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc @@ -14,20 +14,8 @@ using namespace SST::Carcosa; -StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params) { +StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { // create fault - fault = new StuckAtFault(params, this); - // toggle valid installation direction - toggleSendReceiveValid(); - - std::string install_dir = params.find("installDirection", "Receive"); - installDirection_ = setInstallDirection(install_dir); - - if (installDirection_ == installDirection::Invalid) { - out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); - } - -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); -#endif + fault = new FaultBase*; + *fault = new StuckAtFault(params, this); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index eeccea51f9..9fafaefce0 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -15,7 +15,7 @@ #include "sst/elements/carcosa/faultInjectorBase.h" #include -namepace SST::Carcosa { +namespace SST::Carcosa { class StuckAtFaultInjector : public FaultInjectorBase { public: From 55a6c061153171f88b948b32a8a6c292168a0c90 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Tue, 7 Oct 2025 17:44:36 -0400 Subject: [PATCH 27/45] refactor nearly complete must implement serialization for FaultBase class after this is done, I can finally go in and fix the faulty logic in the StuckAtFault and CorruptMemRegion classes --- src/sst/elements/carcosa/faultInjectorBase.cc | 88 ++++++++++------- src/sst/elements/carcosa/faultInjectorBase.h | 49 +++++----- .../elements/carcosa/faultlogic/faultBase.h | 2 +- .../carcosa/faultlogic/stuckAtFault.cc | 5 + .../injectors/corruptMemFaultInjector.cc | 9 +- .../injectors/corruptMemFaultInjector.h | 13 ++- .../carcosa/injectors/doubleFaultInjector.cc | 98 +++++-------------- .../carcosa/injectors/doubleFaultInjector.h | 24 +++-- .../injectors/randomDropFaultInjector.cc | 9 +- .../injectors/randomDropFaultInjector.h | 13 ++- .../injectors/randomFlipFaultInjector.cc | 9 +- .../injectors/randomFlipFaultInjector.h | 13 ++- .../carcosa/injectors/stuckAtFaultInjector.cc | 9 +- .../carcosa/injectors/stuckAtFaultInjector.h | 13 ++- 14 files changed, 181 insertions(+), 173 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 204cc242b3..ddbdcedfc4 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -35,8 +35,30 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - // init randomizer - distribution_ = std::uniform_real_distribution(0,1); + + valid_installation_ = getValidInstallation(); + std::string install_dir = params.find("installDirection", "Receive"); + installDirection_ = setInstallDirection(install_dir); + + if (installDirection_ == installDirection::Invalid) { + out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); + } + +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); +#endif +} + +/** + * Default behavior is to delete all fault objects in the order they were + * added to the vector + */ +FaultInjectorBase::~FaultInjectorBase() { + for (int i = 0; i < fault.size(); i++) { + if (fault[i]) { + delete fault[i]; + } + } } void @@ -44,20 +66,15 @@ FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { if (doInjection()){ #ifdef __SST_DEBUG_OUTPUT__ - dbg_->(CALL_INFO_LONG, 1, 0, "Injection triggered.\n") + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); #endif - if (fault) { - fault->faultLogic(ev); - } else { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); - } + this->executeFaults(ev); } #ifdef __SST_DEBUG_OUTPUT__ else { - dbg_->(CALL_INFO_LONG, 1, 0, "Injection skipped.\n") + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); } #endif - } void @@ -69,54 +86,51 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) if (doInjection()){ #ifdef __SST_DEBUG_OUTPUT__ - dbg_->(CALL_INFO_LONG, 1, 0, "Injection triggered.\n") + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); #endif - if (fault) { - fault->faultLogic(ev); - } else { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); - } + this->executeFaults(ev); } #ifdef __SST_DEBUG_OUTPUT__ else { - dbg_->(CALL_INFO_LONG, 1, 0, "Injection skipped.\n") + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); } #endif } bool FaultInjectorBase::doInjection() { - double rand_val = distribution_(generator_); - return rand_val <= injector_->getInjectionProb(); + double rand_val = base_rng_.nextUniform(); + return rand_val <= getInjectionProb(); } -void FaultInjectorBase::setInstallDirection(std::string param) { +installDirection FaultInjectorBase::setInstallDirection(std::string param) { if ( param == "Receive" ) { if (valid_installation_[0]) { - installDirection_= installDirection::Receive; + return installDirection::Receive; } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); + out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Receive events.\n"); } } else if ( param == "Send" ) { if (valid_installation_[1]) { - installDirection_ = return installDirection::Send; + return installDirection::Send; } else { - injector_->out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); + out_->fatal(CALL_INFO_LONG, 1, 0, "This PortModule Fault Injector cannot intercept Send events.\n"); } } - installDirection_= installDirection::Invalid; + return installDirection::Invalid; } -FaultInjectorBase::memEventType FaultInjectorBase::getMemEventCommandType(Event*& ev) { - SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); - if (mem_ev->isDataRequest()) { - return FaultInjectorBase::memEventType::DataRequest; - } else if (mem_ev->isResponse()) { - return FaultInjectorBase::memEventType::Response; - } else if (mem_ev->isWriteback()) { - return FaultInjectorBase::memEventType::Writeback; - } else if (mem_ev->isRoutedByAddress()) { - return FaultInjectorBase::memEventType::RoutedByAddr; - } else { - return FaultInjectorBase::memEventType::Invalid; +/** + * Default behavior is to execute faults in the order they were + * added to the vector + */ +void FaultInjectorBase::executeFaults(Event*& ev) { + bool success = false; + for (int i = 0; i < fault.size(); i++) { + if (fault[i]) { + success = fault[i]->faultLogic(ev); + } + } + if (!success) { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object, or no fault successfully executed.\n"); } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index b948d34f2e..c061feb65c 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -18,15 +18,21 @@ #include "sst/elements/memHierarchy/memEvent.h" #include "sst/elements/carcosa/faultlogic/faultBase.h" #include +#include "sst/core/rng/mersenne.h" #include #include #include +#include namespace SST::Carcosa { typedef std::vector dataVec; class FaultBase; +#define SEND_RECEIVE_VALID {{true, true}} +#define RECEIVE_VALID {{true, false}} +#define SEND_VALID {{false, true}} + /********** FaultInjectorBase **********/ enum installDirection { @@ -67,14 +73,10 @@ class FaultInjectorBase : public SST::PortModule FaultInjectorBase(Params& params); FaultInjectorBase() = default; - ~FaultInjectorBase() { - if (fault) { - delete fault; - } - } + ~FaultInjectorBase(); void virtual eventSent(uintptr_t key, Event*& ev) override; - void virtual interceptHandler(uintptr_t key, Event*& data, bool& cancel) override; + void virtual interceptHandler(uintptr_t key, Event*& ev, bool& cancel) override; bool installOnReceive() override { @@ -105,6 +107,8 @@ class FaultInjectorBase : public SST::PortModule *cancel_ = true; } + installDirection setInstallDirection(std::string param); + installDirection getInstallDirection() { return installDirection_; } @@ -128,41 +132,32 @@ class FaultInjectorBase : public SST::PortModule protected: SST::Output* out_; SST::Output* dbg_; - FaultBase* fault = nullptr; + std::vector fault; bool* cancel_; installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; - std::default_random_engine generator_; - std::uniform_real_distribution distribution_; - bool valid_installation_[2] = {false, false}; - - void toggleReceiveValid() { - valid_installation_[0] = true; - } - - void toggleSendValid() { - valid_installation_[1] = true; - } + SST::RNG::MersenneRNG base_rng_; + std::array valid_installation_ = {{false, false}}; - void toggleSendReceiveValid() { - valid_installation_[0] = true; - valid_installation_[1] = true; - } - - installDirection setInstallDirection(std::string param); bool doInjection(); - memEventType getMemEventCommandType(Event*& ev); + virtual void executeFaults(Event*& ev); + virtual std::array getValidInstallation() = 0; void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` - // SST_SER(fault); + SST_SER(out_); + SST_SER(dbg_); + SST_SER(fault); + SST_SER(cancel_); SST_SER(installDirection_); SST_SER(injectionProbability_); + SST_SER(base_rng_); + SST_SER(valid_installation_); } - ImplementSerializable(SST::Carcosa::FaultInjectorBase) + ImplementVirtualSerializable(SST::Carcosa::FaultInjectorBase) // Statistics // Statistic stat_eventsArrived; diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index d9a761701d..68628ff947 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -22,7 +22,7 @@ namespace SST::Carcosa { typedef std::vector dataVec; class FaultInjectorBase; - +// TODO: IMPLEMENT SERIALIZATION FOR THIS CLASS class FaultBase { public: FaultBase(Params& params, FaultInjectorBase* injector); diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 1d6d52ff19..6205292ff8 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -79,6 +79,11 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); + // payloads are given a size in the memEvent and it's usually cache line size + // addr is whatever the core requested + // base addr is first addr in byte array + // vanadis riscv is LITTLE ENDIAN so byte order is reversed (byte 0 at Addr A is lowest byte, but Addr0 is still base addr, Addr1 = Addr0+8) + // confirm that little endian is this trolling uint8_t mask = 0b00000000; #ifdef __SST_DEBUG_OUTPUT__ diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc index 431602f4d2..7cbea20325 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc @@ -14,8 +14,11 @@ using namespace SST::Carcosa; -CorruptMemFaultInjector::CorruptMemFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { +CorruptMemFaultInjector::CorruptMemFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault - fault = new FaultBase*; - *fault = new CorruptMemFault(params, this); + fault.push_back(new CorruptMemFault(params, this)); +} + +std::array CorruptMemFaultInjector::getValidInstallation() { + return SEND_RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index 855e4258f6..b38221f9b1 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -19,9 +19,9 @@ namespace SST::Carcosa { class CorruptMemFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - FaultInjectorBase, + CorruptMemFaultInjector, "carcosa", - "CorruptMemFaultInjector", + "corruptMemFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a whole memory region being corrupted" ) @@ -35,7 +35,14 @@ class CorruptMemFaultInjector : public FaultInjectorBase { CorruptMemFaultInjector() = default; ~CorruptMemFaultInjector() {} protected: - // + std::array getValidInstallation() override; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + } + ImplementVirtualSerializable(SST::Carcosa::CorruptMemFaultInjector) }; // class CorruptMemFaultInjector } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc index e32cbb4d32..4161d678c9 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc @@ -15,96 +15,42 @@ using namespace SST::Carcosa; -DoubleFaultInjector::DoubleFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { +DoubleFaultInjector::DoubleFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault - fault = new FaultBase*[2]; + fault.resize(2); fault[0] = new RandomDropFault(params, this); fault[1] = new RandomFlipFault(params, this); // read flipvsdrop param flipVsDropProb_ = params.find("flipVsDropProb", 0.5); - distribution_ = std::uniform_real_distribution(0,1); } -DoubleFaultInjector::~DoubleFaultInjector() { - if (fault) { - if (fault[0]) { - delete fault[0]; - } - if (fault[1]) { - delete fault[1]; - } - delete fault; - } -} - -void DoubleFaultInjector::eventSent(uintptr_t key, Event*& ev) { - if (doInjection()){ -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); -#endif - if (!fault) { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); - } - FaultBase* triggered_fault = nullptr; - if (distribution_(generator_) <= flipVsDropProb_) { - // do flip +/** + * Overridden execution function to cause faults to be chosen at random + * from the vector once a fault has been triggered + */ +void DoubleFaultInjector::executeFaults(Event*& ev) { + FaultBase* triggered_fault = nullptr; + if (rng_.nextUniform() <= flipVsDropProb_) { + // do flip #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); #endif - triggered_fault = fault[1]; - } else { - // do drop + triggered_fault = fault[1]; + } else { + // do drop #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); #endif - triggered_fault = fault[0]; - } - if (triggered_fault) { - triggered_fault->faultLogic(ev); - } else { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); - } + triggered_fault = fault[0]; } -#ifdef __SST_DEBUG_OUTPUT__ - else { - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); + if (triggered_fault) { + triggered_fault->faultLogic(ev); + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); } -#endif } -void DoubleFaultInjector::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) { - // do not cancel delivery by default - cancel = false; - cancel_ = &cancel; - - if (doInjection()){ -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); -#endif - FaultBase* triggered_fault = nullptr; - if (distribution_(generator_) <= flipVsDropProb_) { - // do flip -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); -#endif - triggered_fault = fault[1]; - } else { - // do drop -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); -#endif - triggered_fault = fault[0]; - } - if (triggered_fault) { - triggered_fault->faultLogic(ev); - } else { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); - } - } -#ifdef __SST_DEBUG_OUTPUT__ - else { - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); - } -#endif +std::array DoubleFaultInjector::getValidInstallation() { + return SEND_RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h index f3beeb1cc7..1b852995ed 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -20,9 +20,9 @@ namespace SST::Carcosa { class DoubleFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - FaultInjectorBase, + DoubleFaultInjector, "carcosa", - "DoubleFaultInjector", + "doubleFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a data transfer lost at random OR a random bit flip in transit" ) @@ -34,15 +34,23 @@ class DoubleFaultInjector : public FaultInjectorBase { DoubleFaultInjector(Params& params); DoubleFaultInjector() = default; - ~DoubleFaultInjector(); - - void virtual eventSent(uintptr_t key, Event*& ev) override; - void virtual interceptHandler(uintptr_t key, Event*& ev, bool& cancel) override; + ~DoubleFaultInjector() {} protected: double flipVsDropProb_; - std::default_random_engine generator_; - std::uniform_real_distribution distribution_; + void executeFaults(Event*& ev) override; + std::array getValidInstallation() override; + + SST::RNG::MersenneRNG rng_; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + SST_SER(flipVsDropProb_); + SST_SER(rng_); + } + ImplementVirtualSerializable(SST::Carcosa::DoubleFaultInjector) }; // class DoubleFaultInjector } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index 08e7d439a5..0346a5ed3d 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -14,8 +14,11 @@ using namespace SST::Carcosa; -RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjectorBase(params, RECEIVE_VALID) { +RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault - fault = new FaultBase*; - *fault = new RandomDropFault(params, this); + fault.push_back(new RandomDropFault(params, this)); +} + +std::array RandomDropFaultInjector::getValidInstallation() { + return RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index 85a7ca67b7..645563f676 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -19,9 +19,9 @@ namespace SST::Carcosa { class RandomDropFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - FaultInjectorBase, + RandomDropFaultInjector, "carcosa", - "RandomFlipFaultInjector", + "randomFlipFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a data transfer lost at random" ) @@ -34,7 +34,14 @@ class RandomDropFaultInjector : public FaultInjectorBase { RandomDropFaultInjector() = default; ~RandomDropFaultInjector() {} protected: - // + std::array getValidInstallation() override; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + } + ImplementVirtualSerializable(SST::Carcosa::RandomDropFaultInjector) }; // class RandomDropFaultInjector } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc index 77e9909266..335fa188cd 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc @@ -14,8 +14,11 @@ using namespace SST::Carcosa; -RandomFlipFaultInjector::RandomFlipFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { +RandomFlipFaultInjector::RandomFlipFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault - fault = new FaultBase*; - *fault = new RandomFlipFault(params, this); + fault.push_back(new RandomFlipFault(params, this)); +} + +std::array RandomFlipFaultInjector::getValidInstallation() { + return SEND_RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index e1f3a5776f..0645fd01a1 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -19,9 +19,9 @@ namespace SST::Carcosa { class RandomFlipFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - FaultInjectorBase, + RandomFlipFaultInjector, "carcosa", - "RandomFlipFaultInjector", + "randomFlipFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a random bit flip when transferring data" ) @@ -34,7 +34,14 @@ class RandomFlipFaultInjector : public FaultInjectorBase { RandomFlipFaultInjector() = default; ~RandomFlipFaultInjector() {} protected: - // + std::array getValidInstallation() override; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + } + ImplementVirtualSerializable(SST::Carcosa::RandomFlipFaultInjector) }; // class RandomFlipFaultInjector } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc index 4f2fa39c84..4221f26bea 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc @@ -14,8 +14,11 @@ using namespace SST::Carcosa; -StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params, SEND_RECEIVE_VALID) { +StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault - fault = new FaultBase*; - *fault = new StuckAtFault(params, this); + fault.push_back(new StuckAtFault(params, this)); +} + +std::array StuckAtFaultInjector::getValidInstallation() { + return SEND_RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index 9fafaefce0..2f20205bf3 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -20,9 +20,9 @@ namespace SST::Carcosa { class StuckAtFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - FaultInjectorBase, + StuckAtFaultInjector, "carcosa", - "StuckAtFaultInjector", + "stuckAtFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a stuck bit within a given component" ) @@ -37,7 +37,14 @@ class StuckAtFaultInjector : public FaultInjectorBase { StuckAtFaultInjector() = default; ~StuckAtFaultInjector() {} protected: - // + std::array getValidInstallation() override; + + void serialize_order(SST::Core::Serialization::serializer& ser) override + { + SST::PortModule::serialize_order(ser); + // serialize parameters like `SST_SER()` + } + ImplementVirtualSerializable(SST::Carcosa::StuckAtFaultInjector) }; // class StuckAtFaultInjector } // namespace SST::Carcosa From f07217396452eb421b67af01b92fb0b46cb5d67d Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 8 Oct 2025 16:54:23 -0400 Subject: [PATCH 28/45] refactor should be complete Still todo: 1. Refine stuckAtFault debug prints to make more sense 2. Refine address selection in stuckAtFault and corruptMemFault to only corrupt the valid range of data --- src/sst/elements/carcosa/faultInjectorBase.cc | 33 ++++++++++++------- src/sst/elements/carcosa/faultInjectorBase.h | 12 ++++++- .../carcosa/faultlogic/corruptMemFault.cc | 10 +++--- .../carcosa/faultlogic/corruptMemFault.h | 14 +++++--- .../elements/carcosa/faultlogic/faultBase.h | 9 ++++- .../carcosa/faultlogic/randomDropFault.cc | 1 + .../carcosa/faultlogic/randomDropFault.h | 5 +++ .../carcosa/faultlogic/randomFlipFault.cc | 1 + .../carcosa/faultlogic/randomFlipFault.h | 5 +++ .../carcosa/faultlogic/stuckAtFault.cc | 23 ++++++------- .../carcosa/faultlogic/stuckAtFault.h | 11 +++++-- .../injectors/corruptMemFaultInjector.cc | 5 +-- .../injectors/corruptMemFaultInjector.h | 2 -- .../carcosa/injectors/doubleFaultInjector.cc | 6 ++-- .../carcosa/injectors/doubleFaultInjector.h | 1 - .../injectors/randomDropFaultInjector.cc | 23 +++++++++++-- .../injectors/randomDropFaultInjector.h | 4 +-- .../injectors/randomFlipFaultInjector.cc | 5 +-- .../injectors/randomFlipFaultInjector.h | 2 -- .../carcosa/injectors/stuckAtFaultInjector.cc | 5 +-- .../carcosa/injectors/stuckAtFaultInjector.h | 2 -- 21 files changed, 116 insertions(+), 63 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index ddbdcedfc4..1e3bc17a4c 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -35,18 +35,6 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif - - valid_installation_ = getValidInstallation(); - std::string install_dir = params.find("installDirection", "Receive"); - installDirection_ = setInstallDirection(install_dir); - - if (installDirection_ == installDirection::Invalid) { - out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); - } - -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); -#endif } /** @@ -64,6 +52,9 @@ FaultInjectorBase::~FaultInjectorBase() { void FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { + if (!valid_installs_set) { + out_->fatal(CALL_INFO_LONG, -1, "Valid installation directions not set -- did you forget to call setValidInstallation() in your constructor?\n"); + } if (doInjection()){ #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); @@ -80,6 +71,9 @@ FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) void FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) { + if (!valid_installs_set) { + out_->fatal(CALL_INFO_LONG, -1, "Valid installation directions not set -- did you forget to call setValidInstallation() in your constructor?\n"); + } // do not cancel delivery by default cancel = false; cancel_ = &cancel; @@ -119,6 +113,21 @@ installDirection FaultInjectorBase::setInstallDirection(std::string param) { return installDirection::Invalid; } +void FaultInjectorBase::setValidInstallation(Params& params, std::array valid_install) { + valid_installation_ = valid_install; + std::string install_dir = params.find("installDirection", "Receive"); + installDirection_ = setInstallDirection(install_dir); + + if (installDirection_ == installDirection::Invalid) { + out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); + } + +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInstall Direction: %s\n", install_dir.c_str()); +#endif + valid_installs_set = true; +} + /** * Default behavior is to execute faults in the order they were * added to the vector diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index c061feb65c..521d2bf846 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -137,12 +137,21 @@ class FaultInjectorBase : public SST::PortModule installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; SST::RNG::MersenneRNG base_rng_; +private: std::array valid_installation_ = {{false, false}}; + bool valid_installs_set = false; +protected: bool doInjection(); virtual void executeFaults(Event*& ev); - virtual std::array getValidInstallation() = 0; + /** + * This function MUST be called by the derived class constructor + * @arg params pass the same params object to this function + * @arg valid_install_ pass either SEND_VALID, RECEIVE_VALID, + * or SEND_RECEIVE_VALID + */ + void setValidInstallation(Params& params, std::array valid_install); void serialize_order(SST::Core::Serialization::serializer& ser) override { @@ -156,6 +165,7 @@ class FaultInjectorBase : public SST::PortModule SST_SER(injectionProbability_); SST_SER(base_rng_); SST_SER(valid_installation_); + SST_SER(valid_installs_set); } ImplementVirtualSerializable(SST::Carcosa::FaultInjectorBase) diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index bde17e3112..5d73fceac4 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -33,27 +33,27 @@ CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : region_pair.first, region_pair.second); } - corruptionRegions.push_back(region_pair); + corruptionRegions_.push_back(region_pair); #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Inserted corruption region: [0x%zx, 0x%zx]\n", region_pair.first, region_pair.second); #endif } - distribution = std::uniform_int_distribution(0,255); } +// TODO: fix this to respect endianness and byte array bool CorruptMemFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); Addr ev_addr = mem_ev->getAddr(); - for (auto& region: corruptionRegions) { + for (auto& region: corruptionRegions_) { if ((ev_addr >= region.first) || (ev_addr <= region.second)) { dataVec new_payload(8); for (uint8_t& byte: new_payload) { - byte = distribution(generator); + byte = static_cast(rng_.generateNextUInt32() % 255); } setMemEventPayload(ev, new_payload); - break; + return true; } } } diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index 8b7ef1101c..5e7acf9322 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -13,11 +13,11 @@ #define SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULT_H #include "sst/elements/carcosa/faultlogic/faultBase.h" +#include "sst/core/rng/mersenne.h" #include #include #include #include -#include namespace SST::Carcosa { @@ -49,12 +49,18 @@ class CorruptMemFault : public FaultBase bool faultLogic(Event*& ev) override; protected: - std::vector> corruptionRegions; + std::vector> corruptionRegions_; - std::default_random_engine generator; - std::uniform_int_distribution distribution; + SST::RNG::MersenneRNG rng_; std::pair convertString(std::string& region); + + void serialize_order(SST::Core::Serialization::serializer& ser) override { + FaultBase::serialize_order(ser); + SST_SER(corruptionRegions_); + SST_SER(rng_); + } + ImplementVirtualSerializable(CorruptMemFault) }; // CorruptMemFault } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index 68628ff947..52d134132d 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -13,6 +13,7 @@ #define SST_ELEMENTS_CARCOSA_FAULTBASE_H #include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/core/serialization/serializable.h" #include #include #include @@ -23,7 +24,7 @@ typedef std::vector dataVec; class FaultInjectorBase; // TODO: IMPLEMENT SERIALIZATION FOR THIS CLASS -class FaultBase { +class FaultBase : public SST::Core::Serialization::serializable { public: FaultBase(Params& params, FaultInjectorBase* injector); @@ -43,6 +44,12 @@ class FaultBase { void setMemEventPayload(Event*& ev, dataVec newPayload); protected: FaultInjectorBase* injector_ = nullptr; + + void serialize_order(SST::Core::Serialization::serializer& ser) override { + FaultBase::serialize_order(ser); + SST_SER(injector_); + } + ImplementVirtualSerializable(FaultBase) }; // class FaultBase } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc index db9981b626..b939c88200 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.cc @@ -27,4 +27,5 @@ bool RandomDropFault::faultLogic(Event*& ev) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Event dropped.\n"); #endif + return true; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomDropFault.h b/src/sst/elements/carcosa/faultlogic/randomDropFault.h index 12c3c42079..5dfa679d4b 100644 --- a/src/sst/elements/carcosa/faultlogic/randomDropFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomDropFault.h @@ -29,6 +29,11 @@ class RandomDropFault : public FaultBase { ~RandomDropFault() {} bool faultLogic(Event*& ev) override; +protected: + void serialize_order(SST::Core::Serialization::serializer& ser) override { + FaultBase::serialize_order(ser); + } + ImplementVirtualSerializable(RandomDropFault) }; // RandomDropFault } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index 11c35af241..e9fa674dcb 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -26,6 +26,7 @@ bool RandomFlipFault::faultLogic(Event*& ev) { uint8_t mask = static_cast(1) << (lucky_number.second); payload[lucky_number.first] = byte ^ mask; setMemEventPayload(ev, payload); + return true; } inline std::pair RandomFlipFault::pickByteAndBit() { diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h index 3498f72f0c..881b05331f 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -33,6 +33,11 @@ class RandomFlipFault : public FaultBase { * @return (byte, bit) */ inline std::pair pickByteAndBit(); +protected: + void serialize_order(SST::Core::Serialization::serializer& ser) override { + FaultBase::serialize_order(ser); + } + ImplementVirtualSerializable(RandomFlipFault) }; // RandomFlipFault } diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 6205292ff8..54f54c6b78 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -37,10 +37,10 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB "byte: %d\n", addr, byte); } // check for vector in each map before creating it - if (stuckAtZeroMask.count(addr) == 1) { - stuckAtZeroMask.at(addr).push_back(make_pair(byte, zeroMask)); + if (stuckAtZeroMask_.count(addr) == 1) { + stuckAtZeroMask_.at(addr).push_back(make_pair(byte, zeroMask)); } else { - auto addrVecPair = stuckAtZeroMask.emplace(make_pair(addr, std::vector>())); + auto addrVecPair = stuckAtZeroMask_.emplace(make_pair(addr, std::vector>())); if (addrVecPair.second) { addrVecPair.first->second.push_back(make_pair(byte, zeroMask)); } else { @@ -50,10 +50,10 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Finished inserting zero-masks for 0x%zx.\n", addr); #endif - if (stuckAtOneMask.count(addr) == 1) { - stuckAtOneMask.at(addr).push_back(make_pair(byte, oneMask)); + if (stuckAtOneMask_.count(addr) == 1) { + stuckAtOneMask_.at(addr).push_back(make_pair(byte, oneMask)); } else { - auto addrVecPair = stuckAtOneMask.emplace(make_pair(addr, std::vector>())); + auto addrVecPair = stuckAtOneMask_.emplace(make_pair(addr, std::vector>())); if (addrVecPair.second) { addrVecPair.first->second.push_back(make_pair(byte, oneMask)); } else { @@ -73,7 +73,7 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { Addr addr = mem_ev->getAddr(); // check for the addr in question in the fault map - if (stuckAtZeroMask.count(addr) == 1 || stuckAtOneMask.count(addr) == 1) { + if (stuckAtZeroMask_.count(addr) == 1 || stuckAtOneMask_.count(addr) == 1) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Addr 0x%zx found in stuck map.\n", addr); #endif @@ -89,8 +89,8 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin zero mask for address: 0x%zx\n", addr); #endif - if (stuckAtZeroMask.count(addr) == 1) { - for (auto maskPair: stuckAtZeroMask.at(addr)) { + if (stuckAtZeroMask_.count(addr) == 1) { + for (auto maskPair: stuckAtZeroMask_.at(addr)) { mask = maskPair.second; #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", @@ -104,8 +104,8 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End zero mask for address: 0x%zx\n", addr); getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin one mask for address: 0x%zx\n", addr); #endif - if (stuckAtOneMask.count(addr) == 1) { - for (auto maskPair: stuckAtOneMask.at(addr)) { + if (stuckAtOneMask_.count(addr) == 1) { + for (auto maskPair: stuckAtOneMask_.at(addr)) { mask = maskPair.second; #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", @@ -122,6 +122,7 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { // replace payload this->setMemEventPayload(ev, payload); } + return true; } std::vector StuckAtFault::convertString(std::vector& paramVecString) { diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index 08e8b73a32..f96e5f6978 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -54,9 +54,9 @@ class StuckAtFault : public FaultBase protected: // map of addr->{byte, mask} for saving stuck bit values - std::map>> stuckAtZeroMask; + std::map>> stuckAtZeroMask_; // add stuckAtOneMask - std::map>> stuckAtOneMask; + std::map>> stuckAtOneMask_; typedef struct maskParam { Addr addr; @@ -66,6 +66,13 @@ class StuckAtFault : public FaultBase } maskParam_t; std::vector convertString(std::vector& paramVecStr); + + void serialize_order(SST::Core::Serialization::serializer& ser) override { + FaultBase::serialize_order(ser); + SST_SER(stuckAtZeroMask_); + SST_SER(stuckAtOneMask_); + } + ImplementVirtualSerializable(StuckAtFault) }; } // namespace SST::Carcosa diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc index 7cbea20325..012bb2aaec 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc @@ -17,8 +17,5 @@ using namespace SST::Carcosa; CorruptMemFaultInjector::CorruptMemFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault fault.push_back(new CorruptMemFault(params, this)); -} - -std::array CorruptMemFaultInjector::getValidInstallation() { - return SEND_RECEIVE_VALID; + setValidInstallation(params, SEND_RECEIVE_VALID); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index b38221f9b1..930294c221 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -35,8 +35,6 @@ class CorruptMemFaultInjector : public FaultInjectorBase { CorruptMemFaultInjector() = default; ~CorruptMemFaultInjector() {} protected: - std::array getValidInstallation() override; - void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc index 4161d678c9..ab83e4063b 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc @@ -23,6 +23,8 @@ DoubleFaultInjector::DoubleFaultInjector(Params& params) : FaultInjectorBase(par // read flipvsdrop param flipVsDropProb_ = params.find("flipVsDropProb", 0.5); + + setValidInstallation(params, SEND_RECEIVE_VALID); } /** @@ -49,8 +51,4 @@ void DoubleFaultInjector::executeFaults(Event*& ev) { } else { out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); } -} - -std::array DoubleFaultInjector::getValidInstallation() { - return SEND_RECEIVE_VALID; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h index 1b852995ed..1a7b0c4373 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -39,7 +39,6 @@ class DoubleFaultInjector : public FaultInjectorBase { double flipVsDropProb_; void executeFaults(Event*& ev) override; - std::array getValidInstallation() override; SST::RNG::MersenneRNG rng_; diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index 0346a5ed3d..3a1fb9e642 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -17,8 +17,27 @@ using namespace SST::Carcosa; RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault fault.push_back(new RandomDropFault(params, this)); + setValidInstallation(params, RECEIVE_VALID); } -std::array RandomDropFaultInjector::getValidInstallation() { - return RECEIVE_VALID; +/** + * Custom execution is required to ensure delivery is canceled + * + * In the base interceptHandler, a reference to a boolean called + * 'cancel' is accepted as an argument. That function assigns the + * injector's pointer (called 'cancel_') to that reference's address, + * and that reference must be updated here after the event is destroyed + * if the installation direction of this PortModule was set to 'Receive'. + */ +void RandomDropFaultInjector::executeFaults(Event*& ev) { + bool success = false; + if (fault[0]) { + success = fault[0]->faultLogic(ev); + if (installDirection_ == installDirection::Receive) { + *cancel_ = true; + } + } + if (!success) { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object, or no fault successfully executed.\n"); + } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index 645563f676..557ef2485a 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -34,8 +34,8 @@ class RandomDropFaultInjector : public FaultInjectorBase { RandomDropFaultInjector() = default; ~RandomDropFaultInjector() {} protected: - std::array getValidInstallation() override; - + void executeFaults(Event*& ev) override; + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc index 335fa188cd..ace17da2af 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc @@ -17,8 +17,5 @@ using namespace SST::Carcosa; RandomFlipFaultInjector::RandomFlipFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault fault.push_back(new RandomFlipFault(params, this)); -} - -std::array RandomFlipFaultInjector::getValidInstallation() { - return SEND_RECEIVE_VALID; + setValidInstallation(params, SEND_RECEIVE_VALID); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index 0645fd01a1..c00cc6619f 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -34,8 +34,6 @@ class RandomFlipFaultInjector : public FaultInjectorBase { RandomFlipFaultInjector() = default; ~RandomFlipFaultInjector() {} protected: - std::array getValidInstallation() override; - void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc index 4221f26bea..f8968a63c4 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.cc @@ -17,8 +17,5 @@ using namespace SST::Carcosa; StuckAtFaultInjector::StuckAtFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault fault.push_back(new StuckAtFault(params, this)); -} - -std::array StuckAtFaultInjector::getValidInstallation() { - return SEND_RECEIVE_VALID; + setValidInstallation(params, SEND_RECEIVE_VALID); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index 2f20205bf3..684a10287b 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -37,8 +37,6 @@ class StuckAtFaultInjector : public FaultInjectorBase { StuckAtFaultInjector() = default; ~StuckAtFaultInjector() {} protected: - std::array getValidInstallation() override; - void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); From 8bdc46de799c633b76896daab2c71c00bdde2504 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 8 Oct 2025 17:39:27 -0400 Subject: [PATCH 29/45] add todos to codebase --- src/sst/elements/carcosa/faultlogic/faultBase.h | 2 +- src/sst/elements/carcosa/faultlogic/stuckAtFault.cc | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index 52d134132d..785d25ee63 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -23,7 +23,7 @@ namespace SST::Carcosa { typedef std::vector dataVec; class FaultInjectorBase; -// TODO: IMPLEMENT SERIALIZATION FOR THIS CLASS + class FaultBase : public SST::Core::Serialization::serializable { public: FaultBase(Params& params, FaultInjectorBase* injector); diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 54f54c6b78..d037f6feee 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -79,6 +79,7 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); + // TODO: review everything in below comment and adjust this function // payloads are given a size in the memEvent and it's usually cache line size // addr is whatever the core requested // base addr is first addr in byte array From 50c11cc273fda7bad455cd74581b5e33a50640b9 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 17 Oct 2025 17:07:57 -0400 Subject: [PATCH 30/45] fix some ELI weirdness stuckAtFault debug output should be fixed, and it now properly accounts for endianness in the data array FaultBase debug outputs for setMemEventPayload improved need to take a look at corrupt mem next, and run some more tests on stuck at --- src/sst/elements/carcosa/faultInjectorBase.h | 2 +- .../elements/carcosa/faultlogic/faultBase.cc | 28 ++++--- .../carcosa/faultlogic/stuckAtFault.cc | 78 +++++++++++++------ .../carcosa/faultlogic/stuckAtFault.h | 3 + .../injectors/corruptMemFaultInjector.h | 2 +- .../carcosa/injectors/doubleFaultInjector.h | 2 +- .../injectors/randomDropFaultInjector.h | 2 +- .../injectors/randomFlipFaultInjector.h | 2 +- .../carcosa/injectors/stuckAtFaultInjector.h | 3 +- src/sst/elements/carcosa/tests/dummyTest.py | 4 +- 10 files changed, 85 insertions(+), 41 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 521d2bf846..9487e314d3 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -52,7 +52,7 @@ class FaultInjectorBase : public SST::PortModule SST_ELI_REGISTER_PORTMODULE( FaultInjectorBase, "carcosa", - "faultInjectorBase", + "FaultInjectorBase", SST_ELI_ELEMENT_VERSION(0, 1, 0), "Base PortModule class used to connect fault injection logic to components" ) diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.cc b/src/sst/elements/carcosa/faultlogic/faultBase.cc index 1973544e57..4a648f6699 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.cc +++ b/src/sst/elements/carcosa/faultlogic/faultBase.cc @@ -37,7 +37,7 @@ SST::MemHierarchy::MemEvent* FaultBase::convertMemEvent(Event*& ev) { } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); + getSimulationDebug()->debug(CALL_INFO_LONG, 3, 0, "Intercepted event %zu/%d\n", mem_ev->getID().first, mem_ev->getID().second); #endif return mem_ev; } @@ -48,20 +48,30 @@ dataVec& FaultBase::getMemEventPayload(Event*& ev) { void FaultBase::setMemEventPayload(Event*& ev, dataVec newPayload) { #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n["); - for (int i: getMemEventPayload(ev)) { - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload before replacement:\n"); + SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); + dataVec payload = getMemEventPayload(ev); + for (int i = 0; i < payload.size(); i+=8) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "\n0x%zx: [\t", mem_ev->getBaseAddr() + i); + for (int j = i; j < (i+8); j++) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", payload[j]); + } + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); } - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif convertMemEvent(ev)->setPayload(newPayload); #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n["); - for (int i: getMemEventPayload(ev)) { - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", i); + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Payload after replacement:\n"); + mem_ev = convertMemEvent(ev); + payload = getMemEventPayload(ev); + for (int i = 0; i < payload.size(); i+=8) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "\n0x%zx: [\t", mem_ev->getBaseAddr() + i); + for (int j = i; j < (i+8); j++) { + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "%d\t", payload[j]); + } + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); } - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "]\n"); #endif } diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index d037f6feee..33f32046c0 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -64,6 +64,11 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Finished inserting one-masks for 0x%zx.\n", addr); #endif } + + endianness = (params.find("endianness", "little") == std::string("little")) ? false : true; +#ifdef __SST_DEBUG_OUTPUT__ + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Endianness set to %s.\n", endianness ? "big" : "little"); +#endif } bool StuckAtFault::faultLogic(SST::Event*& ev) { @@ -71,11 +76,17 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = this->convertMemEvent(ev); Addr addr = mem_ev->getAddr(); + std::vector masked_addrs; + for (int i = mem_ev->getBaseAddr(); i < mem_ev->getBaseAddr() + mem_ev->getPayloadSize(); i+=8) { + if (stuckAtZeroMask_.count(i) == 1 || stuckAtOneMask_.count(i) == 1) { + masked_addrs.push_back(i); + } + } // check for the addr in question in the fault map - if (stuckAtZeroMask_.count(addr) == 1 || stuckAtOneMask_.count(addr) == 1) { + if (masked_addrs.size() > 0) { #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Addr 0x%zx found in stuck map.\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Masked Addr at cache line 0x%zx found in stuck map.\n", addr); #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); @@ -86,43 +97,50 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { // vanadis riscv is LITTLE ENDIAN so byte order is reversed (byte 0 at Addr A is lowest byte, but Addr0 is still base addr, Addr1 = Addr0+8) // confirm that little endian is this trolling - uint8_t mask = 0b00000000; + for (int masked_addr: masked_addrs){ + uint8_t mask = 0b00000000; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin zero mask for address: 0x%zx\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin zero mask for address: 0x%zx\n", masked_addr); #endif - if (stuckAtZeroMask_.count(addr) == 1) { - for (auto maskPair: stuckAtZeroMask_.at(addr)) { - mask = maskPair.second; + // mask tuple is (byte, mask) + if (stuckAtZeroMask_.count(masked_addr) == 1) { + for (auto maskPair: stuckAtZeroMask_.at(masked_addr)) { + mask = maskPair.second; + uint32_t final_byte = computeByte(masked_addr, mem_ev->getBaseAddr(), maskPair.first); #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", - maskPair.first, (int)payload[maskPair.first], (int) mask, - (int)(payload[maskPair.first] &= (!mask))); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + maskPair.first, (int)payload[final_byte], (int) mask, + (int)(payload[final_byte] & (!mask))); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tPayload index: %d\n", final_byte); #endif - payload[maskPair.first] &= (!mask); + payload[final_byte] &= (!mask); + } } - } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End zero mask for address: 0x%zx\n", addr); - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin one mask for address: 0x%zx\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End zero mask for address: 0x%zx\n", masked_addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Begin one mask for address: 0x%zx\n", masked_addr); #endif - if (stuckAtOneMask_.count(addr) == 1) { - for (auto maskPair: stuckAtOneMask_.at(addr)) { - mask = maskPair.second; + if (stuckAtOneMask_.count(masked_addr) == 1) { + for (auto maskPair: stuckAtOneMask_.at(masked_addr)) { + mask = maskPair.second; + uint32_t final_byte = computeByte(masked_addr, mem_ev->getBaseAddr(), maskPair.first); #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", - maskPair.first, (int)payload[maskPair.first], (int) mask, - (int)(payload[maskPair.first] |= mask)); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", + maskPair.first, (int)payload[final_byte], (int) mask, + (int)(payload[final_byte] | mask)); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tPayload index: %d\n", final_byte); #endif - payload[maskPair.first] |= mask; - } + payload[final_byte] |= mask; + } #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End one mask for address: 0x%zx\n", addr); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "End one mask for address: 0x%zx\n", masked_addr); #endif + } } // replace payload this->setMemEventPayload(ev, payload); - } + } // if (found) return true; } @@ -160,4 +178,16 @@ std::vector StuckAtFault::convertString(std::vector(B7|B6|B5|B4|B3|B2|B1|B0); Little endian: Addr->(B0|B1|B2|B3|B4|B5|B6|B7) + // endianness bool -> true = big; false = little + if (endianness) { + return (base_byte + 7) - byte; + } else { + return base_byte + byte; + } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index f96e5f6978..f9b1cf85bd 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -57,6 +57,8 @@ class StuckAtFault : public FaultBase std::map>> stuckAtZeroMask_; // add stuckAtOneMask std::map>> stuckAtOneMask_; + // false = little; true = big + bool endianness = false; typedef struct maskParam { Addr addr; @@ -66,6 +68,7 @@ class StuckAtFault : public FaultBase } maskParam_t; std::vector convertString(std::vector& paramVecStr); + uint32_t computeByte(Addr addr, Addr base_addr, uint32_t byte); void serialize_order(SST::Core::Serialization::serializer& ser) override { FaultBase::serialize_order(ser); diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index 930294c221..ae891fb1a3 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -21,7 +21,7 @@ class CorruptMemFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( CorruptMemFaultInjector, "carcosa", - "corruptMemFaultInjector", + "CorruptMemFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a whole memory region being corrupted" ) diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h index 1a7b0c4373..04b658d034 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -22,7 +22,7 @@ class DoubleFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( DoubleFaultInjector, "carcosa", - "doubleFaultInjector", + "DoubleFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a data transfer lost at random OR a random bit flip in transit" ) diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index 557ef2485a..ee6b7f2af2 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -21,7 +21,7 @@ class RandomDropFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( RandomDropFaultInjector, "carcosa", - "randomFlipFaultInjector", + "RandomFlipFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a data transfer lost at random" ) diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index c00cc6619f..cbb79c03f6 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -21,7 +21,7 @@ class RandomFlipFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( RandomFlipFaultInjector, "carcosa", - "randomFlipFaultInjector", + "RandomFlipFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a random bit flip when transferring data" ) diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index 684a10287b..d3ba913e65 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -22,7 +22,7 @@ class StuckAtFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( StuckAtFaultInjector, "carcosa", - "stuckAtFaultInjector", + "StuckAtFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a stuck bit within a given component" ) @@ -30,6 +30,7 @@ class StuckAtFaultInjector : public FaultInjectorBase { SST_ELI_DOCUMENT_PARAMS( {"masks", "String array formatted as [\"addr0, byte0, zeroMask0, oneMask0\",...,\"addrN, byteN, zeroMaskN, oneMaskN\"]." \ "Addresses are expected to be in hexadecimal, and masks are 8 bit strings."}, + {"endianness", "Byte ordering in memory. Given as a string containing \'little\' or \'big\'. Default: little"} ) StuckAtFaultInjector(Params& params); diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index b2d7d7baba..136b4e996e 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -498,8 +498,8 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { "intallDirection": "Receive", - #"injectionProbability": 0.25, - "masks": ["DEADBEEF, 3, 10101010, 01010101"], + "injectionProbability": 1.0, + "masks": ["4DA0, 3, 00001111, 11110000"], "debug" : 1, "debug_level": 2 }) From 06612b0fec4d64fc51939eef81ba8373637ec062 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 20 Oct 2025 14:13:33 -0400 Subject: [PATCH 31/45] 95% sure stuckAtFault logic is working as intended --- src/sst/elements/carcosa/faultInjectorBase.cc | 8 ++++---- src/sst/elements/carcosa/faultlogic/stuckAtFault.cc | 4 ++-- src/sst/elements/carcosa/tests/dummyTest.py | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 1e3bc17a4c..a102fea351 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -57,13 +57,13 @@ FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) } if (doInjection()){ #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); + dbg_->debug(CALL_INFO_LONG, 3, 0, "Injection triggered.\n"); #endif this->executeFaults(ev); } #ifdef __SST_DEBUG_OUTPUT__ else { - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); + dbg_->debug(CALL_INFO_LONG, 3, 0, "Injection skipped.\n"); } #endif } @@ -80,13 +80,13 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) if (doInjection()){ #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); + dbg_->debug(CALL_INFO_LONG, 3, 0, "Injection triggered.\n"); #endif this->executeFaults(ev); } #ifdef __SST_DEBUG_OUTPUT__ else { - dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); + dbg_->debug(CALL_INFO_LONG, 3, 0, "Injection skipped.\n"); } #endif } diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 33f32046c0..3d40a1cb94 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -110,10 +110,10 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", maskPair.first, (int)payload[final_byte], (int) mask, - (int)(payload[final_byte] & (!mask))); + (int)(payload[final_byte] & (~mask))); getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tPayload index: %d\n", final_byte); #endif - payload[final_byte] &= (!mask); + payload[final_byte] &= (~mask); } } #ifdef __SST_DEBUG_OUTPUT__ diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index 136b4e996e..cd8f1b2676 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -499,7 +499,7 @@ def addParamsPrefix(prefix,params): memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { "intallDirection": "Receive", "injectionProbability": 1.0, - "masks": ["4DA0, 3, 00001111, 11110000"], + "masks": ["4DA0, 3, 00001111, 11110000", "4D98, 3, 10101010, 01010101"], "debug" : 1, "debug_level": 2 }) From 87293b4e3958ac3c1f42aa3c10ba398642297984 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Mon, 20 Oct 2025 15:56:44 -0400 Subject: [PATCH 32/45] remove todos from stuckAtFault and make endianness member consistent with other members begin fix for corruptMemRegion - No longer crashes simulation - Should be more optimized to only run on smaller regions of code that actually need changes instead of looping through everything every time - Currently crashes when hitting assertion for start index of corrupt message when two regions are in the same message but don't overlap --- .../carcosa/faultlogic/corruptMemFault.cc | 75 ++++++++++++++++--- .../carcosa/faultlogic/corruptMemFault.h | 8 ++ .../carcosa/faultlogic/stuckAtFault.cc | 12 +-- .../carcosa/faultlogic/stuckAtFault.h | 3 +- .../injectors/corruptMemFaultInjector.cc | 14 ++++ .../injectors/corruptMemFaultInjector.h | 2 + src/sst/elements/carcosa/tests/dummyTest.py | 4 +- 7 files changed, 95 insertions(+), 23 deletions(-) diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index 5d73fceac4..bbab9b698f 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -29,7 +29,7 @@ CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : // check validity if (region_pair.first > region_pair.second) { - getSimulationOutput()->fatal(CALL_INFO_LONG, 1, 0, "Invalid corruption region: [0x%zx, 0x%zx].\n", + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Invalid corruption region: [0x%zx, 0x%zx].\n", region_pair.first, region_pair.second); } @@ -41,20 +41,32 @@ CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : } } -// TODO: fix this to respect endianness and byte array bool CorruptMemFault::faultLogic(Event*& ev) { SST::MemHierarchy::MemEvent* mem_ev = convertMemEvent(ev); - Addr ev_addr = mem_ev->getAddr(); - for (auto& region: corruptionRegions_) { - if ((ev_addr >= region.first) || (ev_addr <= region.second)) { - dataVec new_payload(8); - for (uint8_t& byte: new_payload) { - byte = static_cast(rng_.generateNextUInt32() % 255); + Addr base_addr = mem_ev->getBaseAddr(); + dataVec original_payload = mem_ev->getPayload(); + for (int r: regionsToUse_) { + auto& region = corruptionRegions_[r]; + size_t payload_sz = mem_ev->getPayloadSize(); + int32_t start = computeStartIndex(base_addr, payload_sz, region.first); + if (start < 0) { + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "No valid start index for corruption.\n"); + } + int32_t end = computeEndIndex(base_addr, payload_sz, region.second); + if (end < 0) { + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "No valid start index for corruption.\n"); + } + dataVec new_payload(payload_sz); + for (int i = 0; i < payload_sz; i++) { + if ((i < start) || (i > end)) { + new_payload[i] = original_payload[i]; + } else if ((i >= start) && (i <= end)) { + new_payload[i] = static_cast(rng_.generateNextUInt32() % 255); } - setMemEventPayload(ev, new_payload); - return true; } + setMemEventPayload(ev, new_payload); + return true; } } @@ -69,8 +81,49 @@ std::pair CorruptMemFault::convertString(std::string& region) ss >> std::hex >> addr1; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Extracted region pair: [0x%zu, 0x%zx]\n", + getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Extracted region pair: [0x%zx, 0x%zx]\n", addr0, addr1); #endif return make_pair(addr0, addr1); +} + +int32_t CorruptMemFault::computeStartIndex(Addr base_addr, size_t payload_sz, Addr region_start) { + // start index is always the first byte of this payload in the corruption region + int payload_bytes = payload_sz / 8; + Addr addr = base_addr; + for (int i = 0; i < payload_bytes; i++, addr+=8) { + if (addr >= region_start) { + return addr - base_addr; + } + } + return -1; +} + +int32_t CorruptMemFault::computeEndIndex(Addr base_addr, size_t payload_sz, Addr region_end) { + // end index is either the final addr's final byte, or the region end's addr's final byte + int payload_bytes = payload_sz / 8; + Addr addr = base_addr + ((payload_bytes - 1) * 8); + for (int i = payload_bytes; i >= 0; i--, addr-=8) { + if (addr <= region_end) { + return addr - base_addr; + } + } + return -1; +} + +// TODO: why is this triggering a push_back on 0x4D80 from payload 0x4d40? +std::vector* CorruptMemFault::checkAddrUsage(Event*& ev) { + Addr addr = convertMemEvent(ev)->getBaseAddr(); + for (int i = 0; i < corruptionRegions_.size(); i++) { + auto& region = corruptionRegions_[i]; + // check if message contains ANY address in this region + int payload_bytes = convertMemEvent(ev)->getPayloadSize() / 8; + for (int j = 0; j < payload_bytes; j++, addr+=8) { + if ((addr >= region.first) && (addr <= region.second)) { + regionsToUse_.push_back(i); + break; + } + } + } + return ®ionsToUse_; } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index 5e7acf9322..2d5fc97909 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -47,18 +47,26 @@ class CorruptMemFault : public FaultBase * 4. Replace payload */ bool faultLogic(Event*& ev) override; + + std::vector* checkAddrUsage(Event*& ev); protected: std::vector> corruptionRegions_; SST::RNG::MersenneRNG rng_; + std::vector regionsToUse_; + std::pair convertString(std::string& region); + int32_t computeStartIndex(Addr base_addr, size_t payload_sz, Addr region_start); + int32_t computeEndIndex(Addr base_addr, size_t payload_sz, Addr region_end); + void serialize_order(SST::Core::Serialization::serializer& ser) override { FaultBase::serialize_order(ser); SST_SER(corruptionRegions_); SST_SER(rng_); + SST_SER(regionsToUse_); } ImplementVirtualSerializable(CorruptMemFault) }; // CorruptMemFault diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 3d40a1cb94..7bacc2b2cd 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -65,9 +65,9 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB #endif } - endianness = (params.find("endianness", "little") == std::string("little")) ? false : true; + endianness_ = (params.find("endianness", "little") == std::string("little")) ? false : true; #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Endianness set to %s.\n", endianness ? "big" : "little"); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Endianness set to %s.\n", endianness_ ? "big" : "little"); #endif } @@ -90,12 +90,6 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { #endif // replace data if necessary dataVec payload = this->getMemEventPayload(ev); - // TODO: review everything in below comment and adjust this function - // payloads are given a size in the memEvent and it's usually cache line size - // addr is whatever the core requested - // base addr is first addr in byte array - // vanadis riscv is LITTLE ENDIAN so byte order is reversed (byte 0 at Addr A is lowest byte, but Addr0 is still base addr, Addr1 = Addr0+8) - // confirm that little endian is this trolling for (int masked_addr: masked_addrs){ uint8_t mask = 0b00000000; @@ -185,7 +179,7 @@ uint32_t StuckAtFault::computeByte(Addr addr, Addr base_addr, uint32_t byte) { // vanadis riscv is little endian, so bytes are in reverse order // Big endian: Addr->(B7|B6|B5|B4|B3|B2|B1|B0); Little endian: Addr->(B0|B1|B2|B3|B4|B5|B6|B7) // endianness bool -> true = big; false = little - if (endianness) { + if (endianness_) { return (base_byte + 7) - byte; } else { return base_byte + byte; diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index f9b1cf85bd..c587db77c5 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -58,7 +58,7 @@ class StuckAtFault : public FaultBase // add stuckAtOneMask std::map>> stuckAtOneMask_; // false = little; true = big - bool endianness = false; + bool endianness_ = false; typedef struct maskParam { Addr addr; @@ -74,6 +74,7 @@ class StuckAtFault : public FaultBase FaultBase::serialize_order(ser); SST_SER(stuckAtZeroMask_); SST_SER(stuckAtOneMask_); + SST_SER(endianness_); } ImplementVirtualSerializable(StuckAtFault) }; diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc index 012bb2aaec..dad7271924 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc @@ -18,4 +18,18 @@ CorruptMemFaultInjector::CorruptMemFaultInjector(Params& params) : FaultInjector // create fault fault.push_back(new CorruptMemFault(params, this)); setValidInstallation(params, SEND_RECEIVE_VALID); +} + +void CorruptMemFaultInjector::executeFaults(Event*& ev) { + // is this addr in a corrupt region? + std::vector* regionsToUse = dynamic_cast(fault[0])->checkAddrUsage(ev); + // if returned vec is not empty, save to fault-accessible location and execute + if (regionsToUse->size() != 0) { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 2, 0, "Corruption region detected.\n"); +#endif + fault[0]->faultLogic(ev); + // reset vec + regionsToUse->clear(); + } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index ae891fb1a3..de611f6ab5 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -35,6 +35,8 @@ class CorruptMemFaultInjector : public FaultInjectorBase { CorruptMemFaultInjector() = default; ~CorruptMemFaultInjector() {} protected: + void executeFaults(Event*& ev) override; + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py index cd8f1b2676..78b293fac5 100644 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ b/src/sst/elements/carcosa/tests/dummyTest.py @@ -496,10 +496,10 @@ def addParamsPrefix(prefix,params): # node memory controller memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) -memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { +memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { "intallDirection": "Receive", "injectionProbability": 1.0, - "masks": ["4DA0, 3, 00001111, 11110000", "4D98, 3, 10101010, 01010101"], + "regions": ["4D88, 4D90", "4DA0, 4DA8"], "debug" : 1, "debug_level": 2 }) From b96ebfb6fbda9492c96a71699cb7231eb53caa90 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Tue, 21 Oct 2025 17:39:11 -0400 Subject: [PATCH 33/45] 95% certain that corruptMemFault is working as intended Todo: - Build test configs for each included fault and get them into the testing system --- .../elements/carcosa/faultlogic/corruptMemFault.cc | 12 +++++++----- .../elements/carcosa/faultlogic/randomFlipFault.cc | 1 - .../carcosa/injectors/corruptMemFaultInjector.cc | 7 ++++++- .../carcosa/injectors/randomDropFaultInjector.cc | 3 --- 4 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index bbab9b698f..fdfb26d5b4 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -66,8 +66,9 @@ bool CorruptMemFault::faultLogic(Event*& ev) { } } setMemEventPayload(ev, new_payload); - return true; + break; } + return true; } std::pair CorruptMemFault::convertString(std::string& region) { @@ -80,10 +81,10 @@ std::pair CorruptMemFault::convertString(std::string& region) } ss >> std::hex >> addr1; - #ifdef __SST_DEBUG_OUTPUT__ +#ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 2, 0, "Extracted region pair: [0x%zx, 0x%zx]\n", addr0, addr1); - #endif +#endif return make_pair(addr0, addr1); } @@ -113,12 +114,13 @@ int32_t CorruptMemFault::computeEndIndex(Addr base_addr, size_t payload_sz, Addr // TODO: why is this triggering a push_back on 0x4D80 from payload 0x4d40? std::vector* CorruptMemFault::checkAddrUsage(Event*& ev) { - Addr addr = convertMemEvent(ev)->getBaseAddr(); + Addr base_addr = convertMemEvent(ev)->getBaseAddr(); for (int i = 0; i < corruptionRegions_.size(); i++) { auto& region = corruptionRegions_[i]; // check if message contains ANY address in this region int payload_bytes = convertMemEvent(ev)->getPayloadSize() / 8; - for (int j = 0; j < payload_bytes; j++, addr+=8) { + Addr addr = base_addr; + for (int j = 0; j < payload_bytes; addr+=8, j++) { if ((addr >= region.first) && (addr <= region.second)) { regionsToUse_.push_back(i); break; diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index e9fa674dcb..2ac59e437a 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -20,7 +20,6 @@ RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : bool RandomFlipFault::faultLogic(Event*& ev) { // check if this is the proper event type and get payload if it is dataVec payload = getMemEventPayload(ev); - //getSimulationOutput()->output(CALL_INFO_LONG, 1, 0, "Payload size: %d\n", payload.size()); std::pair lucky_number = pickByteAndBit(); uint8_t byte = payload[lucky_number.first]; uint8_t mask = static_cast(1) << (lucky_number.second); diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc index dad7271924..1d744e7abe 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.cc @@ -28,7 +28,12 @@ void CorruptMemFaultInjector::executeFaults(Event*& ev) { #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 2, 0, "Corruption region detected.\n"); #endif - fault[0]->faultLogic(ev); + if (!fault[0]) { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault to execute.\n"); + } + if (!fault[0]->faultLogic(ev)) { + out_->fatal(CALL_INFO_LONG, -1, "Fault somehow returned unsuccessful... How?\n"); + } // reset vec regionsToUse->clear(); } diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index 3a1fb9e642..84305d9d3a 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -33,9 +33,6 @@ void RandomDropFaultInjector::executeFaults(Event*& ev) { bool success = false; if (fault[0]) { success = fault[0]->faultLogic(ev); - if (installDirection_ == installDirection::Receive) { - *cancel_ = true; - } } if (!success) { out_->fatal(CALL_INFO_LONG, -1, "No valid fault object, or no fault successfully executed.\n"); From 29f703549d86d805307e47974da0f24931b2ee4c Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 13:37:21 -0400 Subject: [PATCH 34/45] add test suite for corruptMemFault (overlap fails currently) --- .../carcosa/tests/testCorruptMemBasic.py | 571 ++++++++++++++++++ .../carcosa/tests/testCorruptMemDouble.py | 571 ++++++++++++++++++ .../tests/testCorruptMemDoubleOverlap.py | 571 ++++++++++++++++++ 3 files changed, 1713 insertions(+) create mode 100644 src/sst/elements/carcosa/tests/testCorruptMemBasic.py create mode 100644 src/sst/elements/carcosa/tests/testCorruptMemDouble.py create mode 100644 src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py diff --git a/src/sst/elements/carcosa/tests/testCorruptMemBasic.py b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py new file mode 100644 index 0000000000..1f2f1b8fe7 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "regions": ["4D88, 4DA0"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDouble.py b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py new file mode 100644 index 0000000000..78b293fac5 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "regions": ["4D88, 4D90", "4DA0, 4DA8"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py new file mode 100644 index 0000000000..f36238219a --- /dev/null +++ b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "regions": ["4D88, 4DA0", "4D90, 4DA8"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + From 107945a1846d792d14a5c3afd5357f0787805605 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 13:37:59 -0400 Subject: [PATCH 35/45] remove dummy test --- src/sst/elements/carcosa/tests/dummyTest.py | 571 -------------------- 1 file changed, 571 deletions(-) delete mode 100644 src/sst/elements/carcosa/tests/dummyTest.py diff --git a/src/sst/elements/carcosa/tests/dummyTest.py b/src/sst/elements/carcosa/tests/dummyTest.py deleted file mode 100644 index 78b293fac5..0000000000 --- a/src/sst/elements/carcosa/tests/dummyTest.py +++ /dev/null @@ -1,571 +0,0 @@ -import os -import sst -mh_debug_level=10 -mh_debug=0 -# this has to be a string -dbgAddr="0" -stopDbg="0" - -checkpointDir = "" -checkpoint = "" - -#checkpointDir = "checkpoint0" -#checkpoint = "load" -#checkpoint = "save" - -pythonDebug=False - -vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") -isa="mipsel" -vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") -isa="riscv64" - -loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") - -testDir="basic-io" -exe = "hello-world" -#exe = "hello-world-cpp" -#exe = "openat" -#exe = "printf-check" -#exe = "read-write" -#exe = "fread-fwrite" -#exe = "unlink" -#exe = "unlinkat" -#exe = "lseek" - -#testDir = "basic-math" -#exe = "sqrt-double" -#exe = "sqrt-float" - -#testDir = "basic-ops" -#exe = "test-branch" -#exe = "test-shift" - -#testDir = "misc" -#exe = "mt-dgemm" -#exe = "stream" -#exe = "stream-fortran" -#exe = "gettime" -#exe = "splitLoad" -#exe = "fork" -#exe = "clone" -#exe = "pthread" -#exe = "openmp" -#exe = "openmp2" -#exe = "uname" -#exe = "mem-test" -#exe = "checkpoint" - -physMemSize = "4GiB" - -tlbType = "simpleTLB" -mmuType = "simpleMMU" - -# Define SST core options -sst.setProgramOption("timebase", "1ps") -sst.setProgramOption("stop-at", "0 ns") - -# Tell SST what statistics handling we want -sst.setStatisticLoadLevel(4) -sst.setStatisticOutput("sst.statOutputConsole") - -full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) -exe_name= full_exe_name.split("/")[-1] - -verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) -os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) -pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") -lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) -lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) - -rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) -retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) -issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) -decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) - -integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) -integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) -fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) -fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) -branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) - -cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") - -numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) -numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) - -vanadis_cpu_type = "vanadis." -vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") - -if (verbosity > 0): - print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) - print("Auto-clock syscalls: " + str(auto_clock_sys)) -# vanadis_cpu_type = "vanadisdbg.VanadisCPU" - -app_args = os.getenv("VANADIS_EXE_ARGS", "") - -app_params = {} -if app_args != "": - app_args_list = app_args.split(" ") - # We have a plus 1 because the executable name is arg0 - app_args_count = len( app_args_list ) + 1 - - app_params["argc"] = app_args_count - - if (verbosity > 0): - print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") - arg_start = 1 - for next_arg in app_args_list: - if (verbosity > 0): - print("arg" + str(arg_start) + " = " + next_arg) - app_params["arg" + str(arg_start)] = next_arg - arg_start = arg_start + 1 -else: - app_params["argc"] = 1 - if (verbosity > 0): - print("No application arguments found, continuing with argc=1") - -vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" -vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" - - -protocol="MESI" - -# OS related params -osParams = { - "processDebugLevel" : 0, - "dbgLevel" : os_verbosity, - "dbgMask" : 8, - "cores" : numCpus, - "hardwareThreadCount" : numThreads, - "page_size" : 4096, - "physMemSize" : physMemSize, - "useMMU" : True, - "checkpointDir" : checkpointDir, - "checkpoint" : checkpoint -} - -processList = ( - ( 1, { - "env_count" : 1, - "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), - "exe" : full_exe_name, - "arg0" : exe_name, - } ), -) - -processList[0][1].update(app_params) - -osl1cacheParams = { - "access_latency_cycles" : "2", - "cache_frequency" : cpu_clock, - "replacement_policy" : "lru", - "coherence_protocol" : protocol, - "associativity" : "8", - "cache_line_size" : "64", - "cache_size" : "32 KB", - "L1" : "1", - "debug" : mh_debug, - "debug_level" : mh_debug_level, -} - -mmuParams = { - "debug_level": 0, - "num_cores": numCpus, - "num_threads": numThreads, - "page_size": 4096, -} - -memRtrParams ={ - "xbar_bw" : "1GB/s", - "link_bw" : "1GB/s", - "input_buf_size" : "2KB", - "num_ports" : str(numCpus+2), - "flit_size" : "72B", - "output_buf_size" : "2KB", - "id" : "0", - "topology" : "merlin.singlerouter" -} - -dirCtrlParams = { - "coherence_protocol" : protocol, - "entry_cache_size" : "1024", - "debug" : mh_debug, - "debug_level" : mh_debug_level, - "addr_range_start" : "0x0", - "addr_range_end" : "0xFFFFFFFF" -} - -dirNicParams = { - "network_bw" : "25GB/s", - "group" : 2, -} - -memCtrlParams = { - "clock" : cpu_clock, - "backend.mem_size" : physMemSize, - "backing" : "malloc", - "initBacking": 1, - "addr_range_start": 0, - "addr_range_end": 0xffffffff, - "debug_level" : mh_debug_level, - "debug" : mh_debug, - "checkpointDir" : checkpointDir, - "checkpoint" : checkpoint -} - -memParams = { - "mem_size" : "4GiB", - "access_time" : "1 ns" -} - -# CPU related params -tlbParams = { - "debug_level": 0, - "hitLatency": 1, - "num_hardware_threads": numThreads, - "num_tlb_entries_per_thread": 64, - "tlb_set_size": 4, -} - -tlbWrapperParams = { - "debug_level": 0, -} - -decoderParams = { - "loader_mode" : loader_mode, - "uop_cache_entries" : 1536, - "predecode_cache_entries" : 4 -} - -osHdlrParams = { } - -branchPredParams = { - "branch_entries" : 32 -} - -cpuParams = { - "clock" : cpu_clock, - "verbose" : verbosity, - "hardware_threads": numThreads, - "physical_fp_registers" : 168 * numThreads, - "physical_integer_registers" : 180 * numThreads, - "integer_arith_cycles" : integer_arith_cycles, - "integer_arith_units" : integer_arith_units, - "fp_arith_cycles" : fp_arith_cycles, - "fp_arith_units" : fp_arith_units, - "branch_unit_cycles" : branch_arith_cycles, - "print_int_reg" : False, - "print_fp_reg" : False, - "pipeline_trace_file" : pipe_trace_file, - "reorder_slots" : rob_slots, - "decodes_per_cycle" : decodes_per_cycle, - "issues_per_cycle" : issues_per_cycle, - "retires_per_cycle" : retires_per_cycle, - "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), - "start_verbose_when_issue_address": dbgAddr, - "stop_verbose_when_retire_address": stopDbg, - "print_rob" : False, - "checkpointDir" : checkpointDir, - "checkpoint" : checkpoint -} - -lsqParams = { - "verbose" : verbosity, - "address_mask" : 0xFFFFFFFF, - "max_stores" : lsq_st_entries, - "max_loads" : lsq_ld_entries, -} - -l1dcacheParams = { - "access_latency_cycles" : "2", - "cache_frequency" : cpu_clock, - "replacement_policy" : "lru", - "coherence_protocol" : protocol, - "associativity" : "8", - "cache_line_size" : "64", - "cache_size" : "32 KB", - "L1" : "1", - "debug" : mh_debug, - "debug_level" : mh_debug_level, -} - -l1icacheParams = { - "access_latency_cycles" : "2", - "cache_frequency" : cpu_clock, - "replacement_policy" : "lru", - "coherence_protocol" : protocol, - "associativity" : "8", - "cache_line_size" : "64", - "cache_size" : "32 KB", - "prefetcher" : "cassini.NextBlockPrefetcher", - "prefetcher.reach" : 1, - "L1" : "1", - "debug" : mh_debug, - "debug_level" : mh_debug_level, -} - -l2cacheParams = { - "access_latency_cycles" : "14", - "cache_frequency" : cpu_clock, - "replacement_policy" : "lru", - "coherence_protocol" : protocol, - "associativity" : "16", - "cache_line_size" : "64", - "cache_size" : "1MB", - "mshr_latency_cycles": 3, - "debug" : mh_debug, - "debug_level" : mh_debug_level, -} -busParams = { - "bus_frequency" : cpu_clock, -} - -l2memLinkParams = { - "group" : 1, - "network_bw" : "25GB/s" -} - -class CPU_Builder: - def __init__(self): - pass - - # CPU - def build( self, prefix, nodeId, cpuId ): - - if pythonDebug: - print("build {}".format(prefix) ) - - # CPU - cpu = sst.Component(prefix, vanadis_cpu_type) - cpu.addParams( cpuParams ) - cpu.addParam( "core_id", cpuId ) - cpu.enableAllStatistics() - - # CPU.decoder - for n in range(numThreads): - decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) - decode.addParams( decoderParams ) - - decode.enableAllStatistics() - - # CPU.decoder.osHandler - os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) - os_hdlr.addParams( osHdlrParams ) - - # CPU.decocer.branch_pred - branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) - branch_pred.addParams( branchPredParams ) - branch_pred.enableAllStatistics() - - # CPU.lsq - cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) - cpu_lsq.addParams(lsqParams) - cpu_lsq.enableAllStatistics() - - # CPU.lsq mem interface which connects to D-cache - cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) - - # CPU.mem interface for I-cache - cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) - - # L1 D-cache - cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") - cpu_l1dcache.addParams( l1dcacheParams ) - - # L2 I-cache - cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") - cpu_l1icache.addParams( l1icacheParams ) - - # L2 cache - cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") - cpu_l2cache.addParams( l2cacheParams ) - - # L2 cache mem interface - l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") - l2cache_2_mem.addParams( l2memLinkParams ) - - # L1 to L2 buss - cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") - cache_bus.addParams(busParams) - - # CPU data TLB - dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") - dtlbWrapper.addParams(tlbWrapperParams) -# dtlbWrapper.addParam( "debug_level", 0) - dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); - dtlb.addParams(tlbParams) - - # CPU instruction TLB - itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") - itlbWrapper.addParams(tlbWrapperParams) -# itlbWrapper.addParam( "debug_level", 0) - itlbWrapper.addParam("exe",True) - itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); - itlb.addParams(tlbParams) - - # CPU (data) -> TLB -> Cache - link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") - link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) - link_cpu_dtlb_link.setNoCut() - - # data TLB -> data L1 - link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") - link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) - link_cpu_l1dcache_link.setNoCut() - - # CPU (instruction) -> TLB -> Cache - link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") - link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) - link_cpu_itlb_link.setNoCut() - - # instruction TLB -> instruction L1 - link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") - link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) - link_cpu_l1icache_link.setNoCut(); - - # data L1 -> bus - link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") - link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) - link_l1dcache_l2cache_link.setNoCut() - - # instruction L1 -> bus - link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") - link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) - link_l1icache_l2cache_link.setNoCut() - - # BUS to L2 cache - link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") - link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) - link_bus_l2cache_link.setNoCut() - - return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") - - -def addParamsPrefix(prefix,params): - #print( prefix ) - ret = {} - for key, value in params.items(): - #print( key, value ) - ret[ prefix + "." + key] = value - - #print( ret ) - return ret - -# node OS -node_os = sst.Component("os", "vanadis.VanadisNodeOS") -node_os.addParams(osParams) - -num=0 -for i,process in processList: - #print( process ) - for y in range(i): - #print( "process", num ) - node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) - num+=1 - -if pythonDebug: - print('total hardware threads ' + str(num) ) - -# node OS MMU -node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) -node_os_mmu.addParams(mmuParams) - -# node OS memory interface to L1 data cache -node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) - -# node OS l1 data cache -os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") -os_cache.addParams(osl1cacheParams) -os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") -os_cache_2_mem.addParams( l2memLinkParams ) - -# node memory router -comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") -comp_chiprtr.addParams(memRtrParams) -comp_chiprtr.setSubComponent("topology","merlin.singlerouter") - -# node directory controller -dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") -dirctrl.addParams(dirCtrlParams) - -# node directory controller port to cpu -dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") -dirNIC.addParams(dirNicParams) - -# node memory controller -memctrl = sst.Component("memory", "memHierarchy.MemController") -memctrl.addParams( memCtrlParams ) -memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, - "regions": ["4D88, 4D90", "4DA0, 4DA8"], - "debug" : 1, - "debug_level": 2 -}) - -# node memory controller backend -memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") -memory.addParams(memParams) - -# node OS data TLB -#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") -#ostlbWrapper.addParams(tlbWrapperParams) -#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); -#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); -#ostlb.addParams(tlbParams) - -# OS (data) -> TLB -> Cache -#link_os_ostlb_link = sst.Link("link_os_ostlb_link") -#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) - -# Directory controller to memory router -link_dir_2_rtr = sst.Link("link_dir_2_rtr") -link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) -link_dir_2_rtr.setNoCut() - -# Directory controller to memory controller -link_dir_2_mem = sst.Link("link_dir_2_mem") -link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) -link_dir_2_mem.setNoCut() - -# MMU -> ostlb -# don't need when using pass through TLB -#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") -#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) - -# ostlb -> os l1 cache -link_os_cache_link = sst.Link("link_os_cache_link") -#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) -link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) -link_os_cache_link.setNoCut() - -os_cache_2_rtr = sst.Link("os_cache_2_rtr") -os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) -os_cache_2_rtr.setNoCut() - -cpuBuilder = CPU_Builder() - -# build all CPUs -nodeId = 0 -for cpu in range(numCpus): - - prefix="node" + str(nodeId) + ".cpu" + str(cpu) - os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - - # MMU -> dtlb - link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") - link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - - # MMU -> itlb - link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") - link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - - # CPU os handler -> node OS - link_core_os_link = sst.Link(prefix + ".link_core_os_link") - link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) - - # connect cpu L2 to router - link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") - link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) - From be41c665cb9ce35aeb68fd47a33be91bef3877d8 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 20:41:47 -0400 Subject: [PATCH 36/45] randomFlip and randomDrop tests added rng hooks in FaultInjectorBase expanded to include every usage without later faults or injectors needing their own need to figure out how to delay injection so that it doesn't occur when sst initialization is still occurring --- src/sst/elements/carcosa/faultInjectorBase.cc | 25 + src/sst/elements/carcosa/faultInjectorBase.h | 7 + .../carcosa/faultlogic/corruptMemFault.cc | 3 +- .../carcosa/faultlogic/corruptMemFault.h | 3 - .../carcosa/faultlogic/randomFlipFault.cc | 12 +- .../carcosa/faultlogic/randomFlipFault.h | 5 +- .../tests/testCorruptMemDoubleOverlap.py | 1 + .../elements/carcosa/tests/testRandomDrop.py | 571 +++++++++++++++++ .../elements/carcosa/tests/testRandomFlip.py | 571 +++++++++++++++++ .../carcosa/tests/testStuckAtBasic.py | 571 +++++++++++++++++ .../carcosa/tests/testStuckAtMultiple.py | 572 ++++++++++++++++++ .../carcosa/tests/testStuckAtOverlap.py | 572 ++++++++++++++++++ .../carcosa/tests/testStuckAtSameByte.py | 572 ++++++++++++++++++ 13 files changed, 3470 insertions(+), 15 deletions(-) create mode 100644 src/sst/elements/carcosa/tests/testRandomDrop.py create mode 100644 src/sst/elements/carcosa/tests/testRandomFlip.py create mode 100644 src/sst/elements/carcosa/tests/testStuckAtBasic.py create mode 100644 src/sst/elements/carcosa/tests/testStuckAtMultiple.py create mode 100644 src/sst/elements/carcosa/tests/testStuckAtOverlap.py create mode 100644 src/sst/elements/carcosa/tests/testStuckAtSameByte.py diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index a102fea351..d78012a882 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -91,6 +91,31 @@ FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) #endif } +uint32_t FaultInjectorBase::randUInt32(uint32_t start, uint32_t end) { + uint32_t range = end - start; + return start + (base_rng_.generateNextUInt32() % range); +} + +int32_t FaultInjectorBase::randInt32(int32_t start, int32_t end) { + int32_t range = end - start; + return start + (base_rng_.generateNextInt32() % range); +} + +uint64_t FaultInjectorBase::randUInt64(uint64_t start, uint64_t end) { + uint64_t range = end - start; + return start + (base_rng_.generateNextUInt64() % range); +} + +int64_t FaultInjectorBase::randInt64(int64_t start, int64_t end) { + int64_t range = end - start; + return start + (base_rng_.generateNextInt64() % range); +} + +double FaultInjectorBase::randFloat(double start, double end) { + double range = end - start; + return start + (base_rng_.nextUniform() * range); +} + bool FaultInjectorBase::doInjection() { double rand_val = base_rng_.nextUniform(); return rand_val <= getInjectionProb(); diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 9487e314d3..2c8671f25a 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -129,6 +129,13 @@ class FaultInjectorBase : public SST::PortModule return dbg_; } + uint32_t randUInt32(uint32_t start, uint32_t end); + int32_t randInt32(int32_t start, int32_t end); + uint64_t randUInt64(uint64_t start, uint64_t end); + int64_t randInt64(int64_t start, int64_t end); + + double randFloat(double start, double end); + protected: SST::Output* out_; SST::Output* dbg_; diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index fdfb26d5b4..56e27c5436 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -62,7 +62,7 @@ bool CorruptMemFault::faultLogic(Event*& ev) { if ((i < start) || (i > end)) { new_payload[i] = original_payload[i]; } else if ((i >= start) && (i <= end)) { - new_payload[i] = static_cast(rng_.generateNextUInt32() % 255); + new_payload[i] = static_cast(injector_->randUInt32(0,255)); } } setMemEventPayload(ev, new_payload); @@ -112,7 +112,6 @@ int32_t CorruptMemFault::computeEndIndex(Addr base_addr, size_t payload_sz, Addr return -1; } -// TODO: why is this triggering a push_back on 0x4D80 from payload 0x4d40? std::vector* CorruptMemFault::checkAddrUsage(Event*& ev) { Addr base_addr = convertMemEvent(ev)->getBaseAddr(); for (int i = 0; i < corruptionRegions_.size(); i++) { diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index 2d5fc97909..f5e6241de2 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -53,8 +53,6 @@ class CorruptMemFault : public FaultBase std::vector> corruptionRegions_; - SST::RNG::MersenneRNG rng_; - std::vector regionsToUse_; std::pair convertString(std::string& region); @@ -65,7 +63,6 @@ class CorruptMemFault : public FaultBase void serialize_order(SST::Core::Serialization::serializer& ser) override { FaultBase::serialize_order(ser); SST_SER(corruptionRegions_); - SST_SER(rng_); SST_SER(regionsToUse_); } ImplementVirtualSerializable(CorruptMemFault) diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc index 2ac59e437a..48da3c7ea7 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.cc @@ -14,13 +14,13 @@ using namespace SST::Carcosa; RandomFlipFault::RandomFlipFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { - this->int_distribution = uniform_int_distribution(0,8); + // } bool RandomFlipFault::faultLogic(Event*& ev) { // check if this is the proper event type and get payload if it is dataVec payload = getMemEventPayload(ev); - std::pair lucky_number = pickByteAndBit(); + std::pair lucky_number = pickByteAndBit(payload.size()); uint8_t byte = payload[lucky_number.first]; uint8_t mask = static_cast(1) << (lucky_number.second); payload[lucky_number.first] = byte ^ mask; @@ -28,11 +28,11 @@ bool RandomFlipFault::faultLogic(Event*& ev) { return true; } -inline std::pair RandomFlipFault::pickByteAndBit() { - uint32_t byte = int_distribution(int_generator); - uint32_t bit = int_distribution(int_generator); +inline std::pair RandomFlipFault::pickByteAndBit(size_t payload_sz) { + uint32_t byte = injector_->randUInt32(0, payload_sz); + uint32_t bit = injector_->randUInt32(0, 8); #ifdef __SST_DEBUG_OUTPUT__ - getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Flipping bit %d in byte %d.\n", (int)bit, (int)byte); + getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Flipping bit %u in byte %u.\n", (uint32_t)bit, (uint32_t)byte); #endif return make_pair(byte, bit); } \ No newline at end of file diff --git a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h index 881b05331f..0ddd02ee63 100644 --- a/src/sst/elements/carcosa/faultlogic/randomFlipFault.h +++ b/src/sst/elements/carcosa/faultlogic/randomFlipFault.h @@ -25,14 +25,11 @@ class RandomFlipFault : public FaultBase { bool faultLogic(Event*& ev) override; protected: - std::default_random_engine int_generator; - std::uniform_int_distribution int_distribution; - /** * Randomly choose which bit in which byte to flip * @return (byte, bit) */ - inline std::pair pickByteAndBit(); + inline std::pair pickByteAndBit(size_t payload_sz); protected: void serialize_order(SST::Core::Serialization::serializer& ser) override { FaultBase::serialize_order(ser); diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py index f36238219a..ca1d629e8c 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py @@ -496,6 +496,7 @@ def addParamsPrefix(prefix,params): # node memory controller memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) +#TODO: fix bug here :) memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { "intallDirection": "Receive", "injectionProbability": 1.0, diff --git a/src/sst/elements/carcosa/tests/testRandomDrop.py b/src/sst/elements/carcosa/tests/testRandomDrop.py new file mode 100644 index 0000000000..decb949f7a --- /dev/null +++ b/src/sst/elements/carcosa/tests/testRandomDrop.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +# SHOULD FAIL TO INITIALIZE +memctrl.addPortModule("highlink", "carcosa.RandomDropFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 0.25, + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testRandomFlip.py b/src/sst/elements/carcosa/tests/testRandomFlip.py new file mode 100644 index 0000000000..671f9f8311 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testRandomFlip.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +# SHOULD FAIL TO INITIALIZE +memctrl.addPortModule("highlink", "carcosa.RandomFlipFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 0.25, + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testStuckAtBasic.py b/src/sst/elements/carcosa/tests/testStuckAtBasic.py new file mode 100644 index 0000000000..3d5674f9ff --- /dev/null +++ b/src/sst/elements/carcosa/tests/testStuckAtBasic.py @@ -0,0 +1,571 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "masks": ["4D88, 3, 11110000, 00001111"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testStuckAtMultiple.py b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py new file mode 100644 index 0000000000..97ec194650 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py @@ -0,0 +1,572 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +# SHOULD FAIL TO INITIALIZE +memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "masks": ["4D88, 3, 11110000, 00001111", "4D90, 3, 11110000, 00001111"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testStuckAtOverlap.py b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py new file mode 100644 index 0000000000..c553a699a3 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py @@ -0,0 +1,572 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +# SHOULD FAIL TO INITIALIZE +memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "masks": ["4D88, 3, 11111111, 11111111"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + diff --git a/src/sst/elements/carcosa/tests/testStuckAtSameByte.py b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py new file mode 100644 index 0000000000..d5d61f5ad5 --- /dev/null +++ b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py @@ -0,0 +1,572 @@ +import os +import sst +mh_debug_level=10 +mh_debug=0 +# this has to be a string +dbgAddr="0" +stopDbg="0" + +checkpointDir = "" +checkpoint = "" + +#checkpointDir = "checkpoint0" +#checkpoint = "load" +#checkpoint = "save" + +pythonDebug=False + +vanadis_isa = os.getenv("VANADIS_ISA", "MIPS") +isa="mipsel" +vanadis_isa = os.getenv("VANADIS_ISA", "RISCV64") +isa="riscv64" + +loader_mode = os.getenv("VANADIS_LOADER_MODE", "0") + +testDir="basic-io" +exe = "hello-world" +#exe = "hello-world-cpp" +#exe = "openat" +#exe = "printf-check" +#exe = "read-write" +#exe = "fread-fwrite" +#exe = "unlink" +#exe = "unlinkat" +#exe = "lseek" + +#testDir = "basic-math" +#exe = "sqrt-double" +#exe = "sqrt-float" + +#testDir = "basic-ops" +#exe = "test-branch" +#exe = "test-shift" + +#testDir = "misc" +#exe = "mt-dgemm" +#exe = "stream" +#exe = "stream-fortran" +#exe = "gettime" +#exe = "splitLoad" +#exe = "fork" +#exe = "clone" +#exe = "pthread" +#exe = "openmp" +#exe = "openmp2" +#exe = "uname" +#exe = "mem-test" +#exe = "checkpoint" + +physMemSize = "4GiB" + +tlbType = "simpleTLB" +mmuType = "simpleMMU" + +# Define SST core options +sst.setProgramOption("timebase", "1ps") +sst.setProgramOption("stop-at", "0 ns") + +# Tell SST what statistics handling we want +sst.setStatisticLoadLevel(4) +sst.setStatisticOutput("sst.statOutputConsole") + +full_exe_name = "../../vanadis/tests/small/basic-math/sqrt-double/riscv64/sqrt-double"#os.getenv("VANADIS_EXE", "./small/" + testDir + "/" + exe + "/" + isa + "/" + exe ) +exe_name= full_exe_name.split("/")[-1] + +verbosity = int(os.getenv("VANADIS_VERBOSE", 0)) +os_verbosity = os.getenv("VANADIS_OS_VERBOSE", verbosity) +pipe_trace_file = os.getenv("VANADIS_PIPE_TRACE", "") +lsq_ld_entries = os.getenv("VANADIS_LSQ_LD_ENTRIES", 16) +lsq_st_entries = os.getenv("VANADIS_LSQ_ST_ENTRIES", 8) + +rob_slots = os.getenv("VANADIS_ROB_SLOTS", 64) +retires_per_cycle = os.getenv("VANADIS_RETIRES_PER_CYCLE", 4) +issues_per_cycle = os.getenv("VANADIS_ISSUES_PER_CYCLE", 4) +decodes_per_cycle = os.getenv("VANADIS_DECODES_PER_CYCLE", 4) + +integer_arith_cycles = int(os.getenv("VANADIS_INTEGER_ARITH_CYCLES", 2)) +integer_arith_units = int(os.getenv("VANADIS_INTEGER_ARITH_UNITS", 2)) +fp_arith_cycles = int(os.getenv("VANADIS_FP_ARITH_CYCLES", 8)) +fp_arith_units = int(os.getenv("VANADIS_FP_ARITH_UNITS", 2)) +branch_arith_cycles = int(os.getenv("VANADIS_BRANCH_ARITH_CYCLES", 2)) + +cpu_clock = os.getenv("VANADIS_CPU_CLOCK", "2.3GHz") + +numCpus = int(os.getenv("VANADIS_NUM_CORES", 1)) +numThreads = int(os.getenv("VANADIS_NUM_HW_THREADS", 1)) + +vanadis_cpu_type = "vanadis." +vanadis_cpu_type += os.getenv("VANADIS_CPU_ELEMENT_NAME","dbg_VanadisCPU") + +if (verbosity > 0): + print("Verbosity: " + str(verbosity) + " -> loading Vanadis CPU type: " + vanadis_cpu_type) + print("Auto-clock syscalls: " + str(auto_clock_sys)) +# vanadis_cpu_type = "vanadisdbg.VanadisCPU" + +app_args = os.getenv("VANADIS_EXE_ARGS", "") + +app_params = {} +if app_args != "": + app_args_list = app_args.split(" ") + # We have a plus 1 because the executable name is arg0 + app_args_count = len( app_args_list ) + 1 + + app_params["argc"] = app_args_count + + if (verbosity > 0): + print("Identified " + str(app_args_count) + " application arguments, adding to input parameters.") + arg_start = 1 + for next_arg in app_args_list: + if (verbosity > 0): + print("arg" + str(arg_start) + " = " + next_arg) + app_params["arg" + str(arg_start)] = next_arg + arg_start = arg_start + 1 +else: + app_params["argc"] = 1 + if (verbosity > 0): + print("No application arguments found, continuing with argc=1") + +vanadis_decoder = "vanadis.Vanadis" + vanadis_isa + "Decoder" +vanadis_os_hdlr = "vanadis.Vanadis" + vanadis_isa + "OSHandler" + + +protocol="MESI" + +# OS related params +osParams = { + "processDebugLevel" : 0, + "dbgLevel" : os_verbosity, + "dbgMask" : 8, + "cores" : numCpus, + "hardwareThreadCount" : numThreads, + "page_size" : 4096, + "physMemSize" : physMemSize, + "useMMU" : True, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +processList = ( + ( 1, { + "env_count" : 1, + "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), + "exe" : full_exe_name, + "arg0" : exe_name, + } ), +) + +processList[0][1].update(app_params) + +osl1cacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +mmuParams = { + "debug_level": 0, + "num_cores": numCpus, + "num_threads": numThreads, + "page_size": 4096, +} + +memRtrParams ={ + "xbar_bw" : "1GB/s", + "link_bw" : "1GB/s", + "input_buf_size" : "2KB", + "num_ports" : str(numCpus+2), + "flit_size" : "72B", + "output_buf_size" : "2KB", + "id" : "0", + "topology" : "merlin.singlerouter" +} + +dirCtrlParams = { + "coherence_protocol" : protocol, + "entry_cache_size" : "1024", + "debug" : mh_debug, + "debug_level" : mh_debug_level, + "addr_range_start" : "0x0", + "addr_range_end" : "0xFFFFFFFF" +} + +dirNicParams = { + "network_bw" : "25GB/s", + "group" : 2, +} + +memCtrlParams = { + "clock" : cpu_clock, + "backend.mem_size" : physMemSize, + "backing" : "malloc", + "initBacking": 1, + "addr_range_start": 0, + "addr_range_end": 0xffffffff, + "debug_level" : mh_debug_level, + "debug" : mh_debug, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +memParams = { + "mem_size" : "4GiB", + "access_time" : "1 ns" +} + +# CPU related params +tlbParams = { + "debug_level": 0, + "hitLatency": 1, + "num_hardware_threads": numThreads, + "num_tlb_entries_per_thread": 64, + "tlb_set_size": 4, +} + +tlbWrapperParams = { + "debug_level": 0, +} + +decoderParams = { + "loader_mode" : loader_mode, + "uop_cache_entries" : 1536, + "predecode_cache_entries" : 4 +} + +osHdlrParams = { } + +branchPredParams = { + "branch_entries" : 32 +} + +cpuParams = { + "clock" : cpu_clock, + "verbose" : verbosity, + "hardware_threads": numThreads, + "physical_fp_registers" : 168 * numThreads, + "physical_integer_registers" : 180 * numThreads, + "integer_arith_cycles" : integer_arith_cycles, + "integer_arith_units" : integer_arith_units, + "fp_arith_cycles" : fp_arith_cycles, + "fp_arith_units" : fp_arith_units, + "branch_unit_cycles" : branch_arith_cycles, + "print_int_reg" : False, + "print_fp_reg" : False, + "pipeline_trace_file" : pipe_trace_file, + "reorder_slots" : rob_slots, + "decodes_per_cycle" : decodes_per_cycle, + "issues_per_cycle" : issues_per_cycle, + "retires_per_cycle" : retires_per_cycle, + "pause_when_retire_address" : os.getenv("VANADIS_HALT_AT_ADDRESS", 0), + "start_verbose_when_issue_address": dbgAddr, + "stop_verbose_when_retire_address": stopDbg, + "print_rob" : False, + "checkpointDir" : checkpointDir, + "checkpoint" : checkpoint +} + +lsqParams = { + "verbose" : verbosity, + "address_mask" : 0xFFFFFFFF, + "max_stores" : lsq_st_entries, + "max_loads" : lsq_ld_entries, +} + +l1dcacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l1icacheParams = { + "access_latency_cycles" : "2", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "8", + "cache_line_size" : "64", + "cache_size" : "32 KB", + "prefetcher" : "cassini.NextBlockPrefetcher", + "prefetcher.reach" : 1, + "L1" : "1", + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} + +l2cacheParams = { + "access_latency_cycles" : "14", + "cache_frequency" : cpu_clock, + "replacement_policy" : "lru", + "coherence_protocol" : protocol, + "associativity" : "16", + "cache_line_size" : "64", + "cache_size" : "1MB", + "mshr_latency_cycles": 3, + "debug" : mh_debug, + "debug_level" : mh_debug_level, +} +busParams = { + "bus_frequency" : cpu_clock, +} + +l2memLinkParams = { + "group" : 1, + "network_bw" : "25GB/s" +} + +class CPU_Builder: + def __init__(self): + pass + + # CPU + def build( self, prefix, nodeId, cpuId ): + + if pythonDebug: + print("build {}".format(prefix) ) + + # CPU + cpu = sst.Component(prefix, vanadis_cpu_type) + cpu.addParams( cpuParams ) + cpu.addParam( "core_id", cpuId ) + cpu.enableAllStatistics() + + # CPU.decoder + for n in range(numThreads): + decode = cpu.setSubComponent( "decoder"+str(n), vanadis_decoder ) + decode.addParams( decoderParams ) + + decode.enableAllStatistics() + + # CPU.decoder.osHandler + os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) + os_hdlr.addParams( osHdlrParams ) + + # CPU.decocer.branch_pred + branch_pred = decode.setSubComponent( "branch_unit", "vanadis.VanadisBasicBranchUnit" ) + branch_pred.addParams( branchPredParams ) + branch_pred.enableAllStatistics() + + # CPU.lsq + cpu_lsq = cpu.setSubComponent( "lsq", "vanadis.VanadisBasicLoadStoreQueue" ) + cpu_lsq.addParams(lsqParams) + cpu_lsq.enableAllStatistics() + + # CPU.lsq mem interface which connects to D-cache + cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) + + # CPU.mem interface for I-cache + cpuIcacheIf = cpu.setSubComponent( "mem_interface_inst", "memHierarchy.standardInterface" ) + + # L1 D-cache + cpu_l1dcache = sst.Component(prefix + ".l1dcache", "memHierarchy.Cache") + cpu_l1dcache.addParams( l1dcacheParams ) + + # L2 I-cache + cpu_l1icache = sst.Component( prefix + ".l1icache", "memHierarchy.Cache") + cpu_l1icache.addParams( l1icacheParams ) + + # L2 cache + cpu_l2cache = sst.Component(prefix+".l2cache", "memHierarchy.Cache") + cpu_l2cache.addParams( l2cacheParams ) + + # L2 cache mem interface + l2cache_2_mem = cpu_l2cache.setSubComponent("lowlink", "memHierarchy.MemNIC") + l2cache_2_mem.addParams( l2memLinkParams ) + + # L1 to L2 buss + cache_bus = sst.Component(prefix+".bus", "memHierarchy.Bus") + cache_bus.addParams(busParams) + + # CPU data TLB + dtlbWrapper = sst.Component(prefix+".dtlb", "mmu.tlb_wrapper") + dtlbWrapper.addParams(tlbWrapperParams) +# dtlbWrapper.addParam( "debug_level", 0) + dtlb = dtlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + dtlb.addParams(tlbParams) + + # CPU instruction TLB + itlbWrapper = sst.Component(prefix+".itlb", "mmu.tlb_wrapper") + itlbWrapper.addParams(tlbWrapperParams) +# itlbWrapper.addParam( "debug_level", 0) + itlbWrapper.addParam("exe",True) + itlb = itlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); + itlb.addParams(tlbParams) + + # CPU (data) -> TLB -> Cache + link_cpu_dtlb_link = sst.Link(prefix+".link_cpu_dtlb_link") + link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) + link_cpu_dtlb_link.setNoCut() + + # data TLB -> data L1 + link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") + link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) + link_cpu_l1dcache_link.setNoCut() + + # CPU (instruction) -> TLB -> Cache + link_cpu_itlb_link = sst.Link(prefix+".link_cpu_itlb_link") + link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) + link_cpu_itlb_link.setNoCut() + + # instruction TLB -> instruction L1 + link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") + link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) + link_cpu_l1icache_link.setNoCut(); + + # data L1 -> bus + link_l1dcache_l2cache_link = sst.Link(prefix+".link_l1dcache_l2cache_link") + link_l1dcache_l2cache_link.connect( (cpu_l1dcache, "lowlink", "1ns"), (cache_bus, "highlink0", "1ns") ) + link_l1dcache_l2cache_link.setNoCut() + + # instruction L1 -> bus + link_l1icache_l2cache_link = sst.Link(prefix+".link_l1icache_l2cache_link") + link_l1icache_l2cache_link.connect( (cpu_l1icache, "lowlink", "1ns"), (cache_bus, "highlink1", "1ns") ) + link_l1icache_l2cache_link.setNoCut() + + # BUS to L2 cache + link_bus_l2cache_link = sst.Link(prefix+".link_bus_l2cache_link") + link_bus_l2cache_link.connect( (cache_bus, "lowlink0", "1ns"), (cpu_l2cache, "highlink", "1ns") ) + link_bus_l2cache_link.setNoCut() + + return (cpu, "os_link", "5ns"), (l2cache_2_mem, "port", "1ns") , (dtlb, "mmu", "1ns"), (itlb, "mmu", "1ns") + + +def addParamsPrefix(prefix,params): + #print( prefix ) + ret = {} + for key, value in params.items(): + #print( key, value ) + ret[ prefix + "." + key] = value + + #print( ret ) + return ret + +# node OS +node_os = sst.Component("os", "vanadis.VanadisNodeOS") +node_os.addParams(osParams) + +num=0 +for i,process in processList: + #print( process ) + for y in range(i): + #print( "process", num ) + node_os.addParams( addParamsPrefix( "process" + str(num), process ) ) + num+=1 + +if pythonDebug: + print('total hardware threads ' + str(num) ) + +# node OS MMU +node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) +node_os_mmu.addParams(mmuParams) + +# node OS memory interface to L1 data cache +node_os_mem_if = node_os.setSubComponent( "mem_interface", "memHierarchy.standardInterface" ) + +# node OS l1 data cache +os_cache = sst.Component("node_os.cache", "memHierarchy.Cache") +os_cache.addParams(osl1cacheParams) +os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") +os_cache_2_mem.addParams( l2memLinkParams ) + +# node memory router +comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") +comp_chiprtr.addParams(memRtrParams) +comp_chiprtr.setSubComponent("topology","merlin.singlerouter") + +# node directory controller +dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") +dirctrl.addParams(dirCtrlParams) + +# node directory controller port to cpu +dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") +dirNIC.addParams(dirNicParams) + +# node memory controller +memctrl = sst.Component("memory", "memHierarchy.MemController") +memctrl.addParams( memCtrlParams ) +# SHOULD FAIL TO INITIALIZE +memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { + "intallDirection": "Receive", + "injectionProbability": 1.0, + "masks": ["4D88, 3, 11110000, 00001111", "4D88, 5, 11110000, 00001111"], + "debug" : 1, + "debug_level": 2 +}) + +# node memory controller backend +memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") +memory.addParams(memParams) + +# node OS data TLB +#ostlbWrapper = sst.Component("ostlb", "mmu.tlb_wrapper") +#ostlbWrapper.addParams(tlbWrapperParams) +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu." + tlbType ); +#ostlb = ostlbWrapper.setSubComponent("tlb", "mmu.passThroughTLB" ); +#ostlb.addParams(tlbParams) + +# OS (data) -> TLB -> Cache +#link_os_ostlb_link = sst.Link("link_os_ostlb_link") +#link_os_ostlb_link.connect( (node_os_mem_if, "lowlink", "1ns"), (ostlbWrapper, "cpu_if", "1ns") ) + +# Directory controller to memory router +link_dir_2_rtr = sst.Link("link_dir_2_rtr") +link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) +link_dir_2_rtr.setNoCut() + +# Directory controller to memory controller +link_dir_2_mem = sst.Link("link_dir_2_mem") +link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) +link_dir_2_mem.setNoCut() + +# MMU -> ostlb +# don't need when using pass through TLB +#link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") +#link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) + +# ostlb -> os l1 cache +link_os_cache_link = sst.Link("link_os_cache_link") +#link_os_cache_link.connect( (ostlbWrapper, "cache_if", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.connect( (node_os_mem_if, "lowlink", "1ns"), (os_cache, "highlink", "1ns") ) +link_os_cache_link.setNoCut() + +os_cache_2_rtr = sst.Link("os_cache_2_rtr") +os_cache_2_rtr.connect( (os_cache_2_mem, "port", "1ns"), (comp_chiprtr, "port"+str(numCpus+1), "1ns") ) +os_cache_2_rtr.setNoCut() + +cpuBuilder = CPU_Builder() + +# build all CPUs +nodeId = 0 +for cpu in range(numCpus): + + prefix="node" + str(nodeId) + ".cpu" + str(cpu) + os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) + + # MMU -> dtlb + link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") + link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) + + # MMU -> itlb + link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") + link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) + + # CPU os handler -> node OS + link_core_os_link = sst.Link(prefix + ".link_core_os_link") + link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) + + # connect cpu L2 to router + link_l2cache_2_rtr = sst.Link(prefix + ".link_l2cache_2_rtr") + link_l2cache_2_rtr.connect( l2cache, (comp_chiprtr, "port" + str(cpu), "1ns") ) + From 272f66d8db144598ffdd1410ee574818e63d6178 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 20:43:28 -0400 Subject: [PATCH 37/45] randomDrop ELI fixed --- src/sst/elements/carcosa/injectors/randomDropFaultInjector.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index ee6b7f2af2..7b937d1774 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -21,7 +21,7 @@ class RandomDropFaultInjector : public FaultInjectorBase { SST_ELI_REGISTER_PORTMODULE( RandomDropFaultInjector, "carcosa", - "RandomFlipFaultInjector", + "RandomDropFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), "PortModule class used to simulate a data transfer lost at random" ) From 6062ef52303d594c1b2627fb740c6752f751f860 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 21:00:03 -0400 Subject: [PATCH 38/45] corruptMem index computation fixed and corruption slightly optimized --- .../carcosa/faultlogic/corruptMemFault.cc | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index 56e27c5436..f1c43c26f5 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -46,6 +46,7 @@ bool CorruptMemFault::faultLogic(Event*& ev) { Addr base_addr = mem_ev->getBaseAddr(); dataVec original_payload = mem_ev->getPayload(); + dataVec new_payload(original_payload); for (int r: regionsToUse_) { auto& region = corruptionRegions_[r]; size_t payload_sz = mem_ev->getPayloadSize(); @@ -57,17 +58,11 @@ bool CorruptMemFault::faultLogic(Event*& ev) { if (end < 0) { getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "No valid start index for corruption.\n"); } - dataVec new_payload(payload_sz); - for (int i = 0; i < payload_sz; i++) { - if ((i < start) || (i > end)) { - new_payload[i] = original_payload[i]; - } else if ((i >= start) && (i <= end)) { - new_payload[i] = static_cast(injector_->randUInt32(0,255)); - } + for (int i = start; i < end; i++) { + new_payload[i] = static_cast(injector_->randUInt32(0,255)); } - setMemEventPayload(ev, new_payload); - break; } + setMemEventPayload(ev, new_payload); return true; } @@ -106,7 +101,7 @@ int32_t CorruptMemFault::computeEndIndex(Addr base_addr, size_t payload_sz, Addr Addr addr = base_addr + ((payload_bytes - 1) * 8); for (int i = payload_bytes; i >= 0; i--, addr-=8) { if (addr <= region_end) { - return addr - base_addr; + return addr - base_addr + 8; } } return -1; From 1bcfa270bcf9f8475e2ca442a15355928c960076 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Wed, 22 Oct 2025 21:03:03 -0400 Subject: [PATCH 39/45] tests added to EXTRA_DIST in makefile --- src/sst/elements/carcosa/Makefile.am | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index 8b97ad8137..b919bd6cef 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -33,7 +33,15 @@ libcarcosa_la_SOURCES = \ faultlogic/randomFlipFault.h EXTRA_DIST = \ - dummyTest.py + tests/testCorruptMemBasic.py \ + tests/testCorruptMemDouble.py \ + tests/testCorruptMemDoubleOverlap.py \ + tests/testRandomDrop.py \ + tests/testRandomFlip.py \ + tests/testStuckAtBasic.py \ + tests/testStuckAtMultiple.py \ + tests/testStuckAtOverlap.py \ + tests/testStuckAtSameByte.py sstdir = $(includedir)/sst/elements/carcosa nobase_sst_HEADERS = \ From f76e70af774a591928d5485c43eb844d939a2f56 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 24 Oct 2025 14:51:12 -0400 Subject: [PATCH 40/45] add manual seed argument and identify seed which causes crash in randomFlip --- src/sst/elements/carcosa/faultInjectorBase.cc | 7 +++++++ src/sst/elements/carcosa/faultInjectorBase.h | 3 +++ src/sst/elements/carcosa/tests/testRandomFlip.py | 3 ++- 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index d78012a882..7a7ecce20b 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -35,6 +35,13 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); #endif + seed_ = params.find("seed", 0); + if (seed_ != 0) { + base_rng_.seed(seed_); +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "\tRNG Seed: %d\n", seed_); +#endif + } } /** diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index 2c8671f25a..f3ff9da3ab 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -60,6 +60,7 @@ class FaultInjectorBase : public SST::PortModule SST_ELI_DOCUMENT_PARAMS( {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, + {"seed", "Optional integer seed to give to the random number generator. Default = 0 (0 seed will be assumed to mean NO seed)."}, {"debug", "Integer determining if debug should be active. 0 disables, 1 sends output to STDOUT, 2 to STDERR. Default = 0"}, {"debug_level", "Integer determining verbosity of debug output. 1 enables basic text output, 2 enables signficant activity output."} ) @@ -144,6 +145,7 @@ class FaultInjectorBase : public SST::PortModule installDirection installDirection_ = installDirection::Receive; double injectionProbability_ = 0.5; SST::RNG::MersenneRNG base_rng_; + uint64_t seed_ = 0; private: std::array valid_installation_ = {{false, false}}; bool valid_installs_set = false; @@ -171,6 +173,7 @@ class FaultInjectorBase : public SST::PortModule SST_SER(installDirection_); SST_SER(injectionProbability_); SST_SER(base_rng_); + SST_SER(seed_); SST_SER(valid_installation_); SST_SER(valid_installs_set); } diff --git a/src/sst/elements/carcosa/tests/testRandomFlip.py b/src/sst/elements/carcosa/tests/testRandomFlip.py index 671f9f8311..296bf5373f 100644 --- a/src/sst/elements/carcosa/tests/testRandomFlip.py +++ b/src/sst/elements/carcosa/tests/testRandomFlip.py @@ -500,8 +500,9 @@ def addParamsPrefix(prefix,params): memctrl.addPortModule("highlink", "carcosa.RandomFlipFaultInjector", { "intallDirection": "Receive", "injectionProbability": 0.25, + "seed": 156, "debug" : 1, - "debug_level": 2 + "debug_level": 1 }) # node memory controller backend From 62eb7c0b002f38fea181f75f52311342d9626b2b Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 24 Oct 2025 16:48:52 -0400 Subject: [PATCH 41/45] remove trailing white space --- src/sst/elements/carcosa/Makefile.am | 2 +- src/sst/elements/carcosa/faultInjectorBase.cc | 6 +-- src/sst/elements/carcosa/faultInjectorBase.h | 4 +- .../carcosa/faultlogic/corruptMemFault.cc | 2 +- .../carcosa/faultlogic/corruptMemFault.h | 6 +-- .../carcosa/faultlogic/stuckAtFault.cc | 8 ++-- .../carcosa/faultlogic/stuckAtFault.h | 4 +- .../injectors/corruptMemFaultInjector.h | 4 +- .../carcosa/injectors/doubleFaultInjector.h | 2 +- .../injectors/randomDropFaultInjector.cc | 6 +-- .../injectors/randomDropFaultInjector.h | 4 +- .../injectors/randomFlipFaultInjector.h | 2 +- .../carcosa/injectors/stuckAtFaultInjector.h | 2 +- .../carcosa/tests/testCorruptMemBasic.py | 40 +++++++++---------- .../carcosa/tests/testCorruptMemDouble.py | 40 +++++++++---------- .../tests/testCorruptMemDoubleOverlap.py | 40 +++++++++---------- .../elements/carcosa/tests/testRandomDrop.py | 40 +++++++++---------- .../elements/carcosa/tests/testRandomFlip.py | 40 +++++++++---------- .../carcosa/tests/testStuckAtBasic.py | 40 +++++++++---------- .../carcosa/tests/testStuckAtMultiple.py | 40 +++++++++---------- .../carcosa/tests/testStuckAtOverlap.py | 40 +++++++++---------- .../carcosa/tests/testStuckAtSameByte.py | 40 +++++++++---------- 22 files changed, 206 insertions(+), 206 deletions(-) diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index b919bd6cef..d0cefbbd77 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -41,7 +41,7 @@ EXTRA_DIST = \ tests/testStuckAtBasic.py \ tests/testStuckAtMultiple.py \ tests/testStuckAtOverlap.py \ - tests/testStuckAtSameByte.py + tests/testStuckAtSameByte.py sstdir = $(includedir)/sst/elements/carcosa nobase_sst_HEADERS = \ diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/faultInjectorBase.cc index 7a7ecce20b..2d787f4f87 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/faultInjectorBase.cc @@ -45,7 +45,7 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() } /** - * Default behavior is to delete all fault objects in the order they were + * Default behavior is to delete all fault objects in the order they were * added to the vector */ FaultInjectorBase::~FaultInjectorBase() { @@ -57,7 +57,7 @@ FaultInjectorBase::~FaultInjectorBase() { } void -FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) +FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) { if (!valid_installs_set) { out_->fatal(CALL_INFO_LONG, -1, "Valid installation directions not set -- did you forget to call setValidInstallation() in your constructor?\n"); @@ -76,7 +76,7 @@ FaultInjectorBase::eventSent(uintptr_t key, Event*& ev) } void -FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) +FaultInjectorBase::interceptHandler(uintptr_t key, Event*& ev, bool& cancel) { if (!valid_installs_set) { out_->fatal(CALL_INFO_LONG, -1, "Valid installation directions not set -- did you forget to call setValidInstallation() in your constructor?\n"); diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/faultInjectorBase.h index f3ff9da3ab..a73d882be6 100644 --- a/src/sst/elements/carcosa/faultInjectorBase.h +++ b/src/sst/elements/carcosa/faultInjectorBase.h @@ -149,7 +149,7 @@ class FaultInjectorBase : public SST::PortModule private: std::array valid_installation_ = {{false, false}}; bool valid_installs_set = false; -protected: +protected: bool doInjection(); virtual void executeFaults(Event*& ev); @@ -157,7 +157,7 @@ class FaultInjectorBase : public SST::PortModule /** * This function MUST be called by the derived class constructor * @arg params pass the same params object to this function - * @arg valid_install_ pass either SEND_VALID, RECEIVE_VALID, + * @arg valid_install_ pass either SEND_VALID, RECEIVE_VALID, * or SEND_RECEIVE_VALID */ void setValidInstallation(Params& params, std::array valid_install); diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc index f1c43c26f5..fdabd7deb1 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.cc @@ -29,7 +29,7 @@ CorruptMemFault::CorruptMemFault(Params& params, FaultInjectorBase* injector) : // check validity if (region_pair.first > region_pair.second) { - getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Invalid corruption region: [0x%zx, 0x%zx].\n", + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Invalid corruption region: [0x%zx, 0x%zx].\n", region_pair.first, region_pair.second); } diff --git a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h index f5e6241de2..5574639bad 100644 --- a/src/sst/elements/carcosa/faultlogic/corruptMemFault.h +++ b/src/sst/elements/carcosa/faultlogic/corruptMemFault.h @@ -25,13 +25,13 @@ typedef std::vector dataVec; typedef SST::MemHierarchy::Addr Addr; /** - * This fault is intended to be placed on the input/output ports + * This fault is intended to be placed on the input/output ports * of memory components such as DRAM or HBM. Events that pass through - * it, and whose data addresses fall within the ranges set in this + * it, and whose data addresses fall within the ranges set in this * module's parameters, will have their payloads randomly altered * to simulate corruption in the affected region of memory. */ -class CorruptMemFault : public FaultBase +class CorruptMemFault : public FaultBase { public: diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc index 7bacc2b2cd..571d1e45a6 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.cc @@ -15,7 +15,7 @@ using namespace SST::Carcosa; /********** StuckAtFault **********/ -StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) +StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultBase(params, injector) { #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "Fault Type: Stuck-At Fault\n"); @@ -33,7 +33,7 @@ StuckAtFault::StuckAtFault(Params& params, FaultInjectorBase* injector) : FaultB uint8_t zeroMask = param->zeroMask; uint8_t oneMask = param->oneMask; if ((int)(zeroMask & oneMask) > 0) { - getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Masks contain overlapping values. Addr: 0x%zx, " + getSimulationOutput()->fatal(CALL_INFO_LONG, -1, "Masks contain overlapping values. Addr: 0x%zx, " "byte: %d\n", addr, byte); } // check for vector in each map before creating it @@ -103,7 +103,7 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { uint32_t final_byte = computeByte(masked_addr, mem_ev->getBaseAddr(), maskPair.first); #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", - maskPair.first, (int)payload[final_byte], (int) mask, + maskPair.first, (int)payload[final_byte], (int) mask, (int)(payload[final_byte] & (~mask))); getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tPayload index: %d\n", final_byte); #endif @@ -120,7 +120,7 @@ bool StuckAtFault::faultLogic(SST::Event*& ev) { uint32_t final_byte = computeByte(masked_addr, mem_ev->getBaseAddr(), maskPair.first); #ifdef __SST_DEBUG_OUTPUT__ getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tbyte %d, value: %d, mask: %d, new value: %d\n", - maskPair.first, (int)payload[final_byte], (int) mask, + maskPair.first, (int)payload[final_byte], (int) mask, (int)(payload[final_byte] | mask)); getSimulationDebug()->debug(CALL_INFO_LONG, 1, 0, "\tPayload index: %d\n", final_byte); #endif diff --git a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h index c587db77c5..9ec4cdb59a 100644 --- a/src/sst/elements/carcosa/faultlogic/stuckAtFault.h +++ b/src/sst/elements/carcosa/faultlogic/stuckAtFault.h @@ -29,10 +29,10 @@ typedef SST::MemHierarchy::Addr Addr; * To ensure correct operation, make sure that the port module * using this fault is attached at every point where the data * for this bit could be read. For example, a stuck bit in the L2 - * cache would need a port module with this fault installed on all + * cache would need a port module with this fault installed on all * input OR all output ports to the L2; if the simulator has forwarding enabled, * but the actual system being simulated does not do the forwarding from memory - * directly into the L1 or the core (bypassing L2 ops in simulation), it may be + * directly into the L1 or the core (bypassing L2 ops in simulation), it may be * advisable to also place these port modules on the ports used to forward these events. */ class StuckAtFault : public FaultBase diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index de611f6ab5..2d8bdf811d 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -36,7 +36,7 @@ class CorruptMemFaultInjector : public FaultInjectorBase { ~CorruptMemFaultInjector() {} protected: void executeFaults(Event*& ev) override; - + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); @@ -44,7 +44,7 @@ class CorruptMemFaultInjector : public FaultInjectorBase { } ImplementVirtualSerializable(SST::Carcosa::CorruptMemFaultInjector) }; // class CorruptMemFaultInjector - + } // namespace SST::Carcosa #endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h index 04b658d034..b9a9b6ed42 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -51,7 +51,7 @@ class DoubleFaultInjector : public FaultInjectorBase { } ImplementVirtualSerializable(SST::Carcosa::DoubleFaultInjector) }; // class DoubleFaultInjector - + } // namespace SST::Carcosa #endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index 84305d9d3a..f22ff9d472 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -22,9 +22,9 @@ RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjector /** * Custom execution is required to ensure delivery is canceled - * - * In the base interceptHandler, a reference to a boolean called - * 'cancel' is accepted as an argument. That function assigns the + * + * In the base interceptHandler, a reference to a boolean called + * 'cancel' is accepted as an argument. That function assigns the * injector's pointer (called 'cancel_') to that reference's address, * and that reference must be updated here after the event is destroyed * if the installation direction of this PortModule was set to 'Receive'. diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index 7b937d1774..83b8a32fec 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -35,7 +35,7 @@ class RandomDropFaultInjector : public FaultInjectorBase { ~RandomDropFaultInjector() {} protected: void executeFaults(Event*& ev) override; - + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); @@ -43,7 +43,7 @@ class RandomDropFaultInjector : public FaultInjectorBase { } ImplementVirtualSerializable(SST::Carcosa::RandomDropFaultInjector) }; // class RandomDropFaultInjector - + } // namespace SST::Carcosa #endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index cbb79c03f6..cd038e04ff 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -41,7 +41,7 @@ class RandomFlipFaultInjector : public FaultInjectorBase { } ImplementVirtualSerializable(SST::Carcosa::RandomFlipFaultInjector) }; // class RandomFlipFaultInjector - + } // namespace SST::Carcosa #endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index d3ba913e65..90b80de81e 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -45,7 +45,7 @@ class StuckAtFaultInjector : public FaultInjectorBase { } ImplementVirtualSerializable(SST::Carcosa::StuckAtFaultInjector) }; // class StuckAtFaultInjector - + } // namespace SST::Carcosa #endif \ No newline at end of file diff --git a/src/sst/elements/carcosa/tests/testCorruptMemBasic.py b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py index 1f2f1b8fe7..4485ff40c9 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemBasic.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -504,7 +504,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -524,12 +524,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -553,14 +553,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDouble.py b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py index 78b293fac5..736a7cdad0 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemDouble.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -504,7 +504,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -524,12 +524,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -553,14 +553,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py index ca1d629e8c..53c44f6ea2 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -505,7 +505,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -525,12 +525,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -554,14 +554,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testRandomDrop.py b/src/sst/elements/carcosa/tests/testRandomDrop.py index decb949f7a..f8a9e1951d 100644 --- a/src/sst/elements/carcosa/tests/testRandomDrop.py +++ b/src/sst/elements/carcosa/tests/testRandomDrop.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -504,7 +504,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -524,12 +524,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -553,14 +553,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testRandomFlip.py b/src/sst/elements/carcosa/tests/testRandomFlip.py index 296bf5373f..6ecebfa294 100644 --- a/src/sst/elements/carcosa/tests/testRandomFlip.py +++ b/src/sst/elements/carcosa/tests/testRandomFlip.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -505,7 +505,7 @@ def addParamsPrefix(prefix,params): "debug_level": 1 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -525,12 +525,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -554,14 +554,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testStuckAtBasic.py b/src/sst/elements/carcosa/tests/testStuckAtBasic.py index 3d5674f9ff..a289d5a5e9 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtBasic.py +++ b/src/sst/elements/carcosa/tests/testStuckAtBasic.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -504,7 +504,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -524,12 +524,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -553,14 +553,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testStuckAtMultiple.py b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py index 97ec194650..dcd1156c56 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtMultiple.py +++ b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -505,7 +505,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -525,12 +525,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -554,14 +554,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testStuckAtOverlap.py b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py index c553a699a3..ccf39f831f 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtOverlap.py +++ b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -505,7 +505,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -525,12 +525,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -554,14 +554,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) diff --git a/src/sst/elements/carcosa/tests/testStuckAtSameByte.py b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py index d5d61f5ad5..a0c31ede53 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtSameByte.py +++ b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py @@ -145,7 +145,7 @@ "checkpoint" : checkpoint } -processList = ( +processList = ( ( 1, { "env_count" : 1, "env0" : "OMP_NUM_THREADS={}".format(numCpus*numThreads), @@ -317,20 +317,20 @@ "debug" : mh_debug, "debug_level" : mh_debug_level, } -busParams = { - "bus_frequency" : cpu_clock, +busParams = { + "bus_frequency" : cpu_clock, } -l2memLinkParams = { +l2memLinkParams = { "group" : 1, - "network_bw" : "25GB/s" + "network_bw" : "25GB/s" } class CPU_Builder: def __init__(self): pass - # CPU + # CPU def build( self, prefix, nodeId, cpuId ): if pythonDebug: @@ -349,7 +349,7 @@ def build( self, prefix, nodeId, cpuId ): decode.enableAllStatistics() - # CPU.decoder.osHandler + # CPU.decoder.osHandler os_hdlr = decode.setSubComponent( "os_handler", vanadis_os_hdlr ) os_hdlr.addParams( osHdlrParams ) @@ -363,7 +363,7 @@ def build( self, prefix, nodeId, cpuId ): cpu_lsq.addParams(lsqParams) cpu_lsq.enableAllStatistics() - # CPU.lsq mem interface which connects to D-cache + # CPU.lsq mem interface which connects to D-cache cpuDcacheIf = cpu_lsq.setSubComponent( "memory_interface", "memHierarchy.standardInterface" ) # CPU.mem interface for I-cache @@ -409,7 +409,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_dtlb_link.connect( (cpuDcacheIf, "lowlink", "1ns"), (dtlbWrapper, "cpu_if", "1ns") ) link_cpu_dtlb_link.setNoCut() - # data TLB -> data L1 + # data TLB -> data L1 link_cpu_l1dcache_link = sst.Link(prefix+".link_cpu_l1dcache_link") link_cpu_l1dcache_link.connect( (dtlbWrapper, "cache_if", "1ns"), (cpu_l1dcache, "highlink", "1ns") ) link_cpu_l1dcache_link.setNoCut() @@ -419,7 +419,7 @@ def build( self, prefix, nodeId, cpuId ): link_cpu_itlb_link.connect( (cpuIcacheIf, "lowlink", "1ns"), (itlbWrapper, "cpu_if", "1ns") ) link_cpu_itlb_link.setNoCut() - # instruction TLB -> instruction L1 + # instruction TLB -> instruction L1 link_cpu_l1icache_link = sst.Link(prefix+".link_cpu_l1icache_link") link_cpu_l1icache_link.connect( (itlbWrapper, "cache_if", "1ns"), (cpu_l1icache, "highlink", "1ns") ) link_cpu_l1icache_link.setNoCut(); @@ -457,7 +457,7 @@ def addParamsPrefix(prefix,params): node_os.addParams(osParams) num=0 -for i,process in processList: +for i,process in processList: #print( process ) for y in range(i): #print( "process", num ) @@ -466,7 +466,7 @@ def addParamsPrefix(prefix,params): if pythonDebug: print('total hardware threads ' + str(num) ) - + # node OS MMU node_os_mmu = node_os.setSubComponent( "mmu", "mmu." + mmuType ) node_os_mmu.addParams(mmuParams) @@ -480,7 +480,7 @@ def addParamsPrefix(prefix,params): os_cache_2_mem = os_cache.setSubComponent("lowlink", "memHierarchy.MemNIC") os_cache_2_mem.addParams( l2memLinkParams ) -# node memory router +# node memory router comp_chiprtr = sst.Component("chiprtr", "merlin.hr_router") comp_chiprtr.addParams(memRtrParams) comp_chiprtr.setSubComponent("topology","merlin.singlerouter") @@ -489,7 +489,7 @@ def addParamsPrefix(prefix,params): dirctrl = sst.Component("dirctrl", "memHierarchy.DirectoryController") dirctrl.addParams(dirCtrlParams) -# node directory controller port to cpu +# node directory controller port to cpu dirNIC = dirctrl.setSubComponent("highlink", "memHierarchy.MemNIC") dirNIC.addParams(dirNicParams) @@ -505,7 +505,7 @@ def addParamsPrefix(prefix,params): "debug_level": 2 }) -# node memory controller backend +# node memory controller backend memory = memctrl.setSubComponent("backend", "memHierarchy.simpleMem") memory.addParams(memParams) @@ -525,12 +525,12 @@ def addParamsPrefix(prefix,params): link_dir_2_rtr.connect( (comp_chiprtr, "port"+str(numCpus), "1ns"), (dirNIC, "port", "1ns") ) link_dir_2_rtr.setNoCut() -# Directory controller to memory controller +# Directory controller to memory controller link_dir_2_mem = sst.Link("link_dir_2_mem") link_dir_2_mem.connect( (dirctrl, "lowlink", "1ns"), (memctrl, "highlink", "1ns") ) link_dir_2_mem.setNoCut() -# MMU -> ostlb +# MMU -> ostlb # don't need when using pass through TLB #link_mmu_ostlb_link = sst.Link("link_mmu_ostlb_link") #link_mmu_ostlb_link.connect( (node_os_mmu, "ostlb", "1ns"), (ostlb, "mmu", "1ns") ) @@ -554,14 +554,14 @@ def addParamsPrefix(prefix,params): prefix="node" + str(nodeId) + ".cpu" + str(cpu) os_hdlr, l2cache, dtlb, itlb = cpuBuilder.build(prefix, nodeId, cpu) - # MMU -> dtlb + # MMU -> dtlb link_mmu_dtlb_link = sst.Link(prefix + ".link_mmu_dtlb_link") link_mmu_dtlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".dtlb", "1ns"), dtlb ) - # MMU -> itlb + # MMU -> itlb link_mmu_itlb_link = sst.Link(prefix + ".link_mmu_itlb_link") link_mmu_itlb_link.connect( (node_os_mmu, "core"+ str(cpu) +".itlb", "1ns"), itlb ) - + # CPU os handler -> node OS link_core_os_link = sst.Link(prefix + ".link_core_os_link") link_core_os_link.connect( os_hdlr, (node_os, "core" + str(cpu), "5ns") ) From 5436f8b14443a5f5c0fbf2b94fc3f234cfb25659 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 29 Jan 2026 13:42:34 -0500 Subject: [PATCH 42/45] move faultInjectorBase into injectors dir update paths to faultInjectorBase --- src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h | 2 +- src/sst/elements/carcosa/injectors/doubleFaultInjector.h | 2 +- src/sst/elements/carcosa/{ => injectors}/faultInjectorBase.cc | 0 src/sst/elements/carcosa/{ => injectors}/faultInjectorBase.h | 0 src/sst/elements/carcosa/injectors/randomDropFaultInjector.h | 2 +- src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h | 2 +- src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h | 2 +- 7 files changed, 5 insertions(+), 5 deletions(-) rename src/sst/elements/carcosa/{ => injectors}/faultInjectorBase.cc (100%) rename src/sst/elements/carcosa/{ => injectors}/faultInjectorBase.h (100%) diff --git a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h index 2d8bdf811d..acdcad1e45 100644 --- a/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/corruptMemFaultInjector.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULTINJECTOR_H #define SST_ELEMENTS_CARCOSA_CORRUPTMEMFAULTINJECTOR_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h index b9a9b6ed42..0ca05a6b71 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/doubleFaultInjector.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_DOUBLEFAULTINJECTOR_H #define SST_ELEMENTS_CARCOSA_DOUBLEFAULTINJECTOR_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" #include namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/faultInjectorBase.cc b/src/sst/elements/carcosa/injectors/faultInjectorBase.cc similarity index 100% rename from src/sst/elements/carcosa/faultInjectorBase.cc rename to src/sst/elements/carcosa/injectors/faultInjectorBase.cc diff --git a/src/sst/elements/carcosa/faultInjectorBase.h b/src/sst/elements/carcosa/injectors/faultInjectorBase.h similarity index 100% rename from src/sst/elements/carcosa/faultInjectorBase.h rename to src/sst/elements/carcosa/injectors/faultInjectorBase.h diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index 83b8a32fec..fde5a5ca31 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_RANDOMDROPFAULTINJECTOR_H #define SST_ELEMENTS_CARCOSA_RANDOMDROPFAULTINJECTOR_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index cd038e04ff..08ee6dbeee 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULTINJECTOR_H #define SST_ELEMENTS_CARCOSA_RANDOMFLIPFAULTINJECTOR_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" namespace SST::Carcosa { diff --git a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h index 90b80de81e..87b1157c3d 100644 --- a/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/stuckAtFaultInjector.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_STUCKATFAULTINJECTOR_H #define SST_ELEMENTS_CARCOSA_STUCKATFAULTINJECTOR_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" #include namespace SST::Carcosa { From acfda659609f3a1a81415f08953e856fd8685174 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 29 Jan 2026 13:43:51 -0500 Subject: [PATCH 43/45] rename doubleFaultInjector to dropFlipFaultInjector --- .../{doubleFaultInjector.cc => dropFlipFaultInjector.cc} | 2 +- .../{doubleFaultInjector.h => dropFlipFaultInjector.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/sst/elements/carcosa/injectors/{doubleFaultInjector.cc => dropFlipFaultInjector.cc} (96%) rename src/sst/elements/carcosa/injectors/{doubleFaultInjector.h => dropFlipFaultInjector.h} (100%) diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc similarity index 96% rename from src/sst/elements/carcosa/injectors/doubleFaultInjector.cc rename to src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc index ab83e4063b..9266792cb7 100644 --- a/src/sst/elements/carcosa/injectors/doubleFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc @@ -9,7 +9,7 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include "sst/elements/carcosa/injectors/doubleFaultInjector.h" +#include "sst/elements/carcosa/injectors/dropFlipFaultInjector.h" #include "sst/elements/carcosa/faultlogic/randomFlipFault.h" #include "sst/elements/carcosa/faultlogic/randomDropFault.h" diff --git a/src/sst/elements/carcosa/injectors/doubleFaultInjector.h b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h similarity index 100% rename from src/sst/elements/carcosa/injectors/doubleFaultInjector.h rename to src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h From 8e3c56ef6f693bed90ac04d007ccf956814a2e5c Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Thu, 29 Jan 2026 16:58:48 -0500 Subject: [PATCH 44/45] All PR changes made -- thorough test needed execution doesn't end in random drop test --- src/sst/elements/carcosa/Makefile.am | 12 +-- .../elements/carcosa/faultlogic/faultBase.h | 2 +- .../injectors/dropFlipFaultInjector.cc | 81 ++++++++++++++----- .../carcosa/injectors/dropFlipFaultInjector.h | 30 ++++--- .../carcosa/injectors/faultInjectorBase.cc | 19 ++--- .../carcosa/injectors/faultInjectorBase.h | 39 ++++----- .../injectors/randomDropFaultInjector.cc | 28 +++++-- .../injectors/randomDropFaultInjector.h | 7 +- .../injectors/randomFlipFaultInjector.cc | 34 ++++++++ .../injectors/randomFlipFaultInjector.h | 8 ++ .../carcosa/tests/testCorruptMemBasic.py | 3 +- .../carcosa/tests/testCorruptMemDouble.py | 3 +- .../tests/testCorruptMemDoubleOverlap.py | 3 +- .../elements/carcosa/tests/testRandomDrop.py | 4 +- .../elements/carcosa/tests/testRandomFlip.py | 4 +- .../carcosa/tests/testStuckAtBasic.py | 3 +- .../carcosa/tests/testStuckAtMultiple.py | 3 +- .../carcosa/tests/testStuckAtOverlap.py | 3 +- .../carcosa/tests/testStuckAtSameByte.py | 3 +- 19 files changed, 188 insertions(+), 101 deletions(-) diff --git a/src/sst/elements/carcosa/Makefile.am b/src/sst/elements/carcosa/Makefile.am index d0cefbbd77..986cab2899 100644 --- a/src/sst/elements/carcosa/Makefile.am +++ b/src/sst/elements/carcosa/Makefile.am @@ -9,8 +9,8 @@ AM_CPPFLAGS += \ compdir = $(pkglibdir) comp_LTLIBRARIES = libcarcosa.la libcarcosa_la_SOURCES = \ - faultInjectorBase.cc \ - faultInjectorBase.h \ + injectors/faultInjectorBase.cc \ + injectors/faultInjectorBase.h \ injectors/stuckAtFaultInjector.cc \ injectors/stuckAtFaultInjector.h \ injectors/corruptMemFaultInjector.cc \ @@ -19,8 +19,8 @@ libcarcosa_la_SOURCES = \ injectors/randomDropFaultInjector.h \ injectors/randomFlipFaultInjector.cc \ injectors/randomFlipFaultInjector.h \ - injectors/doubleFaultInjector.cc \ - injectors/doubleFaultInjector.h \ + injectors/dropFlipFaultInjector.cc \ + injectors/dropFlipFaultInjector.h \ faultlogic/faultBase.cc \ faultlogic/faultBase.h \ faultlogic/stuckAtFault.cc \ @@ -45,12 +45,12 @@ EXTRA_DIST = \ sstdir = $(includedir)/sst/elements/carcosa nobase_sst_HEADERS = \ - faultInjectorBase.h \ + injectors/faultInjectorBase.h \ injectors/stuckAtFaultInjector.h \ injectors/corruptMemFaultInjector.h \ injectors/randomDropFaultInjector.h \ injectors/randomFlipFaultInjector.h \ - injectors/doubleFaultInjector.h \ + injectors/dropFlipFaultInjector.h \ faultlogic/faultBase.h \ faultlogic/stuckAtFault.h \ faultlogic/corruptMemFault.h \ diff --git a/src/sst/elements/carcosa/faultlogic/faultBase.h b/src/sst/elements/carcosa/faultlogic/faultBase.h index 785d25ee63..08da7ac773 100644 --- a/src/sst/elements/carcosa/faultlogic/faultBase.h +++ b/src/sst/elements/carcosa/faultlogic/faultBase.h @@ -12,7 +12,7 @@ #ifndef SST_ELEMENTS_CARCOSA_FAULTBASE_H #define SST_ELEMENTS_CARCOSA_FAULTBASE_H -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" #include "sst/core/serialization/serializable.h" #include #include diff --git a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc index 9266792cb7..c2c2da126e 100644 --- a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc @@ -15,40 +15,85 @@ using namespace SST::Carcosa; -DoubleFaultInjector::DoubleFaultInjector(Params& params) : FaultInjectorBase(params) { +DropFlipFaultInjector::DropFlipFaultInjector(Params& params) : FaultInjectorBase(params) { // create fault fault.resize(2); fault[0] = new RandomDropFault(params, this); fault[1] = new RandomFlipFault(params, this); - // read flipvsdrop param - flipVsDropProb_ = params.find("flipVsDropProb", 0.5); + // read probability params + drop_probability_ = params.find("drop_probability", 0.0); +#ifdef __SST_DEBUG_OUTPUT__ + if (drop_probability_ > 0.0){ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop probability set to %lf.\n", drop_probability_); + } +#endif + + flip_probability_ = params.find("flip_probability", 0.0); +#ifdef __SST_DEBUG_OUTPUT__ + if (flip_probability_ > 0.0){ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip probability set to %lf.\n", flip_probability_); + } +#endif setValidInstallation(params, SEND_RECEIVE_VALID); } +bool DropFlipFaultInjector::doInjection() { + if (this->randFloat(0.0, 1.0) <= this->drop_probability_) { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); +#endif + this->triggered_injection_[0] = true; + } else { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop skipped.\n"); +#endif + this->triggered_injection_[0] = false; + } + + if (this->randFloat(0.0, 1.0) <= this->flip_probability_) { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); +#endif + this->triggered_injection_[1] = true; + } + else { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip skipped.\n"); +#endif + this->triggered_injection_[1] = false; + } + + return this->triggered_injection_[0] || this->triggered_injection_[1]; +} + /** * Overridden execution function to cause faults to be chosen at random * from the vector once a fault has been triggered */ -void DoubleFaultInjector::executeFaults(Event*& ev) { - FaultBase* triggered_fault = nullptr; - if (rng_.nextUniform() <= flipVsDropProb_) { - // do flip -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); -#endif - triggered_fault = fault[1]; - } else { +void DropFlipFaultInjector::executeFaults(Event*& ev) { + if (this->triggered_injection_[0]) { // do drop + if (fault[0]) { + fault[0]->faultLogic(ev); #ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); + dbg_->debug(CALL_INFO_LONG, 1, 0, "Drop triggered.\n"); #endif - triggered_fault = fault[0]; + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid drop fault object.\n"); + } + return; } - if (triggered_fault) { - triggered_fault->faultLogic(ev); - } else { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + if (this->triggered_injection_[1]) { + // do flip + if (fault[1]) { + fault[1]->faultLogic(ev); +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip triggered.\n"); +#endif + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid flip fault object.\n"); + } } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h index 0ca05a6b71..a0b165f62c 100644 --- a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.h @@ -17,37 +17,41 @@ namespace SST::Carcosa { -class DoubleFaultInjector : public FaultInjectorBase { +class DropFlipFaultInjector : public FaultInjectorBase { public: SST_ELI_REGISTER_PORTMODULE( - DoubleFaultInjector, + DropFlipFaultInjector, "carcosa", - "DoubleFaultInjector", + "DropFlipFaultInjector", SST_ELI_ELEMENT_VERSION(0, 1, 0), - "PortModule class used to simulate a data transfer lost at random OR a random bit flip in transit" + "PortModule class used to simulate a data transfer lost at random and a random bit flip in transit" ) SST_ELI_DOCUMENT_PARAMS( - {"flipVsDropProb", "The probability that a flip will be chosen over a drop when a fault is injected"} + {"drop_probability", "The probability that a drop will be injected. Default = 0.0"}, + {"flip_probability", "The probability that a flip will be injected. Default = 0.0"} ) - DoubleFaultInjector(Params& params); + DropFlipFaultInjector(Params& params); - DoubleFaultInjector() = default; - ~DoubleFaultInjector() {} + DropFlipFaultInjector() = default; + ~DropFlipFaultInjector() {} protected: - double flipVsDropProb_; + double drop_probability_; + double flip_probability_; + // Byte array representing triggered fault. First is drop, second is flip. + std::array triggered_injection_; + bool doInjection() override; void executeFaults(Event*& ev) override; - SST::RNG::MersenneRNG rng_; - void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` - SST_SER(flipVsDropProb_); - SST_SER(rng_); + SST_SER(drop_probability_); + SST_SER(flip_probability_); + SST_SER(triggered_injection_); } ImplementVirtualSerializable(SST::Carcosa::DoubleFaultInjector) }; // class DoubleFaultInjector diff --git a/src/sst/elements/carcosa/injectors/faultInjectorBase.cc b/src/sst/elements/carcosa/injectors/faultInjectorBase.cc index 2d787f4f87..6e760de39f 100644 --- a/src/sst/elements/carcosa/injectors/faultInjectorBase.cc +++ b/src/sst/elements/carcosa/injectors/faultInjectorBase.cc @@ -9,7 +9,7 @@ // information, see the LICENSE file in the top level directory of the // distribution. -#include "sst/elements/carcosa/faultInjectorBase.h" +#include "sst/elements/carcosa/injectors/faultInjectorBase.h" #include "sst/core/params.h" using namespace SST::Carcosa; @@ -27,14 +27,6 @@ FaultInjectorBase::FaultInjectorBase(SST::Params& params) : PortModule() #ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "Initializing FaultInjector:\n"); #endif - - injectionProbability_ = params.find("injectionProbability", "0.5"); - if ( injectionProbability_ < 0.0 || injectionProbability_ > 1.0 ) { - out_->fatal(CALL_INFO_LONG, -1, "\tInjection probability outside of bounds. Must be in the following range: [0.0,1.0].\n"); - } -#ifdef __SST_DEBUG_OUTPUT__ - dbg_->debug(CALL_INFO_LONG, 1, 0, "\tInjection Probability: %f\n", injectionProbability_); -#endif seed_ = params.find("seed", 0); if (seed_ != 0) { base_rng_.seed(seed_); @@ -124,8 +116,7 @@ double FaultInjectorBase::randFloat(double start, double end) { } bool FaultInjectorBase::doInjection() { - double rand_val = base_rng_.nextUniform(); - return rand_val <= getInjectionProb(); + return true; } installDirection FaultInjectorBase::setInstallDirection(std::string param) { @@ -147,10 +138,10 @@ installDirection FaultInjectorBase::setInstallDirection(std::string param) { void FaultInjectorBase::setValidInstallation(Params& params, std::array valid_install) { valid_installation_ = valid_install; - std::string install_dir = params.find("installDirection", "Receive"); - installDirection_ = setInstallDirection(install_dir); + std::string install_dir = params.find("install_direction", "Receive"); + install_direction_ = setInstallDirection(install_dir); - if (installDirection_ == installDirection::Invalid) { + if (install_direction_ == installDirection::Invalid) { out_->fatal(CALL_INFO_LONG, -1, "Install Direction should never be set to Invalid! Did you forget to set which directions are valid?\n"); } diff --git a/src/sst/elements/carcosa/injectors/faultInjectorBase.h b/src/sst/elements/carcosa/injectors/faultInjectorBase.h index a73d882be6..18fa2dbd22 100644 --- a/src/sst/elements/carcosa/injectors/faultInjectorBase.h +++ b/src/sst/elements/carcosa/injectors/faultInjectorBase.h @@ -43,7 +43,13 @@ enum installDirection { /** * Base class containing required functions and basic data for - * creating fault injection on component ports + * creating fault injection on component ports. + * + * Injectors are used to execute the logic that tests for + * whether or not an injection should occur. Upon triggering + * an injection, a fault object which inherits from the + * FaultBase class but be used to execute the fault logic + * on the triggering message. */ class FaultInjectorBase : public SST::PortModule { @@ -58,19 +64,12 @@ class FaultInjectorBase : public SST::PortModule ) SST_ELI_DOCUMENT_PARAMS( - {"installDirection", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, - {"injectionProbability", "The probability with which an injection should occur. Valid inputs range from 0 to 1. Default = 0.5."}, + {"install_direction", "Flag which direction the injector should read from on a port. Valid optins are \'Send\', \'Receive\', and \'Both\'. Default is \'Receive\'."}, {"seed", "Optional integer seed to give to the random number generator. Default = 0 (0 seed will be assumed to mean NO seed)."}, {"debug", "Integer determining if debug should be active. 0 disables, 1 sends output to STDOUT, 2 to STDERR. Default = 0"}, {"debug_level", "Integer determining verbosity of debug output. 1 enables basic text output, 2 enables signficant activity output."} ) - // SST_ELI_DOCUMENT_STATISTICS( - // // Trigger Statistics - // {"EventsArrived", "Number of events that passed through the fault injector", "count", 1}, - // {"FaultsTriggered", "Number of events that triggered a fault", "count", 1} - // ) - FaultInjectorBase(Params& params); FaultInjectorBase() = default; @@ -81,7 +80,7 @@ class FaultInjectorBase : public SST::PortModule bool installOnReceive() override { - switch (installDirection_) { + switch (install_direction_) { case Send: return false; case Receive: @@ -91,7 +90,7 @@ class FaultInjectorBase : public SST::PortModule } bool installOnSend() override { - switch (installDirection_) { + switch (install_direction_) { case Send: return true; case Receive: @@ -100,10 +99,6 @@ class FaultInjectorBase : public SST::PortModule } } - double getInjectionProb() { - return injectionProbability_; - } - void cancelDelivery() { *cancel_ = true; } @@ -111,7 +106,7 @@ class FaultInjectorBase : public SST::PortModule installDirection setInstallDirection(std::string param); installDirection getInstallDirection() { - return installDirection_; + return install_direction_; } enum memEventType { @@ -142,8 +137,7 @@ class FaultInjectorBase : public SST::PortModule SST::Output* dbg_; std::vector fault; bool* cancel_; - installDirection installDirection_ = installDirection::Receive; - double injectionProbability_ = 0.5; + installDirection install_direction_ = installDirection::Receive; SST::RNG::MersenneRNG base_rng_; uint64_t seed_ = 0; private: @@ -151,7 +145,7 @@ class FaultInjectorBase : public SST::PortModule bool valid_installs_set = false; protected: - bool doInjection(); + virtual bool doInjection(); virtual void executeFaults(Event*& ev); /** @@ -170,18 +164,13 @@ class FaultInjectorBase : public SST::PortModule SST_SER(dbg_); SST_SER(fault); SST_SER(cancel_); - SST_SER(installDirection_); - SST_SER(injectionProbability_); + SST_SER(install_direction_); SST_SER(base_rng_); SST_SER(seed_); SST_SER(valid_installation_); SST_SER(valid_installs_set); } ImplementVirtualSerializable(SST::Carcosa::FaultInjectorBase) - - // Statistics - // Statistic stat_eventsArrived; - // Statistic stat_faultsTriggered; }; } // namespace SST::FaultInjectorBase diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc index f22ff9d472..33f9bcc735 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.cc @@ -15,11 +15,27 @@ using namespace SST::Carcosa; RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjectorBase(params) { + // read injection probability + injection_probability_ = params.find("injection_probability", 0.0); // create fault fault.push_back(new RandomDropFault(params, this)); setValidInstallation(params, RECEIVE_VALID); } +bool RandomDropFaultInjector::doInjection() { + if (this->randFloat(0.0, 1.0) <= this->injection_probability_) { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); +#endif + return true; + } else { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); +#endif + return false; + } +} + /** * Custom execution is required to ensure delivery is canceled * @@ -30,11 +46,13 @@ RandomDropFaultInjector::RandomDropFaultInjector(Params& params) : FaultInjector * if the installation direction of this PortModule was set to 'Receive'. */ void RandomDropFaultInjector::executeFaults(Event*& ev) { - bool success = false; if (fault[0]) { - success = fault[0]->faultLogic(ev); - } - if (!success) { - out_->fatal(CALL_INFO_LONG, -1, "No valid fault object, or no fault successfully executed.\n"); + if (this->doInjection()) { + if (!fault[0]->faultLogic(ev)) { + out_->fatal(CALL_INFO_LONG, -1, "Fault execution failed.\n"); + } + } + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h index fde5a5ca31..e1b3b901e2 100644 --- a/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomDropFaultInjector.h @@ -22,11 +22,12 @@ class RandomDropFaultInjector : public FaultInjectorBase { RandomDropFaultInjector, "carcosa", "RandomDropFaultInjector", - SST_ELI_ELEMENT_VERSION(0, 1, 0), + SST_ELI_ELEMENT_VERSION(0, 2, 0), "PortModule class used to simulate a data transfer lost at random" ) SST_ELI_DOCUMENT_PARAMS( + {"injection_probability", "Probability for injection to randomly occur. Default = 0.0"} ) RandomDropFaultInjector(Params& params); @@ -34,11 +35,15 @@ class RandomDropFaultInjector : public FaultInjectorBase { RandomDropFaultInjector() = default; ~RandomDropFaultInjector() {} protected: + + double injection_probability_; + bool doInjection() override; void executeFaults(Event*& ev) override; void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); + SST_SER(injection_probability_); // serialize parameters like `SST_SER()` } ImplementVirtualSerializable(SST::Carcosa::RandomDropFaultInjector) diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc index ace17da2af..999045c316 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.cc @@ -15,7 +15,41 @@ using namespace SST::Carcosa; RandomFlipFaultInjector::RandomFlipFaultInjector(Params& params) : FaultInjectorBase(params) { + // read injection probability + this->injection_probability_ = params.find("injection_probability", 0.0); +#ifdef __SST_DEBUG_OUTPUT__ + if (injection_probability_ > 0.0){ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection probability set to %lf.\n", injection_probability_); + } +#endif + // create fault fault.push_back(new RandomFlipFault(params, this)); setValidInstallation(params, SEND_RECEIVE_VALID); +} + +bool RandomFlipFaultInjector::doInjection() { + if (this->randFloat(0.0, 1.0) <= this->injection_probability_) { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection triggered.\n"); +#endif + return true; + } else { +#ifdef __SST_DEBUG_OUTPUT__ + dbg_->debug(CALL_INFO_LONG, 1, 0, "Injection skipped.\n"); +#endif + return false; + } +} + +void RandomFlipFaultInjector::executeFaults(Event*& ev) { + if (fault[0]) { + if (this->doInjection()) { + if (!fault[0]->faultLogic(ev)) { + out_->fatal(CALL_INFO_LONG, -1, "Fault execution failed.\n"); + } + } + } else { + out_->fatal(CALL_INFO_LONG, -1, "No valid fault object.\n"); + } } \ No newline at end of file diff --git a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h index 08ee6dbeee..cf79131bef 100644 --- a/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h +++ b/src/sst/elements/carcosa/injectors/randomFlipFaultInjector.h @@ -27,6 +27,7 @@ class RandomFlipFaultInjector : public FaultInjectorBase { ) SST_ELI_DOCUMENT_PARAMS( + {"injection_probability", "Probability for fault injection to trigger. Default = 0.0"} ) RandomFlipFaultInjector(Params& params); @@ -34,10 +35,17 @@ class RandomFlipFaultInjector : public FaultInjectorBase { RandomFlipFaultInjector() = default; ~RandomFlipFaultInjector() {} protected: + double injection_probability_; + + + bool doInjection() override; + void executeFaults(Event*& ev) override; + void serialize_order(SST::Core::Serialization::serializer& ser) override { SST::PortModule::serialize_order(ser); // serialize parameters like `SST_SER()` + SST_SER(injection_probability_); } ImplementVirtualSerializable(SST::Carcosa::RandomFlipFaultInjector) }; // class RandomFlipFaultInjector diff --git a/src/sst/elements/carcosa/tests/testCorruptMemBasic.py b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py index 4485ff40c9..54b8785484 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemBasic.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemBasic.py @@ -497,8 +497,7 @@ def addParamsPrefix(prefix,params): memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "regions": ["4D88, 4DA0"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDouble.py b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py index 736a7cdad0..d38f90d7ba 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemDouble.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemDouble.py @@ -497,8 +497,7 @@ def addParamsPrefix(prefix,params): memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "regions": ["4D88, 4D90", "4DA0, 4DA8"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py index 53c44f6ea2..c3693a7b21 100644 --- a/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py +++ b/src/sst/elements/carcosa/tests/testCorruptMemDoubleOverlap.py @@ -498,8 +498,7 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) #TODO: fix bug here :) memctrl.addPortModule("highlink", "carcosa.CorruptMemFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "regions": ["4D88, 4DA0", "4D90, 4DA8"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testRandomDrop.py b/src/sst/elements/carcosa/tests/testRandomDrop.py index f8a9e1951d..f6de6aaaff 100644 --- a/src/sst/elements/carcosa/tests/testRandomDrop.py +++ b/src/sst/elements/carcosa/tests/testRandomDrop.py @@ -498,8 +498,8 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.RandomDropFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 0.25, + "install_direction": "Receive", + "injection_probability": 1.0, "debug" : 1, "debug_level": 2 }) diff --git a/src/sst/elements/carcosa/tests/testRandomFlip.py b/src/sst/elements/carcosa/tests/testRandomFlip.py index 6ecebfa294..d3a1d9ef16 100644 --- a/src/sst/elements/carcosa/tests/testRandomFlip.py +++ b/src/sst/elements/carcosa/tests/testRandomFlip.py @@ -498,8 +498,8 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.RandomFlipFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 0.25, + "install_direction": "Receive", + "injection_probability": 0.25, "seed": 156, "debug" : 1, "debug_level": 1 diff --git a/src/sst/elements/carcosa/tests/testStuckAtBasic.py b/src/sst/elements/carcosa/tests/testStuckAtBasic.py index a289d5a5e9..29ece08d5f 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtBasic.py +++ b/src/sst/elements/carcosa/tests/testStuckAtBasic.py @@ -497,8 +497,7 @@ def addParamsPrefix(prefix,params): memctrl = sst.Component("memory", "memHierarchy.MemController") memctrl.addParams( memCtrlParams ) memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "masks": ["4D88, 3, 11110000, 00001111"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testStuckAtMultiple.py b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py index dcd1156c56..467a22c30f 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtMultiple.py +++ b/src/sst/elements/carcosa/tests/testStuckAtMultiple.py @@ -498,8 +498,7 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "intall_direction": "Receive", "masks": ["4D88, 3, 11110000, 00001111", "4D90, 3, 11110000, 00001111"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testStuckAtOverlap.py b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py index ccf39f831f..945e8880b5 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtOverlap.py +++ b/src/sst/elements/carcosa/tests/testStuckAtOverlap.py @@ -498,8 +498,7 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "masks": ["4D88, 3, 11111111, 11111111"], "debug" : 1, "debug_level": 2 diff --git a/src/sst/elements/carcosa/tests/testStuckAtSameByte.py b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py index a0c31ede53..11b7b86987 100644 --- a/src/sst/elements/carcosa/tests/testStuckAtSameByte.py +++ b/src/sst/elements/carcosa/tests/testStuckAtSameByte.py @@ -498,8 +498,7 @@ def addParamsPrefix(prefix,params): memctrl.addParams( memCtrlParams ) # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.StuckAtFaultInjector", { - "intallDirection": "Receive", - "injectionProbability": 1.0, + "install_direction": "Receive", "masks": ["4D88, 3, 11110000, 00001111", "4D88, 5, 11110000, 00001111"], "debug" : 1, "debug_level": 2 From 0fe6ca76b3a7fc5b7b701ab03cfdd752a1ef40b4 Mon Sep 17 00:00:00 2001 From: Michael Goldstein Date: Fri, 30 Jan 2026 16:09:51 -0500 Subject: [PATCH 45/45] hopefully fixed trailing white space --- src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc | 2 +- src/sst/elements/carcosa/tests/testRandomDrop.py | 2 +- src/sst/elements/carcosa/tests/testRandomFlip.py | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc index c2c2da126e..1dcbddec05 100644 --- a/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc +++ b/src/sst/elements/carcosa/injectors/dropFlipFaultInjector.cc @@ -59,7 +59,7 @@ bool DropFlipFaultInjector::doInjection() { this->triggered_injection_[1] = true; } else { -#ifdef __SST_DEBUG_OUTPUT__ +#ifdef __SST_DEBUG_OUTPUT__ dbg_->debug(CALL_INFO_LONG, 1, 0, "Flip skipped.\n"); #endif this->triggered_injection_[1] = false; diff --git a/src/sst/elements/carcosa/tests/testRandomDrop.py b/src/sst/elements/carcosa/tests/testRandomDrop.py index f6de6aaaff..716086b8de 100644 --- a/src/sst/elements/carcosa/tests/testRandomDrop.py +++ b/src/sst/elements/carcosa/tests/testRandomDrop.py @@ -499,7 +499,7 @@ def addParamsPrefix(prefix,params): # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.RandomDropFaultInjector", { "install_direction": "Receive", - "injection_probability": 1.0, + "injection_probability": 0.01, "debug" : 1, "debug_level": 2 }) diff --git a/src/sst/elements/carcosa/tests/testRandomFlip.py b/src/sst/elements/carcosa/tests/testRandomFlip.py index d3a1d9ef16..cd251ef2c8 100644 --- a/src/sst/elements/carcosa/tests/testRandomFlip.py +++ b/src/sst/elements/carcosa/tests/testRandomFlip.py @@ -499,8 +499,8 @@ def addParamsPrefix(prefix,params): # SHOULD FAIL TO INITIALIZE memctrl.addPortModule("highlink", "carcosa.RandomFlipFaultInjector", { "install_direction": "Receive", - "injection_probability": 0.25, - "seed": 156, + "injection_probability": 0.001, + #"seed": 156, "debug" : 1, "debug_level": 1 })