diff --git a/src/sst/core/Makefile.am b/src/sst/core/Makefile.am index 35d39857e..de60e5873 100644 --- a/src/sst/core/Makefile.am +++ b/src/sst/core/Makefile.am @@ -96,6 +96,9 @@ nobase_dist_sst_HEADERS = \ serialization/serialize_impl_fwd.h \ serialization/objectMap.h \ serialization/objectMapDeferred.h \ + serialization/objectMapTreeBuilder.h \ + serialization/ObjTree.h \ + serialization/ObjTreeLeaves.h \ serialization/impl/serialize_adapter.h \ serialization/impl/serialize_aggregate.h \ serialization/impl/serialize_array.h \ diff --git a/src/sst/core/from_string.h b/src/sst/core/from_string.h index db858a602..72d79ba9b 100644 --- a/src/sst/core/from_string.h +++ b/src/sst/core/from_string.h @@ -165,7 +165,7 @@ to_string(const T& input) if constexpr ( std::is_floating_point_v ) { std::ostringstream s; T abs_val = input < 0 ? -input : input; - if ( abs_val > (T)10e6 || abs_val < (T)10e-6 ) + if ( abs_val > (T)1e6 || abs_val < (T)1e-6 ) s << std::scientific << std::setprecision(std::numeric_limits::max_digits10) << input; else s << std::fixed << std::setprecision(std::numeric_limits::max_digits10) << input; diff --git a/src/sst/core/impl/interactive/Makefile.inc b/src/sst/core/impl/interactive/Makefile.inc index a9ac8d954..2b196ec9f 100644 --- a/src/sst/core/impl/interactive/Makefile.inc +++ b/src/sst/core/impl/interactive/Makefile.inc @@ -10,4 +10,5 @@ sst_core_sources += \ impl/interactive/cmdLineEditor.h \ impl/interactive/debugCommands.h \ impl/interactive/debugStream.h \ - impl/interactive/debugStream.cc \ No newline at end of file + impl/interactive/debugStream.cc \ + impl/interactive/ObjTreeHelpers.cc \ No newline at end of file diff --git a/src/sst/core/impl/interactive/NumericHandle.h b/src/sst/core/impl/interactive/NumericHandle.h new file mode 100644 index 000000000..ce056983f --- /dev/null +++ b/src/sst/core/impl/interactive/NumericHandle.h @@ -0,0 +1,219 @@ +// 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/core/serialization/ObjTree.h" + +#include +#include + +namespace SST::Core::Serialization { +// A lightweight non-owning handle returned by findByName that enables +// direct comparisons against constants and other tree nodes. +// +// Usage: +// NumericHandle a = NumericHandle::from(root->findByName("counter")); +// NumericHandle b = NumericHandle::from(root->findByName("threshold")); +// +// if (a < 42) { ... } // compare against int constant +// if (a < 3.14) { ... } // compare against double constant +// if (a < b) { ... } // compare two tree nodes + +class NumericHandle +{ +public: + enum class Kind { None, Integer, Float, Bool, Cont }; + +private: + ObjTreeCont* node_ = nullptr; + Kind kind_ = Kind::None; + + NumericHandle(ObjTreeCont* n, Kind k) : + node_(n), + kind_(k) + {} + +public: + NumericHandle() = default; + + static NumericHandle from(ObjTreeCont* node) + { + if ( !node ) return {}; + if ( dynamic_cast(node) ) return { node, Kind::Integer }; + if ( dynamic_cast(node) ) return { node, Kind::Float }; + if ( dynamic_cast(node) ) return { node, Kind::Bool }; + if ( dynamic_cast(node) ) return { node, Kind::Cont }; + return {}; + } + + explicit operator bool() const { return kind_ != Kind::None; } + Kind getKind() const { return kind_; } + ObjTreeCont* getNode() const { return node_; } + + IntegerObj* asInteger() const { return dynamic_cast(node_); } + FloatObj* asFloat() const { return dynamic_cast(node_); } + BoolObj* asBool() const { return dynamic_cast(node_); } + ContainerObj* asCont() const { return dynamic_cast(node_); } + + // ── Compare handle <=> handle ──────────────────────────────── + bool operator<(const NumericHandle& rhs) const { return cmpHandle(rhs, std::less<> {}); } + bool operator>(const NumericHandle& rhs) const { return rhs < *this; } + bool operator<=(const NumericHandle& rhs) const { return !(rhs < *this); } + bool operator>=(const NumericHandle& rhs) const { return !(*this < rhs); } + bool operator==(const NumericHandle& rhs) const { return !(*this < rhs) && !(rhs < *this); } + bool operator!=(const NumericHandle& rhs) const { return !(*this == rhs); } + + // ── Compare handle <=> arithmetic constant ─────────────────── + // A single template for every numeric type avoids the int64_t vs + // double ambiguity that plain overloads cause. + + template >> + bool operator<(T rhs) const + { + return cmpConst(rhs, std::less<> {}); + } + + template >> + bool operator>(T rhs) const + { + return cmpConst(rhs, std::greater<> {}); + } + + template >> + bool operator<=(T rhs) const + { + return cmpConst(rhs, std::less_equal<> {}); + } + + template >> + bool operator>=(T rhs) const + { + return cmpConst(rhs, std::greater_equal<> {}); + } + + template >> + bool operator==(T rhs) const + { + return cmpConst(rhs, std::equal_to<> {}); + } + + template >> + bool operator!=(T rhs) const + { + return cmpConst(rhs, std::not_equal_to<> {}); + } + +private: + // Visit both sides' variants and compare directly. + template + bool cmpHandle(const NumericHandle& rhs, Cmp cmp) const + { + if ( !*this || !rhs ) return false; + + // Lambda that visits the RHS given a concrete LHS value + auto visitRhs = [&](auto lhsVal) -> bool { + auto inner = [&](auto rhsVal) -> bool { + if constexpr ( std::is_integral_v && std::is_integral_v ) { + using Common = std::common_type_t; + return cmp(static_cast(lhsVal), static_cast(rhsVal)); + } + else { + return cmp(static_cast(lhsVal), static_cast(rhsVal)); + } + }; + if ( rhs.kind_ == Kind::Integer ) return rhs.asInteger()->visit(inner); + if ( rhs.kind_ == Kind::Float ) return rhs.asFloat()->visit(inner); + if ( rhs.kind_ == Kind::Bool ) return inner(static_cast(rhs.asBool()->getVal())); + if ( rhs.kind_ == Kind::Cont ) return inner(static_cast(rhs.asCont()->getSize())); + return false; + }; + + if ( kind_ == Kind::Integer ) return asInteger()->visit(visitRhs); + if ( kind_ == Kind::Float ) return asFloat()->visit(visitRhs); + if ( kind_ == Kind::Bool ) return visitRhs(static_cast(asBool()->getVal())); + if ( kind_ == Kind::Cont ) return visitRhs(static_cast(asCont()->getSize())); + return false; + } + + // Visit the held variant and apply `cmp` against any arithmetic constant. + // Integer-to-integer comparisons stay exact; anything involving a + // floating-point side is promoted to long double to preserve precision. + template + bool cmpConst(ConstT rhs, Cmp cmp) const + { + if ( kind_ == Kind::Integer ) { + return asInteger()->visit([&](auto lhs) { + if constexpr ( std::is_integral_v && std::is_integral_v ) { + // Both sides integral — compare without floating-point loss + using Common = std::common_type_t; + return cmp(static_cast(lhs), static_cast(rhs)); + } + else { + return cmp(static_cast(lhs), static_cast(rhs)); + } + }); + } + if ( kind_ == Kind::Float ) { + return asFloat()->visit( + [&](auto lhs) { return cmp(static_cast(lhs), static_cast(rhs)); }); + } + if ( kind_ == Kind::Bool ) { + auto lhs = static_cast(asBool()->getVal()); + if constexpr ( std::is_integral_v ) { + using Common = std::common_type_t; + return cmp(static_cast(lhs), static_cast(rhs)); + } + else { + return cmp(static_cast(lhs), static_cast(rhs)); + } + } + if ( kind_ == Kind::Cont ) { + auto lhs = asCont()->getSize(); + if constexpr ( std::is_integral_v ) { + using Common = std::common_type_t; + return cmp(static_cast(lhs), static_cast(rhs)); + } + else { + return cmp(static_cast(lhs), static_cast(rhs)); + } + } + return false; + } +}; + +// ── Reverse comparisons (constant <=> handle) ─────────────────── +template >> +bool +operator<(T lhs, const NumericHandle& rhs) +{ + return rhs > lhs; +} + +template >> +bool +operator>(T lhs, const NumericHandle& rhs) +{ + return rhs < lhs; +} + +template >> +bool +operator<=(T lhs, const NumericHandle& rhs) +{ + return rhs >= lhs; +} + +template >> +bool +operator>=(T lhs, const NumericHandle& rhs) +{ + return rhs <= lhs; +} +}; // namespace SST::Core::Serialization diff --git a/src/sst/core/impl/interactive/ObjMapToTree.h b/src/sst/core/impl/interactive/ObjMapToTree.h new file mode 100644 index 000000000..7cbd7c99d --- /dev/null +++ b/src/sst/core/impl/interactive/ObjMapToTree.h @@ -0,0 +1,381 @@ +// 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_CORE_SERIALIZATION_OBJECTMAPTOTREE_DEBUGGER_H +#define SST_CORE_SERIALIZATION_OBJECTMAPTOTREE_DEBUGGER_H + +#include "sst/core/serialization/ObjTree.h" +#include "sst/core/serialization/objectMapTreeBuilder.h" + +#include +#include +#include +#include + +namespace SST::Core::Serialization { + +class ObjectMapToTree +{ + using IntVariant = IntegerObj::IntVariant; + using FloatVariant = FloatObj::FloatVariant; + + // Known integer type strings + static bool isIntegerType(const std::string& type) + { + static const std::unordered_set intTypes = { "signed char", "int8_t", "char", "short", "int16_t", + "int", "int32_t", "long", "long long", "int64_t", "unsigned char", "uint8_t", "unsigned short", "uint16_t", + "unsigned int", "unsigned", "uint32_t", "unsigned long", "unsigned long long", "uint64_t" }; + return intTypes.count(type) > 0; + } + + static bool isFloatType(const std::string& type) + { + return type == "float" || type == "double" || type == "long double"; + } + + static bool isStringType(const std::string& type) + { + // Demangled std::string can appear in various forms + return type.find("std::string") != std::string::npos || + type.find("std::__cxx11::basic_string") != std::string::npos || + type.find("basic_string") != std::string::npos; + } + + static bool isContainerType(const std::string& type) + { + return type.find("std::vector") != std::string::npos || type.find("std::map") != std::string::npos || + type.find("std::unordered_map") != std::string::npos || type.find("std::set") != std::string::npos || + type.find("std::unordered_set") != std::string::npos || type.find("std::list") != std::string::npos || + type.find("std::deque") != std::string::npos || type.find("std::multimap") != std::string::npos || + type.find("std::array") != std::string::npos; + } + + static std::unique_ptr makeIntegerObj(const std::string& type, void* addr) + { + if ( !addr ) return nullptr; + if ( type == "signed char" || type == "int8_t" || type == "char" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "short" || type == "int16_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "int" || type == "int32_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "long" || type == "long long" || type == "int64_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "unsigned char" || type == "uint8_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "unsigned short" || type == "uint16_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "unsigned int" || type == "unsigned" || type == "uint32_t" ) + return std::make_unique(*static_cast(addr), addr); + if ( type == "unsigned long" || type == "unsigned long long" || type == "uint64_t" ) + return std::make_unique(*static_cast(addr), addr); + return nullptr; + } + + static std::unique_ptr makeFloatObj(const std::string& type, void* addr) + { + if ( !addr ) return nullptr; + if ( type == "float" ) return std::make_unique(*static_cast(addr), addr); + if ( type == "double" ) return std::make_unique(*static_cast(addr), addr); + if ( type == "long double" ) return std::make_unique(*static_cast(addr), addr); + return nullptr; + } + +public: + // Convert a single ObjectMap* into an ObjTreeCont* + // Caller takes ownership of the returned pointer + static ObjTreeCont* convert(const std::string& name, ObjectMap* objMap, bool recursive = true) + { + if ( !objMap ) return nullptr; + + const std::string type = objMap->getType(); + void* addr = objMap->getAddr(); + + if ( objMap->isFundamental() ) { + if ( type == "bool" && addr ) { + // handle bitset and vector case + auto* ref = objMap->buildTreeNode(name); + if ( ref ) { + return ref; + } + // standard case + auto* o = new BoolObj(*static_cast(addr), addr); + o->setName(name); + o->setType(type); + return o; + } + if ( isIntegerType(type) ) { + // handle fundamental ref case + auto* ref = objMap->buildTreeNode(name); + if ( ref ) { + return ref; + } + // standard case + if ( auto o = makeIntegerObj(type, addr) ) { + o->setName(name); + o->setType(type); + if ( objMap->isReadOnly() ) { + o->makeReadOnly(); + } + return o.release(); + } + } + if ( isFloatType(type) ) { + // handle fundamental ref case + auto* ref = objMap->buildTreeNode(name); + if ( ref ) { + return ref; + } + // standard case + if ( auto o = makeFloatObj(type, addr) ) { + o->setName(name); + o->setType(type); + if ( objMap->isReadOnly() ) { + o->makeReadOnly(); + } + return o.release(); + } + } + if ( isStringType(type) && addr ) { + auto* o = new StringObj(*static_cast(addr), addr); + o->setName(name); + o->setType(type); + if ( objMap->isReadOnly() ) { + o->makeReadOnly(); + } + return o; + } + // Unknown fundamental — wrap in GenericObj with the value as string + // Note: we pass a nullptr in for objMap as the objMap used here is destroyed by the caller + // If it is necessary to set one of these generic values we will need to preserve the + // value of objMap. For now, we just pass in a nullptr rather than carry the (potentially) + // heavy ObjMap around in this container + auto* g = new GenericValObj(objMap->get(), addr, nullptr); + g->setName(name); + g->setType(type); + if ( objMap->isReadOnly() ) { + g->makeReadOnly(); + } + return g; + } + + if ( objMap->isContainer() || isContainerType(type) ) { + const auto& vars = objMap->getVariables(); + auto* c = new ContainerObj(name, type, vars.size(), nullptr); + for ( const auto& [n, m] : vars ) + if ( auto* child = convert(n, m, recursive) ) c->addChildObj(child); + return c; + } + + if ( objMap->getCategory() == ObjectMap::ObjectCategory::Component ) { + if ( auto* comp = static_cast(addr) ) { + auto* co = new ComponentObj(comp, nullptr); + co->setName(name); + co->setType(type); + if ( objMap->isReadOnly() ) { + co->makeReadOnly(); + } + return co; + } + } + + auto* node = new ObjTreeCont(name, type); + if ( recursive ) { + for ( const auto& [n, m] : objMap->getVariables() ) + if ( auto* child = convert(n, m, false) ) node->addChildObj(child); + } + return node; + } + + static void addChildrenFromMap(ObjTreeCont* parent, const ObjectMultimap& variables) + { + if ( !parent ) return; + for ( const auto& [name, objMap] : variables ) { + ObjTreeCont* child = convert(name, objMap, false); + if ( child ) parent->addChildObj(child); + } + } + + static void addChildrenFromMapRecursive(ObjTreeCont* parent, const ObjectMultimap& variables) + { + if ( !parent ) return; + for ( const auto& [name, objMap] : variables ) { + ObjTreeCont* child = convert(name, objMap, true); + if ( child ) parent->addChildObj(child); + } + } + + // Convert an entire ObjectMap's variables into an ObjTreeCont tree + static std::unique_ptr convertTree(const std::string& rootName, ObjectMap* objMap) + { + auto root = std::make_unique(rootName, objMap->getType()); + const auto& variables = objMap->getVariables(); + for ( const auto& [name, childMap] : variables ) { + ObjTreeCont* child = convert(name, childMap, true); + if ( child ) { + root->addChildObj(child); + } + } + return root; + } + + /** + * Takes a ComponentObj, serializes its BaseComponent via + * ObjectMapDeferred, and populates the ComponentObj's children + * with the serialized variables. + * + * @param compNode The ComponentObj node to expand + * @param recursive If true, recursively convert all children + * @return true if serialization succeeded + */ + static bool serializeComponent(ComponentObj* compNode, bool recursive = false) + { + if ( !compNode ) return false; + + BaseComponent* comp = compNode->getVal(); + if ( !comp ) return false; + + ComponentInfo* compInfo = compNode->getInfo(); + + + // Create a temporary deferred map and trigger serialization + ComponentSerializer serializer(comp); + serializer.serialize(); + + if ( serializer.hasSerialized() ) { + const auto& variables = serializer.getVariables(); + + // Collect sub-component addresses so we skip them during conversion + std::vector subCompAddrs; + if ( compInfo ) { + collectSubComponentAddrs(compInfo, subCompAddrs); + } + + for ( const auto& [name, objMap] : variables ) { + if ( !objMap ) continue; + + // Skip variables that are sub-components + if ( std::find(subCompAddrs.begin(), subCompAddrs.end(), objMap->getAddr()) != subCompAddrs.end() ) + continue; + + // ObjTreeCont* child = recursive + // ? convert(name, objMap) + // : convertNode(name, objMap); + ObjTreeCont* child = convert(name, objMap, recursive); + if ( child ) compNode->addChildObj(child); + } + } + + // Serialize sub-components from ComponentInfo + if ( compInfo ) { + serializeSubComponents(compNode, compInfo, recursive); + } + + return true; + } + + /** + * Serialize all ComponentObj children of a given node. + * + * @param parent The parent node whose ComponentObj children to expand + * @param recursive If true, recursively convert all grandchildren + */ + static void serializeAllComponents(ObjTreeCont* parent, bool recursive = false) + { + if ( !parent ) return; + + parent->applyRecursiveByType( + [recursive](ComponentObj* comp) { serializeComponent(comp, recursive); }); + } + + /** + * Full pipeline: convert an ObjectMap tree, then serialize + * any ComponentObj nodes found in the result. + * + * @param rootName Name for the root node + * @param objMap Source ObjectMap to convert + * @param recursive If true, fully expand all levels + * @return Root of the converted and serialized tree + */ + static std::unique_ptr convertAndSerialize( + const std::string& rootName, ObjectMap* objMap, bool recursive = true) + { + auto root = convertTree(rootName, objMap); + if ( !root ) return nullptr; + + // Serialize all component nodes in the tree + serializeAllComponents(root.get(), recursive); + + return root; + } + +private: + static void collectSubComponentAddrs(ComponentInfo* compInfo, std::vector& addrs) + { + auto& subComps = compInfo->getSubComponents(); + + for ( auto it = subComps.begin(); it != subComps.end(); ++it ) { + + BaseComponent* sub = it->second.getComponent(); + if ( sub ) { + addrs.push_back(static_cast(sub)); + } + } + } + + static void serializeSubComponents(ObjTreeCont* parent, ComponentInfo* compInfo, bool recursive) + { + auto& subComps = compInfo->getSubComponents(); + for ( auto& [compId, subInfo] : subComps ) { + BaseComponent* sub = subInfo.getComponent(); + if ( !sub ) continue; + + auto* subObj = new ComponentObj(sub, &subInfo); + subObj->setName(subInfo.getName()); + subObj->setType(subInfo.getType()); + + // Serialize this sub-component's own variables + ComponentSerializer subSerializer(sub); + subSerializer.serialize(); + + if ( subSerializer.hasSerialized() ) { + const auto& subVars = subSerializer.getVariables(); + + // Collect nested sub-component addresses + std::vector nestedAddrs; + collectSubComponentAddrs(&subInfo, nestedAddrs); + + for ( const auto& [name, objMap] : subVars ) { + if ( !objMap ) continue; + if ( std::find(nestedAddrs.begin(), nestedAddrs.end(), objMap->getAddr()) != nestedAddrs.end() ) + continue; + + // ObjTreeCont* child = recursive + // ? convert(name, objMap) + // : convertNode(name, objMap); + ObjTreeCont* child = convert(name, objMap, recursive); + if ( child ) subObj->addChildObj(child); + } + } + + // Recurse into this sub-component's own sub-components + if ( recursive ) { + serializeSubComponents(subObj, &subInfo, recursive); + } + + parent->addChildObj(subObj); + } + } +}; + +} // namespace SST::Core::Serialization + +#endif diff --git a/src/sst/core/impl/interactive/ObjTree.h b/src/sst/core/impl/interactive/ObjTree.h new file mode 100644 index 000000000..77d29e392 --- /dev/null +++ b/src/sst/core/impl/interactive/ObjTree.h @@ -0,0 +1,985 @@ +// 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_CORE_SERIALIZATION_OBJECTTREE_DEBUGGER_H +#define SST_CORE_SERIALIZATION_OBJECTTREE_DEBUGGER_H + +#include "sst/core/baseComponent.h" +#include "sst/core/componentInfo.h" +#include "sst/core/from_string.h" +#include "sst/core/serialization/objectMapDeferred.h" +#include "sst/core/warnmacros.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SST::Core::Serialization { + +class ObjTreeCont +{ +public: + enum class NodeKind { Generic, Integer, Float, String, Bool, Component, Container, GenericVal }; + + ObjTreeCont() : + parent_(nullptr), + children_(), + name_("uninit"), + type_("uninit"), + kind_(NodeKind::Generic), + readOnly_(false) {}; + ObjTreeCont(const std::string& name, const std::string& type, NodeKind kind = NodeKind::Generic) : + parent_(nullptr), + children_(), + name_(name), + type_(type), + kind_(kind), + readOnly_(false) + {} + virtual ~ObjTreeCont() = default; + + ObjTreeCont(const ObjTreeCont& rhs) : + parent_(nullptr), + children_(), + name_(rhs.name_), + type_(rhs.type_), + kind_(rhs.kind_), + readOnly_(rhs.readOnly_) + { + children_.reserve(rhs.children_.size()); + for ( const auto& child : rhs.children_ ) { + auto* cloned = child->clone(); + cloned->parent_ = this; + children_.emplace_back(cloned); + } + } + + ObjTreeCont& operator=(const ObjTreeCont& rhs) + { + if ( this == &rhs ) return *this; + parent_ = nullptr; + name_ = rhs.name_; + type_ = rhs.type_; + kind_ = rhs.kind_; + children_.clear(); + children_.reserve(rhs.children_.size()); + for ( const auto& child : rhs.children_ ) { + auto* cloned = child->clone(); + cloned->parent_ = this; + children_.emplace_back(cloned); + } + return *this; + } + + virtual ObjTreeCont* clone() const { return new ObjTreeCont(*this); } + + void addChildObj(ObjTreeCont* obj) + { + children_.push_back(std::unique_ptr(obj)); + obj->parent_ = this; + } + + void setParent(ObjTreeCont* p) { parent_ = p; } + ObjTreeCont* getParent() const { return parent_; } + const std::vector>& getChildren() const { return children_; } + + const std::string& getObjName() const { return name_; } + const std::string& getType() const { return type_; } + void setName(const std::string& name) { name_ = name; } + void setType(const std::string& type) { type_ = prettifyType(type); } + bool isRoot() { return parent_ == nullptr; } + void makeReadOnly() { readOnly_ = true; } + bool isReadOnly() { return readOnly_; } + + template + void applyRecursive(Func&& func) + { + for ( auto& child : children_ ) { + func(child.get()); + } + } + + template + void applyRecursiveByType(Func&& func) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + func(child_t); + } + } + } + + template + ObjectType* findByType(Func&& predicate) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + if ( predicate(child_t) ) return child_t; + } + } + return nullptr; + } + + ObjTreeCont* findByName(const std::string name) + { + for ( size_t i = 0; i < children_.size(); i++ ) { + if ( children_[i]->getObjName() == name ) { + return children_[i].get(); + } + } + return nullptr; + } + + virtual void apply() {}; + virtual std::string getTypeName() const { return type_; }; + virtual void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) + { + os << name_ << "/ " << std::endl; //(" << type_ << ")" << std::endl; + if ( verbosity > 0 ) { + applyRecursive([&](ObjTreeCont* child) { child->Dump(verbosity - 1, base, os); }); + } + } + + virtual bool setFromString([[maybe_unused]] const std::string& value) { return false; } + virtual void syncFromSim() {}; + virtual bool hasChanged() { return false; } + + NodeKind getKind() const { return kind_; } + bool isComponent() const { return kind_ == NodeKind::Component; } + bool isLeaf() const + { + return kind_ == NodeKind::Integer || kind_ == NodeKind::Float || kind_ == NodeKind::String || + kind_ == NodeKind::Bool || kind_ == NodeKind::GenericVal; + } + + virtual void clear() { children_.clear(); } + +protected: + ObjTreeCont* parent_; + std::vector> children_; + std::string name_; + std::string type_; + NodeKind kind_; + bool readOnly_; + + static void replaceAll(std::string& s, std::string_view from, std::string_view to) + { + if ( from.empty() ) return; + size_t pos = 0; + while ( (pos = s.find(from, pos)) != std::string::npos ) { + s.replace(pos, from.size(), to); + pos += to.size(); + } + } + + static std::string prettifyType(std::string t) + { + replaceAll(t, "std::__1::", "std::"); + replaceAll(t, "std::__cxx11::", "std::"); + replaceAll(t, " ", " "); + return t; + } +}; + +template +class ObjTree : public ObjTreeCont +{ +public: + ObjTree() = default; + ObjTree(NodeKind kind) : + ObjTreeCont("", "", kind) + {} + + ObjTree(const ObjTree& rhs) : + ObjTreeCont(rhs), + objects_() + { + objects_.reserve(rhs.objects_.size()); + for ( const auto& obj : rhs.objects_ ) { + auto* cloned = obj->clone(); + cloned->setParent(this); + objects_.emplace_back(cloned); + } + } + + ObjTree& operator=(const ObjTree& other) + { + if ( this == &other ) return *this; + ObjTreeCont::operator=(other); + objects_.clear(); + objects_.reserve(other.objects_.size()); + for ( const auto& obj : other.objects_ ) { + auto* cloned = obj->clone(); + cloned->setParent(this); + objects_.emplace_back(cloned); + } + return *this; + } + + void BuildTree(const ComponentInfoMap& compMap); + + Obj_T& getObj() { return static_cast(*this); } + const Obj_T& getObj() const { return static_cast(*this); } + + + template + void applyRecursiveByType(Func&& func) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + func(child_t); + } + } + } + + std::string getTypeName() const override { return typeid(Obj_T).name(); } + + bool isEmpty() { return objects_.empty() && children_.empty(); } + + void Dump([[maybe_unused]] const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + os << "Root/" << std::endl; + } + void clear() override + { + ObjTreeCont::clear(); + objects_.clear(); + } + +protected: + std::vector> objects_; +}; + +class IntegerObj : public ObjTree +{ +public: + using IntVariant = std::variant; + +private: + IntVariant val_; + void* addr_; + +public: + template + IntegerObj(T v, void* addr) : + ObjTree(NodeKind::Integer), + val_(v), + addr_(addr) + {} + + IntegerObj(const IntegerObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_) + {} + IntegerObj& operator=(const IntegerObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + return *this; + } + ObjTreeCont* clone() const override { return new IntegerObj(*this); } + + template + T getVal() const + { + return std::get(val_); + } + + template + void setVal(T v) + { + val_ = v; + } + + template + void setSimVal(T v) + { + val_ = v; + syncToSim(); + } + + virtual void syncFromSim() override + { + if ( !addr_ ) return; + std::visit([this](auto& v) { v = *static_cast*>(addr_); }, val_); + } + + virtual bool hasChanged() override + { + if ( !addr_ ) return false; + return std::visit( + [this](const auto& v) -> bool { return v != *static_cast*>(addr_); }, val_); + } + + template + auto visit(Visitor&& visitor) + { + return std::visit(std::forward(visitor), val_); + } + + template + auto visit(Visitor&& visitor) const + { + return std::visit(std::forward(visitor), val_); + } + + void apply() override + { + visit([](auto val) { std::cout << "Processing integer: " << static_cast(val) << std::endl; }); + } + + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + visit([&](auto val) { + auto old_flags = os.flags(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << " = " << static_cast(val) << std::endl; + os.flags(old_flags); + }); + } + else { + visit([&](auto val) { + auto old_flags = os.flags(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << " = " << static_cast(val) << " (" << getType() << ")" << std::endl; + os.flags(old_flags); + }); + } + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + return false; + } + try { + visit([&](auto& current) { + using T = std::decay_t; + setSimVal(static_cast(std::stoll(value))); + }); + return true; + } + catch ( ... ) { + return false; + } + } + +private: + void syncToSim() + { + if ( !addr_ ) return; + std::visit([this](auto& v) { *static_cast*>(addr_) = v; }, val_); + } +}; + +class FloatObj : public ObjTree +{ +public: + using FloatVariant = std::variant; + +private: + FloatVariant val_; + void* addr_; + +public: + template + FloatObj(T v, void* addr) : + ObjTree(NodeKind::Float), + val_(v), + addr_(addr) + {} + + FloatObj(const FloatObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_) + {} + + FloatObj& operator=(const FloatObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + return *this; + } + + ObjTreeCont* clone() const override { return new FloatObj(*this); } + + template + T getVal() const + { + return std::get(val_); + } + + template + void setVal(T v) + { + val_ = v; + } + + template + void setSimVal(T v) + { + val_ = v; + syncToSim(); + } + + virtual void syncFromSim() override + { + if ( !addr_ ) return; + std::visit([this](auto& v) { v = *static_cast*>(addr_); }, val_); + } + + virtual bool hasChanged() override + { + if ( !addr_ ) return false; + return std::visit( + [this](const auto& v) -> bool { return v != *static_cast*>(addr_); }, val_); + } + + template + auto visit(Visitor&& visitor) + { + return std::visit(std::forward(visitor), val_); + } + + template + auto visit(Visitor&& visitor) const + { + return std::visit(std::forward(visitor), val_); + } + + void apply() override + { + visit([](auto val) { std::cout << "Processing float: " << val << std::endl; }); + } + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + visit([&](auto val) { + auto old_flags = os.flags(); + auto old_prec = os.precision(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << std::fixed << std::setprecision(12) << " = " << val << std::endl; + os.flags(old_flags); + os.precision(old_prec); + }); + } + else { + visit([&](auto val) { + auto old_flags = os.flags(); + auto old_prec = os.precision(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << std::fixed << std::setprecision(12) << " = " << val << " (" << getType() + << ")" << std::endl; + os.flags(old_flags); + os.precision(old_prec); + }); + } + } + + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + return false; + } + try { + visit([&](auto& current) { + using T = std::decay_t; + setSimVal(static_cast(std::stold(value))); + }); + return true; + } + catch ( ... ) { + return false; + } + } + +private: + void syncToSim() + { + if ( !addr_ ) return; + std::visit([this](auto& v) { *static_cast*>(addr_) = v; }, val_); + } +}; + +class ComponentObj : public ObjTree +{ + +private: + BaseComponent* val_ = nullptr; + ComponentInfo* compInfo_ = nullptr; + +public: + ComponentObj() = default; + ComponentObj(BaseComponent* v, ComponentInfo* ci) : + ObjTree(NodeKind::Component), + val_(v), + compInfo_(ci) + { + setName(v->getName()); + } + + ComponentObj(const ComponentObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + compInfo_(rhs.compInfo_) + {} + + ComponentObj& operator=(const ComponentObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + compInfo_ = rhs.compInfo_; + return *this; + } + + ObjTreeCont* clone() const override { return new ComponentObj(*this); } + + BaseComponent* getVal() const { return val_; } + ComponentInfo* getInfo() const { return compInfo_; } + + void setVal(BaseComponent* v) { val_ = v; } + + void apply() override { std::cout << "Processing component: " << val_->getName() << std::endl; } + void Dump([[maybe_unused]] const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + if ( verbosity < 3 ) + os << val_->getName() << "/" << std::endl; + else + os << val_->getName() << "/ (" << compInfo_->getType() << ")" << std::endl; + } + + ComponentObj* find(const std::string name) + { + ComponentObj* result = nullptr; + applyRecursiveByType([&result, &name](ComponentObj* obj) { + if ( obj->getVal()->getName() == name ) { + result = obj; + } + }); + return result; + } +}; + +template +void +ObjTree::BuildTree(const ComponentInfoMap& compMap) +{ + if ( !children_.empty() ) { + std::cout << "WARNING: Calling BuildTree on non-empty ObjTree" << std::endl; + } + for ( auto comp = compMap.begin(); comp != compMap.end(); comp++ ) { + ComponentInfo* compinfo = *comp; + BaseComponent* bc = compinfo->getComponent(); + ComponentObj* c = new ComponentObj(bc, compinfo); + addChildObj(c); + } + + std::sort(children_.begin(), children_.end(), + [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->getObjName() < b->getObjName(); + }); +} + +class ContainerObj : public ObjTree +{ + size_t size_ = 0; + ObjectMap* sourceMap_ = nullptr; + +public: + ContainerObj(const std::string& name, const std::string& type, size_t size, ObjectMap* source) : + ObjTree(NodeKind::Container), + size_(size), + sourceMap_(source) + { + setName(name); + setType(type); + } + + ContainerObj(const ContainerObj& rhs) : + ObjTree(rhs), + size_(rhs.size_), + sourceMap_(rhs.sourceMap_) + { + setName(rhs.name_); + setType(rhs.type_); + } + + ContainerObj& operator=(const ContainerObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + name_ = rhs.name_; + type_ = rhs.type_; + size_ = rhs.size_; + sourceMap_ = rhs.sourceMap_; + return *this; + } + + ObjTreeCont* clone() const override { return new ContainerObj(*this); } + + + const std::string& getContainerType() const { return type_; } + size_t getSize() const { return size_; } + + void syncFromSim() override + { + if ( !sourceMap_ ) return; + size_ = sourceMap_->getVariables().size(); // or cheaper accessor if available + } + + bool hasChanged() override + { + if ( !sourceMap_ ) return false; + return size_ != sourceMap_->getVariables().size(); + } + + void apply() override { std::cout << "Container: " << name_ << " (" << type_ << ") size=" << size_ << std::endl; } + + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + if ( verbosity == 0 ) { + os << name_ << " [" << size_ << " elements] (" << type_ << ")" << std::endl; + } + else { + os << name_ << " [" << size_ << " elements] (" << type_ << ")" << std::endl; + applyRecursive([&](ObjTreeCont* child) { child->Dump(verbosity - 1, base, os); }); + } + } + + ObjTreeCont* getElementAt(std::vector indices) const + { + ObjTreeCont* current = const_cast(this); + + for ( size_t idx : indices ) { + if ( !current ) return nullptr; + + auto& elems = current->getChildren(); + if ( idx >= elems.size() ) return nullptr; + + current = elems[idx].get(); + } + return current; + } + + void printElementAt(std::vector indices, int verbosity = 1, + std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) const + { + ObjTreeCont* elem = getElementAt(indices); + if ( elem ) { + elem->Dump(verbosity, base, os); + } + else { + os << "Element not found at path {"; + bool first = true; + for ( auto i : indices ) { + if ( !first ) os << ", "; + os << i; + first = false; + } + os << "}" << std::endl; + } + } + + bool setElementFromString(std::vector indices, std::string val) + { + ObjTreeCont* elem = getElementAt(indices); + bool success = elem != nullptr; + if ( elem ) { + success = elem->setFromString(val); + } + if ( !success ) { + std::cout << "Element not found at path {"; + bool first = true; + for ( auto i : indices ) { + if ( !first ) std::cout << ", "; + std::cout << i; + first = false; + } + std::cout << "}" << std::endl; + } + return success; + } +}; + +// Node for string types (treated specially since they're fundamental-like) +class StringObj : public ObjTree +{ + std::string val_; + void* addr_; + +public: + StringObj(const std::string& v, void* addr) : + ObjTree(NodeKind::String), + val_(v), + addr_(addr) + {} + StringObj(const StringObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_) + {} + + StringObj& operator=(const StringObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + return *this; + } + + ObjTreeCont* clone() const override { return new StringObj(*this); } + + const std::string& getVal() const { return val_; } + void setVal(const std::string& v) { val_ = v; } + void setSimVal(const std::string& v) + { + val_ = v; + *static_cast(addr_) = val_; + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + return false; + } + setSimVal(value); + return true; + } + virtual void syncFromSim() override { val_ = *static_cast(addr_); } + virtual bool hasChanged() override + { + if ( !addr_ ) return false; + return val_ != *static_cast(addr_); + } + + void apply() override { std::cout << "Processing string: " << val_ << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = \"" << val_ << "\"" << std::endl; + } + else { + os << getObjName() << ro << " = \"" << val_ << "\"" << " (" << getType() << ")" << std::endl; + } + } +}; + +// Node for bool (separate from integer for clarity) +class BoolObj : public ObjTree +{ + bool val_; + void* addr_; // This points back to the ObjectMap + +public: + BoolObj(bool v, void* addr) : + ObjTree(NodeKind::Bool), + val_(v), + addr_(addr) + {} + BoolObj(const BoolObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_) + {} + + BoolObj& operator=(const BoolObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + return *this; + } + + ObjTreeCont* clone() const override { return new BoolObj(*this); } + + bool getVal() const { return val_; } + void setVal(bool v) { val_ = v; } + void setSimVal(bool v) + { + *(static_cast(addr_)) = v; + val_ = v; + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + return false; + } + setSimVal(value == "true" || value == "1"); + return true; + } + virtual void syncFromSim() override { val_ = *(static_cast(addr_)); } + virtual bool hasChanged() override + { + if ( !addr_ ) return false; + return val_ != *static_cast(addr_); + } + + void apply() override { std::cout << "Processing bool: " << (val_ ? "true" : "false") << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = " << (val_ ? "true" : "false") << std::endl; + } + else { + os << getObjName() << ro << " = " << (val_ ? "true" : "false") << " (" << getType() << ")" << std::endl; + } + } +}; + +class GenericValObj : public ObjTree +{ + std::string val_; + void* addr_ = nullptr; + ObjectMap* sourceMap_ = nullptr; // for write-back via string interface + +public: + GenericValObj(const std::string& val, void* addr, ObjectMap* source) : + ObjTree(NodeKind::GenericVal), + val_(val), + addr_(addr), + sourceMap_(source) + {} + + GenericValObj(const GenericValObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_), + sourceMap_(rhs.sourceMap_) + {} + + GenericValObj& operator=(const GenericValObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + sourceMap_ = rhs.sourceMap_; + return *this; + } + + ObjTreeCont* clone() const override { return new GenericValObj(*this); } + + const std::string& getVal() const { return val_; } + + // Write-back through ObjectMap's string-based set interface, + // which knows the real type and handles conversion internally. + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + return false; + } + if ( !sourceMap_ ) return false; + if ( sourceMap_->isReadOnly() ) return false; + sourceMap_->set(value); + // Re-read to confirm the value was accepted + val_ = sourceMap_->get(); + return true; + } + + // NOTE: we are currently not carrying around sourceMap so this + // will ALWAYS return false + bool hasChanged() override + { + if ( !sourceMap_ ) return false; + return val_ != sourceMap_->get(); + } + + void apply() override { std::cout << "Processing generic: " << val_ << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = " << val_ << std::endl; + } + else { + os << getObjName() << ro << " = " << val_ << " (" << getType() << ")" << std::endl; + } + } +}; + +} // namespace SST::Core::Serialization + +#endif diff --git a/src/sst/core/impl/interactive/ObjTreeHelpers.cc b/src/sst/core/impl/interactive/ObjTreeHelpers.cc new file mode 100644 index 000000000..97a7e84d0 --- /dev/null +++ b/src/sst/core/impl/interactive/ObjTreeHelpers.cc @@ -0,0 +1,63 @@ +// 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/core/impl/interactive/ObjTreeHelpers.h" + +#include "sst/core/impl/interactive/NumericHandle.h" + +namespace SST::Core::Serialization { + +bool +ObjTreeComparison::evaluateComparison(unsigned index, [[maybe_unused]] SST::Core::Serialization::ObjTreeCont* treeRoot) +{ + + // Get the error conditions out of the way + if ( objectsToCompare.empty() || operators.empty() || (operators.size() < index) || + (objectsToCompare.size() < (index * 2)) || (operators[index] == Op::INVALID) ) { + return false; + } + + if ( operators[index] == Op::CHANGED ) { + bool result = + std::get>(objectsToCompare[index * 2])->hasChanged(); + std::get>(objectsToCompare[index * 2])->syncFromSim(); + return result; + } + else { + std::get>(objectsToCompare[index * 2])->syncFromSim(); + std::get>(objectsToCompare[(index * 2) + 1])->syncFromSim(); + + auto lhs = SST::Core::Serialization::NumericHandle::from( + std::get>(objectsToCompare[index * 2]).get()); + auto rhs = SST::Core::Serialization::NumericHandle::from( + std::get>(objectsToCompare[(index * 2) + 1]).get()); + switch ( operators[index] ) { + case Op::LT: + return lhs < rhs; + case Op::LTE: + return lhs <= rhs; + case Op::GT: + return lhs > rhs; + case Op::GTE: + return lhs >= rhs; + case Op::EQ: + return lhs == rhs; + case Op::NEQ: + return lhs != rhs; + default: + return false; + } + } +} + + +}; // namespace SST::Core::Serialization diff --git a/src/sst/core/impl/interactive/ObjTreeHelpers.h b/src/sst/core/impl/interactive/ObjTreeHelpers.h new file mode 100644 index 000000000..dd3fc2452 --- /dev/null +++ b/src/sst/core/impl/interactive/ObjTreeHelpers.h @@ -0,0 +1,393 @@ +// 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_CORE_SERIALIZATION_OBJECTTREEHELPERS_DEBUGGER_H +#define SST_CORE_SERIALIZATION_OBJECTTREEHELPERS_DEBUGGER_H + +#include "sst/core/serialization/ObjTree.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SST::Core::Serialization { + +class ObjTreeComparison +{ +public: + enum class Op : std::uint8_t { LT, LTE, GT, GTE, EQ, NEQ, CHANGED, INVALID }; + enum class valType : std::uint8_t { OBJ, CONST, UNKNOWN }; + static Op getOperationFromString(const std::string& op) + { + if ( op == "<" ) return Op::LT; + if ( op == "<=" ) return Op::LTE; + if ( op == ">" ) return Op::GT; + if ( op == ">=" ) return Op::GTE; + if ( op == "==" ) return Op::EQ; + if ( op == "!=" ) return Op::NEQ; + if ( op == "changed" ) return Op::CHANGED; // Could also use <> + return Op::INVALID; + } + + static std::string getStringFromOp(Op op) + { + switch ( op ) { + case Op::LT: + return "<"; + case Op::LTE: + return "<+"; + case Op::GT: + return ">"; + case Op::GTE: + return ">="; + case Op::EQ: + return "=="; + case Op::NEQ: + return "!="; + case Op::CHANGED: + return "CHANGED"; + case Op::INVALID: + return "INVALID"; + default: + return "Invalid Op"; + } + } + // TODO: add some limits on these + // The full path and name to the objects for compairson. Vector contains the full path to each object stored as + // individual + // elements within the dequeue. Ex: /comp0/subcomp/target --> [comp0][subcomp][target] within the dequeue + std::vector, valType, std::unique_ptr>> objectsToCompare; + std::vector operators; + + void print(std::stringstream& s, unsigned startIdx, unsigned stopIdx) const + { + if ( objectsToCompare.empty() || operators.empty() ) { + return; + } + if ( objectsToCompare.size() < startIdx || objectsToCompare.size() < stopIdx ) { + return; + } + for ( size_t i = startIdx; i < stopIdx; i++ ) { + if ( std::get(objectsToCompare[i]) == valType::UNKNOWN ) { + continue; + } + if ( std::get(objectsToCompare[i]) == valType::CONST ) { + s << std::get>(objectsToCompare[i]).back(); + s << " "; + continue; + } + else { + for ( size_t j = 0; j < std::get>(objectsToCompare[i]).size(); j++ ) { + s << "/"; + s << std::get>(objectsToCompare[i])[j]; + } + } + if ( (i % 2 == 0) && (i / 2 < operators.size()) ) { + s << " " << getStringFromOp(operators[i / 2]); + } + s << " "; + } + // s << std::endl; + } + + bool evaluateComparison(unsigned index, [[maybe_unused]] SST::Core::Serialization::ObjTreeCont* treeRoot); + + ObjTreeComparison() = default; + ~ObjTreeComparison() = default; +}; + +class ObjTreeTraceBuffer +{ + +public: + ObjTreeTraceBuffer(size_t sz, size_t pdelay) : + bufSize_(sz), + postDelay_(pdelay) + { + tagBuffer_.resize(bufSize_); + cycleBuffer_.resize(bufSize_); + handlerBuffer_.resize(bufSize_); + } + + virtual ~ObjTreeTraceBuffer() = default; + + void setBufferReset() { reset_ = true; } + + void resetTraceBuffer() + { + postCount_ = 0; + cur_ = 0; + first_ = 0; + numRecs_ = 0; + samplesLost_ = 0; + isOverrun_ = false; + reset_ = false; + state_ = CLEAR; + + // should we do a syncFromSim on the remaining objBuffers? + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + auto& [bufVec, storedTriggerIdx] = objBuffers_[obj]; + auto e = bufVec.end(); + e--; + bufVec.erase(bufVec.begin(), e); + bufVec.front()->syncFromSim(); + storedTriggerIdx = INT_MAX; + } + } + + size_t getBufferSize() { return bufSize_; } + + void addObjectBuffer(std::unique_ptr vb) + { + std::vector> newBuf; + newBuf.push_back(std::move(vb)); + objBuffers_.emplace_back(std::move(newBuf), INT_MAX); + } + + enum BufferState : int { + CLEAR, // 0 Pre Trigger + TRIGGER, // 1 Trigger + POSTTRIGGER, // 2 Post Trigger + OVERRUN // 3 Overrun + }; + + const std::map state2char { { CLEAR, '-' }, { TRIGGER, '!' }, { POSTTRIGGER, '+' }, + { OVERRUN, 'o' } }; + + bool sampleT(bool trigger, uint64_t cycle, const std::string& handler) + { + size_t start_state = state_; + bool invokeAction = false; + + // if Trigger == TRUE + if ( trigger ) { + if ( start_state == CLEAR ) { // Not previously triggered + state_ = TRIGGER; // State becomes trigger record + } + // printf(" Sample: trigger\n"); + + } // if trigger + + if ( start_state == TRIGGER || start_state == POSTTRIGGER ) { // trigger record or post trigger + state_ = POSTTRIGGER; // State becomes post trigger + // printf(" Sample: post trigger\n"); + } + + // Circular buffer + if ( !(state_ == POSTTRIGGER && postCount_ >= postDelay_) ) { +#ifdef _OBJMAP_DEBUG_ + std::cout << " Sample:" << handler << ": numRecs:" << numRecs_ << " first:" << first_ << " cur:" << cur_ + << " state:" << state2char.at(state_) << " isOverrun:" << isOverrun_ + << " samplesLost:" << samplesLost_ << std::endl; +#endif + cycleBuffer_[cur_] = cycle; + handlerBuffer_[cur_] = handler; + if ( trigger ) { + triggerCycle = cycle; + } + + // Sample all the trace object buffers + ObjTreeCont* varBuffer_; + + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + auto& [bufVec, storedTriggerIdx] = objBuffers_[obj]; + varBuffer_ = bufVec.back().get(); + // varBuffer_->sample(cur_, trigger); + if ( storedTriggerIdx != INT_MAX ) { + std::unique_ptr updatedBuf(varBuffer_->clone()); + updatedBuf->syncFromSim(); + bufVec.push_back(std::move(updatedBuf)); + unsigned triggerIdx = trigger ? bufVec.size() - 1 : storedTriggerIdx; + storedTriggerIdx = triggerIdx; + } + else { + bufVec.back()->syncFromSim(); + storedTriggerIdx = 0; + } + // DDD: Add a way to flag which of these values was the trigger value + } + + if ( numRecs_ < bufSize_ ) { + tagBuffer_[cur_] = state_; + numRecs_++; + cur_ = (cur_ + 1) % bufSize_; + if ( cur_ == 0 ) first_ = 0; // 1; + } + else { // Buffer full + // Check to see if we are overwriting trigger + if ( tagBuffer_[cur_] == TRIGGER ) { + // printf(" Sample Overrun\n"); + isOverrun_ = true; + } + tagBuffer_[cur_] = state_; + numRecs_++; + cur_ = (cur_ + 1) % bufSize_; + first_ = cur_; + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + auto& [bufVec, storedTriggerIdx] = objBuffers_[obj]; + bufVec.erase(bufVec.begin()); + if ( storedTriggerIdx == bufVec.size() ) { + storedTriggerIdx--; + } + } + } + } + + if ( isOverrun_ ) { + samplesLost_++; + } + + if ( (state_ == TRIGGER) && (postDelay_ == 0) ) { + invokeAction = true; + } + + if ( state_ == POSTTRIGGER ) { + postCount_++; + if ( postCount_ >= postDelay_ ) { + invokeAction = true; + } + } + + return invokeAction; + } + + void dumpTraceBufferT(std::ostream& os = std::cout) + { + if ( numRecs_ == 0 ) return; + + size_t start; + size_t end; + + start = first_; + if ( cur_ == 0 ) { + end = bufSize_ - 1; + } + else { + end = cur_ - 1; + } + size_t buf = 0; + for ( int j = start;; j++ ) { + size_t i = j % bufSize_; + + os << "buf[" << i << "] " << handlerBuffer_.at(i) << " @" << cycleBuffer_.at(i) << " (" + << state2char.at(tagBuffer_.at(i)) << ") "; + + std::ostringstream tmpBuf; + std::string objNames; + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + ObjTreeCont* varBuffer_ = + std::get>>(objBuffers_[obj])[buf].get(); // DDD: Maybe? + varBuffer_->Dump(1, std::ios_base::dec, tmpBuf); + // std::cout << varBuffer_->getObjName() << "=" << varBuffer_->get() << " "; + objNames.append(tmpBuf.str()); + if ( !objNames.empty() && objNames.back() == '\n' ) { + objNames.pop_back(); + objNames.push_back(' '); + } + tmpBuf.str(""); + tmpBuf.clear(); + } + os << objNames << std::endl; + buf++; + + if ( i == end ) { + break; + } + } + } + + void dumpTriggerRecord(std::ostream& os = std::cout) + { + if ( numRecs_ == 0 ) { + std::cout << "No trace samples in current buffer" << std::endl; + return; + } + if ( state_ != CLEAR ) { + std::stringstream ss; // Need to buffer in a stream so it doesn't get split in parallel execution + std::ostringstream tmpBuf; + std::string objNames; + unsigned idxToPrint = 0; + // print trigger value for the one variable (variables?) that actually triggered + ss << "LastTriggerRecord:@cycle" << triggerCycle << ": SamplesLost=" << samplesLost_ << ": "; + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + unsigned triggerIdx = std::get(objBuffers_[obj]); + auto* record = &std::get>>(objBuffers_[obj]); + if ( triggerIdx < record->size() ) { + idxToPrint = triggerIdx; + } + else { + idxToPrint = record->size() - 1; + } + ObjTreeCont* varBuffer_ = (*record)[idxToPrint].get(); + // OK, so we have to use Dump() to get the value, but it adds a \n after each call, so strip it out + varBuffer_->Dump(1, std::ios_base::dec, tmpBuf); + objNames.append(tmpBuf.str()); + if ( !objNames.empty() && objNames.back() == '\n' ) { + objNames.pop_back(); + objNames.push_back(' '); + } + tmpBuf.str(""); + tmpBuf.clear(); + } + ss << objNames << std::endl; + os << ss.str(); // Print everything at once to avoid splitting + } + } + + void printVars(std::stringstream& ss) + { + for ( size_t obj = 0; obj < objBuffers_.size(); obj++ ) { + ObjTreeCont* varBuffer_ = + std::get>>(objBuffers_[obj]).back().get(); + // ss << SST::Core::to_string(varBuffer_->getName()) << " "; + ss << varBuffer_->getObjName() << " "; + } + } + + void printConfig(std::stringstream& ss) + { + ss << "bufsize = " << bufSize_ << " postDelay = " << postDelay_ << " : "; + printVars(ss); + } + + // private: + size_t bufSize_ = 64; + size_t postDelay_ = 8; + size_t postCount_ = 0; + size_t cur_ = 0; + size_t first_ = 0; + size_t numRecs_ = 0; + bool isOverrun_ = false; + size_t samplesLost_ = 0; + bool reset_ = false; + BufferState state_ = CLEAR; + + std::vector tagBuffer_; + std::vector handlerBuffer_; + // Vector of ObjTreeCont - organized as all the sampled values with the index of the last + // triggered value + std::vector>, unsigned>> objBuffers_; + std::vector cycleBuffer_; + uint64_t triggerCycle; + +}; // class TraceBuffer +} // namespace SST::Core::Serialization +#endif diff --git a/src/sst/core/impl/interactive/cmdLineEditor.cc b/src/sst/core/impl/interactive/cmdLineEditor.cc index f4568ad43..f3a5683b2 100644 --- a/src/sst/core/impl/interactive/cmdLineEditor.cc +++ b/src/sst/core/impl/interactive/cmdLineEditor.cc @@ -363,7 +363,7 @@ CmdLineEditor::getline(const std::vector& cmdHistory, std::string& else if ( c == ctrl_d ) { int position = curpos - prompt.size() - 1; if ( position == 0 && history[index].size() == 0 ) { - // if the line is empty then quit (tactcomplabs/sst-core #32) + // if the line is empty then shutdown (tactcomplabs/sst-core #32) end_of_file = true; break; } @@ -425,7 +425,7 @@ CmdLineEditor::getline(const std::vector& cmdHistory, std::string& // set the new line info if ( end_of_file ) - newcmd = "quit"; + newcmd = "shutdown"; else newcmd = history[index]; diff --git a/src/sst/core/impl/interactive/debugCommands.h b/src/sst/core/impl/interactive/debugCommands.h index 206180775..2fe59e7c3 100644 --- a/src/sst/core/impl/interactive/debugCommands.h +++ b/src/sst/core/impl/interactive/debugCommands.h @@ -196,8 +196,9 @@ class CommandRegistry std::vector& getUserRegistryVector() { return user_registry; } enum SEARCH_TYPE { ALL, BUILTIN, USER }; std::pair const seek(std::string token, SEARCH_TYPE search_type); + bool replace_user_cmd(std::string token); // User defined command entry - bool beginUserCommand(std::string name); + bool beginUserCommand(std::string name, bool confirm); void appendUserCommand(std::string token0, std::string line); void commitUserCommand(); std::vector* userCommandInsts(std::string key) diff --git a/src/sst/core/impl/interactive/debugConsole.cc b/src/sst/core/impl/interactive/debugConsole.cc index e1d91d160..48d6c103a 100644 --- a/src/sst/core/impl/interactive/debugConsole.cc +++ b/src/sst/core/impl/interactive/debugConsole.cc @@ -14,6 +14,8 @@ #include "sst/core/impl/interactive/debugConsole.h" #include "sst/core/baseComponent.h" +#include "sst/core/impl/interactive/ObjMapToTree.h" +#include "sst/core/impl/interactive/ObjTreeHelpers.h" #include "sst/core/simulation.h" #include "sst/core/stringize.h" #include "sst/core/timeConverter.h" @@ -78,6 +80,13 @@ DebugConsole::DebugConsole(Params& params) : ConsoleCommandGroup::GENERAL, [this](std::string& cmd_str) { return cmd_help(cmd_str); }, }, + { + "show", + "sh", + "[CMD]: show user-defined command \"CMD\" or show all user-defined commands", + ConsoleCommandGroup::GENERAL, + [this](std::string& cmd_str) { return cmd_show(cmd_str); }, + }, { "verbose", "v", "[mask]: set verbosity mask or print if no mask specified", ConsoleCommandGroup::GENERAL, exec_type, [this](std::string& cmd_str) { return cmd_verbose_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_verbose_thread(cmd_str); }, @@ -88,7 +97,7 @@ DebugConsole::DebugConsole(Params& params) : { "info", "info", - "\"current\"|\"all\" print summary for current thread or all threads", + "\"current\"|\"all\": print summary for current thread or all threads", ConsoleCommandGroup::GENERAL, exec_type, [this](std::string& cmd_str) { return cmd_info_serial(cmd_str); }, @@ -97,13 +106,13 @@ DebugConsole::DebugConsole(Params& params) : [this](std::string& cmd_str) { return cmd_info_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return cmd_info_remote(tokens); }, }, - { "thread", "thd", "[threadID]: switch to specified thread ID", ConsoleCommandGroup::GENERAL, exec_type, + { "thread", "thd", ": switch to specified thread ID", ConsoleCommandGroup::GENERAL, exec_type, [this](std::string& cmd_str) { return cmd_thread_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_thread_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_thread_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_thread_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return cmd_thread_remote(tokens); } }, - { "rank", "rank", "[rankID]: switch to specified rank ID, same thread", ConsoleCommandGroup::GENERAL, exec_type, + { "rank", "rank", ": switch to specified rank ID, same thread", ConsoleCommandGroup::GENERAL, exec_type, [this](std::string& cmd_str) { return cmd_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_rank_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_rank_rank_serial(cmd_str); }, @@ -111,32 +120,32 @@ DebugConsole::DebugConsole(Params& params) : [this](std::vector& tokens) { return cmd_rank_remote(tokens); } }, { "confirm", "cfm", ": set confirmation requests on (default) or off", ConsoleCommandGroup::GENERAL, [this](std::string& cmd_str) { return cmd_setConfirm(cmd_str); } }, - { "pwd", "pwd", "print the current working directory in the object map", ConsoleCommandGroup::NAVIGATION, + { "pwd", "pwd", ": print the current working directory in the object tree", ConsoleCommandGroup::NAVIGATION, exec_type, [this](std::string& cmd_str) { return cmd_pwd_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_pwd_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_pwd_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_pwd_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return cmd_pwd_remote(tokens); } }, - { "chdir", "cd", "change 1 directory level in the object map", ConsoleCommandGroup::NAVIGATION, exec_type, + { "chdir", "cd", ": change 1 directory level in the object tree", ConsoleCommandGroup::NAVIGATION, exec_type, [this](std::string& cmd_str) { return cmd_cd_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_cd_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_cd_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_cd_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return cmd_cd_remote(tokens); } }, - { "list", "ls", "list the objects in the current level of the object map", ConsoleCommandGroup::NAVIGATION, - exec_type, [this](std::string& cmd_str) { return cmd_ls_serial(cmd_str); }, + { "list", "ls", "[-l] [-ll]: list the objects in the current level of the object tree", + ConsoleCommandGroup::NAVIGATION, exec_type, [this](std::string& cmd_str) { return cmd_ls_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_ls_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_ls_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_ls_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return cmd_ls_remote(tokens); } }, // State - { "time", "tm", "print current simulation time in cycles", ConsoleCommandGroup::STATE, + { "time", "tm", ": print current simulation time in cycles", ConsoleCommandGroup::STATE, [this](std::string& cmd_str) { return cmd_time(cmd_str); } }, { "print", "p", - "[-rN] []: print objects at the current level", + "[-r N] : print objects at the current level", ConsoleCommandGroup::STATE, exec_type, [this](std::string& cmd_str) { return cmd_print_serial(cmd_str); }, @@ -148,7 +157,7 @@ DebugConsole::DebugConsole(Params& params) : { "set", "s", - "var value: set value for a variable at the current level", + " : set value for a variable at the current level", ConsoleCommandGroup::STATE, exec_type, [this](std::string& cmd_str) { return cmd_set_serial(cmd_str); }, @@ -172,7 +181,7 @@ DebugConsole::DebugConsole(Params& params) : { "trace", "t", - " : : ... : ", + " : : ... : (see 'help trace')", ConsoleCommandGroup::WATCH, exec_type, [this](std::string& cmd_str) { return cmd_trace_serial(cmd_str); }, @@ -184,7 +193,7 @@ DebugConsole::DebugConsole(Params& params) : { "watchlist", "wl", - "prints the current list of watchpoints", + ": prints the current list of watchpoints", ConsoleCommandGroup::WATCH, exec_type, [this](std::string& cmd_str) { return cmd_watchlist_serial(cmd_str); }, @@ -196,7 +205,7 @@ DebugConsole::DebugConsole(Params& params) : { "addTraceVar", "add", - " ... ", + " ... : adds additional trace variables to existing watchpoint", ConsoleCommandGroup::WATCH, exec_type, [this](std::string& cmd_str) { return cmd_addTraceVar_serial(cmd_str); }, @@ -244,7 +253,7 @@ DebugConsole::DebugConsole(Params& params) : { "setHandler", "shn", - " ... : trigger check/sampling handler", + " ... : set a watchpoint's handler location(s) for trigger check and sampling", ConsoleCommandGroup::WATCH, exec_type, [this](std::string& cmd_str) { return cmd_setHandler_serial(cmd_str); }, @@ -276,93 +285,107 @@ DebugConsole::DebugConsole(Params& params) : { "continue", "c", - "alias for run", + ": alias for run", ConsoleCommandGroup::SIMULATION, [this](std::string& cmd_str) { return cmd_run(cmd_str); }, }, - { "exit", "e", "exit debugger and continue simulation", ConsoleCommandGroup::SIMULATION, exec_type, + { "exit", "e", ": exit debugger and continue simulation", ConsoleCommandGroup::SIMULATION, exec_type, [this](std::string& cmd_str) { return cmd_exit_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return clear_watchlist(tokens); } }, - { "quit", "q", "alias for exit", ConsoleCommandGroup::SIMULATION, exec_type, + { "quit", "q", ": alias for exit", ConsoleCommandGroup::SIMULATION, exec_type, [this](std::string& cmd_str) { return cmd_exit_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_thread(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_rank_serial(cmd_str); }, [this](std::string& cmd_str) { return cmd_exit_rank_parallel(cmd_str); }, [this](std::vector& tokens) { return clear_watchlist(tokens); } }, - { "shutdown", "shutd", "exit the debugger and cleanly shutdown simulator", ConsoleCommandGroup::SIMULATION, + { "shutdown", "shutd", ": exit the debugger and cleanly shutdown simulator", ConsoleCommandGroup::SIMULATION, [this](std::string& cmd_str) { return cmd_shutdown(cmd_str); } }, // Logging/Replay - { "logging", "log", ": log command line entires to file", ConsoleCommandGroup::LOGGING, + { "logging", "log", ": log command line entries to file", ConsoleCommandGroup::LOGGING, [this](std::string& cmd_str) { return cmd_logging(cmd_str); } }, - { "replay", "rep", ": run commands from a file. See also: sst --replay", ConsoleCommandGroup::LOGGING, - [this](std::string& cmd_str) { return cmd_replay(cmd_str); } }, + { "replay", "rep", ": run commands from a file. See also: 'sst --replay'", + ConsoleCommandGroup::LOGGING, [this](std::string& cmd_str) { return cmd_replay(cmd_str); } }, { "history", "h", "[N]: display all or last N unique commands", ConsoleCommandGroup::LOGGING, [this](std::string& cmd_str) { return cmd_history(cmd_str); } }, // Misc - { "autoComplete", "ac", "toggle command line auto-completion enable", ConsoleCommandGroup::MISC, + { "autoComplete", "ac", ": toggle command line auto-completion enable", ConsoleCommandGroup::MISC, [this](std::string& cmd_str) { return cmd_autoComplete(cmd_str); } }, - { "clear", "clr", "reset terminal", ConsoleCommandGroup::MISC, + { "clear", "clr", ": reset terminal", ConsoleCommandGroup::MISC, [this](std::string& cmd_str) { return cmd_clear(cmd_str); } }, - { "define", "def", "define a user command sequence", ConsoleCommandGroup::MISC, + { "define", "def", ": define a user command sequence", ConsoleCommandGroup::MISC, [this](std::string& cmd_str) { return cmd_define(cmd_str); } }, - { "document", "doc", "document help for a user defined command", ConsoleCommandGroup::MISC, + { "document", "doc", ": document help for a user defined command", ConsoleCommandGroup::MISC, [this](std::string& cmd_str) { return cmd_document(cmd_str); } }, }); // Detailed help from some commands. Can also add general things like 'help navigation' - cmdRegistry.cmdHelp = { - { "verbose", "[mask]: set verbosity mask or print if no mask specified\n" - "\tA mask is used to select which features to enable verbosity.\n" - "\tTo turn on all features set the mask to 0xffffffff\n" - "\t\t0x10: Show trigger details" }, - { "print", "[-rN][]: print objects in the current level of the object map\n" - "\tif -rN is provided print recursive N levels (default N=4)" }, + cmdRegistry.cmdHelp = { { "verbose", "[mask]: set verbosity mask or print if no mask specified\n" + "\tA mask is used to select which features to enable verbosity.\n" + "\tTo turn on all features set the mask to 0xffffffff\n" + "\t\t0x10: Show trigger details" }, + { "print", "[-r R] [-v V] [-f F] [][[idx][idx]]\n" + "\t-r R prints recursively to R levels\n" + "\t-v V prints with increasing verbosity\n" + "\t-f F formatted print (hex oct dec(default))" }, { "set", " : sets an object in the current scope to the provided value\n" - "\tobject must be a 'fundamental type' (arithmetic or string)\n" - "\t e.g. set mystring hello world" }, - { "examine", "[e][]: prints object in the current scope\n" }, + "\t Example: set mystring hello world" }, { "watchpoints", "Manage watchpoints (with or without tracing)\n" "\tA can be a or a sequence of comparisons combined with a \n" - "\tE.g. = or ...\n" + "\tE.g. = '' or ' ...'\n" "\tA can be ' changed' which checks whether the value has changed\n" "\tor ' ' which compares the variable to a given value\n" "\tAn can be <, <=, >, >=, ==, or !=\n" "\tA can be && or ||\n" "\t'watch' creates a default watchpoint that breaks into an interactive console when triggered\n" "\t'trace' creates a watchpoint with a trace buffer to trace a set of variables and trigger an \n" + "\t Note that only data members with persistent references should be used in watchpoints\n" "\tAvailable actions include: \n" - "\t interactive, printTrace, checkpoint, set , printStatus, or shutdown" - "\t Note: checkpoint action must be enabled at startup via the '--checkpoint-enable' command line " + "\t interactive, printTrace, checkpoint, set , printStatus, or shutdown\n" + "\tNote that checkpoint action must be enabled at startup via the '--checkpoint-enable' command line " "option\n" }, - { "watch", ": adds watchpoint to the watchlist; breaks into interactive console when triggered\n" - "\tExample: watch var1 > 90 && var2 < 100 || var3 changed" }, + { "watch", ": Adds the watchpoint to the watchlist. Breaks into interactive console \n" + "\twhen the trigger condition evaluates to true\n" + "\tExample: watch var1 > 90 && var2 < 100 || var3 changed\n" + "\tWill break into the interactive console when 'var 1 > 90 && var2 < 100 || var3 changed'\n" }, { "trace", " : : ... : \n" - "\tAdds watchpoint to the watchlist with a trace buffer of and a post trigger delay of " - "\n" - "\tTraces all of the variables specified in the var list and invokes the after postDelay " - "when triggered\n" + "\tAdds a watchpoint to the watchlist with a trace buffer of and a post trigger delay of \n" + "\t. Each of the variable values is sampled (recorded in the trace buffer) at each handler \n" + "\tlocation (before/after clock/event handlers). Once the trigger condition is true, \n" + "\tit will sample postDelay additional times and then trigger the associated action. \n" "\tAvailable actions include: \n" "\t interactive, printTrace, checkpoint, set , printStatus, or shutdown\n" "\t Note: checkpoint action must be enabled at startup via the '--checkpoint-enable' command line option\n" - "\tExample: trace var1 > 90 || var2 == 100 : 32 4 : size count state : printTrace" }, + "\tExample: trace var1 > 90 || var2 == 100 : 32 4 : size count state : printTrace\n" + "\tThis example will sample the size, count, and state variables in a circular buffer of size 32 until \n" + "\tuntil the trigger condition is true, i.e. 'var1 > 90 || var2 == 100'. It will then sample 4 additional " + "\n" + "\ttimes before printing the trace buffer and resetting it.\n" }, { "watchlist", "prints the current list of watchpoints and their associated indices" }, - { "addtracevar", " ... : adds the specified variables to the specified " + { "addtracevar", " ... : adds the variables to the specified " "watchpoint's trace buffer" }, - { "printwatchpoint", ": prints the watchpoint based on the index specified by watchlist" }, - { "printtrace", ": prints the trace buffer for the specified watchpoint" }, - { "resettrace", ": resets the trace buffer for the specified watchpoint" }, + { "printwatchpoint", ": prints the watchpoint at that index in the local watchlist" }, + { "printtrace", + ": prints the trace buffer for the specified watchpoint in the local watchlist" }, + { "resettrace", + ": resets the trace buffer for the specified watchpoint in the local watchlist" }, { "sethandler", " ... \n" - "\tset where to do trigger checks and sampling (before/after clock/event handler)" }, - { "unwatch", ": removes the specified watchpoint from the watch list.\n" + "\tset location(s) to execute trigger checks and sampling (default is all)\n" + "\t bc: before clock handler\n" + "\t ac: after clock handler\n" + "\t be: before event handler\n" + "\t ae: after event handler\n" + "\t all: all 4 locations\n" + "\tExample setHandler 1 ac ae" }, + { "unwatch", ": removes the specified watchpoint from the current watch list.\n" "\tIf no index is provided, all watchpoints are removed." }, - { "run", "[TIME]: runs the simulation from the current point for TIME and then returns to\n" - "\tinteractive mode; if no time is given, the simulation runs to completion;\n" + { "run", "[TIME]: runs the simulation from the current point for TIME and then returns to interactive mode;\n" + "\t if no time is given, the simulation runs to the next watchpoint trigger or completion;\n" "\tTIME is of the format e.g. 4us" }, { "history", "[N]: list previous N instructions. If N is not set list all\n" "\tSupports bash-style commands:\n" @@ -379,16 +402,20 @@ DebugConsole::DebugConsole(Params& params) : "\ttab: auto-completion\n" "\tctrl-a: move cursor to beginning of line\n" "\tctrl-b: move cursor to the left\n" - "\tctrl-d: delete character at cursor or quit debugger\n" + "\tctrl-d: delete character at cursor or shutdown\n" "\tctrl-e: move cursor to end of line\n" - "\tctrl-f: move cursor to the right\n" }, + "\tctrl-f: move cursor to the right\n" + "\tNote: this functionality is not available when using mpi" }, { "define", ": enter a command sequence for a user defined command.\n" - "Terminate the sequence by typing \"end\"\n" }, + "\tTerminate the sequence by typing \"end\"\n" }, { "document", ": provide help documentation for a user defined command.\n" - "The first line will be summarized in the short help text.\n" - "Remaining lines will be provided in detailed help\n" - "Terminate the sequence by typing \"end\"\n" }, - }; + "\tThe first line will be summarized in the short help text.\n" + "\tRemaining lines will be provided in detailed help\n" + "\tTerminate the sequence by typing \"end\"\n" }, + { "list", + "[-l] [-ll]: list the objects in the current level of the object tree with varying detail (default 1).\n" + "\tl: verbosity level 2\n" + "\tll: verbosity level 3\n" } }; // Command autofill strings std::list cmdStrings; @@ -402,6 +429,7 @@ DebugConsole::DebugConsole(Params& params) : // Callback for directory listing strings cmdLineEditor.set_listing_callback([this](std::list& vec) { get_listing_strings(vec); }); + objTree_ = new SST::Core::Serialization::ComponentObj(); struct winsize size; if ( ioctl(STDERR_FILENO, TIOCGWINSZ, &size) == 0 ) { dout.setLineWidth(size.ws_col); @@ -413,6 +441,7 @@ DebugConsole::~DebugConsole() { if ( loggingFile.is_open() ) loggingFile.close(); if ( replayFile.is_open() ) replayFile.close(); + if ( objTree_ ) delete objTree_; } void @@ -458,8 +487,20 @@ DebugConsole::consoleExecute(const std::string& msg) << getCurrentSimCycle() << std::endl; std::cout << msg << std::endl; - // Create a new ObjectMap - obj_ = getComponentObjectMap(); + // Try and serialize the entire map + // auto totalMap = SST::Core::Serialization::ObjectMapToTree::convertAndSerialize("root", obj_); + // printf("---- total map:\n ----"); + // totalMap->Dump(2); + + // if(curObj_ == nullptr || objTree_->isEmpty()){ + if ( objTree_->isEmpty() ) { + objTree_->BuildTree(getComponentInfoMap()); + curObj_ = objTree_; + } + if ( curObj_ == nullptr ) { + curObj_ = objTree_; + } + // Descend into the name_stack cd_name_stack(); @@ -534,39 +575,32 @@ DebugConsole::consoleExecute(const std::string& msg) } } - // Save the position on the name_stack, and clear obj_ + // Save the position on the name_stack, and clear objTree_ and curObj_ save_name_stack(); + done = true; return retState; } -// Save the name stack of the current position, and clear obj_ +// Save the name stack of the current position, and clear objTree and curObj_ void DebugConsole::save_name_stack() { name_stack.clear(); - for ( ;; ) { - // Get the name of the current node - std::string name = obj_->getName(); - - // Get the parent of the current node - Core::Serialization::ObjectMap* parent = obj_->selectParent(); - - // If the parent is nullptr, we have reached the top and can stop - if ( !parent ) break; - // Push the name on the name_stack - name_stack.push_front(std::move(name)); - - // See if this is the top level component, and if so, set it to nullptr - if ( dynamic_cast(base_comp_) == obj_ ) base_comp_ = nullptr; - - // Move up to the parent - obj_ = parent; + if ( curObj_ && !curObj_->isRoot() ) { + SST::Core::Serialization::ObjTreeCont* parent = curObj_->getParent(); + name_stack.push_front(std::move(curObj_->getObjName())); + while ( parent && !parent->isRoot() ) { + name_stack.push_front(std::move(parent->getObjName())); + parent = parent->getParent(); + } } - obj_->decRefCount(); - obj_ = nullptr; + if ( !objTree_->isEmpty() ) { + objTree_->clear(); // tear down the children so we refresh next time we break in + curObj_ = nullptr; + } } // Descend into the name_stack @@ -585,6 +619,12 @@ DebugConsole::cd_name_stack() bool DebugConsole::dispatch_cmd(std::string& cmd) { + // ctrl+d + if ( std::cin.eof() ) { + std::cout << "" << std::endl; + cmd = "shutdown"; + } + // empty command if ( cmd.size() == 0 ) return true; @@ -758,6 +798,45 @@ DebugConsole::cmd_help(std::string& UNUSED(cmd_str)) return true; } +bool +DebugConsole::cmd_show(std::string& UNUSED(cmd_str)) +{ + // First check for specific command help + if ( tokens.size() == 1 ) { + if ( cmdRegistry.getUserRegistryVector().size() > 0 ) { + std::cout << "--- User-Defined Commands ---" << std::endl; + for ( const auto& cmd : cmdRegistry.getUserRegistryVector() ) { + // if ( g.first == c.group() ) { + // std::cout << c << std::endl; + // } + std::string c = cmd.str_long(); + std::cout << "User command \"" << c << "\":\n"; + auto insts = cmdRegistry.userCommandInsts(c); + for ( auto i : *insts ) { + std::cout << "\t" << i << "\n"; + } + std::cout << std::endl; + } + } + return true; + } + + if ( tokens.size() > 1 ) { + std::string c = tokens[1]; + auto insts = cmdRegistry.userCommandInsts(c); + if ( insts == nullptr ) { + std::cout << "User-defined command \"" << c << "\" not found" << std::endl; + return false; + } + std::cout << "User command \"" << c << "\":\n"; + for ( auto i : *insts ) { + std::cout << "\t" << i << "\n"; + } + return true; + } + return false; +} + // verbose [mask] : set verbosity mask or print if no mask specified bool DebugConsole::cmd_verbose_query() @@ -781,6 +860,11 @@ DebugConsole::cmd_verbose_query() bool DebugConsole::cmd_verbose_remote(std::vector& tokens) { + if ( tokens.size() <= 1 ) { + std::cout << "Invalid format for verbose command (verbose N)" << std::endl; + return false; + } + verbosity = SST::Core::from_string(tokens[1]); // update watchpoint verbosity in all ranks/threads @@ -921,7 +1005,8 @@ DebugConsole::cmd_info_thread(std::string& UNUSED(cmd_str)) else if ( tokens[1] == "all" ) { // Print info for all threads succeed = handleCommandAll(); - std::cout << result.str(); + dout << result.str(); + dout << dreset; } else { std::cout << "Invalid argument for info command: " << tokens[1] << " (info \"current\"|\"all\")" << std::endl; @@ -961,14 +1046,15 @@ DebugConsole::cmd_info_rank_serial(std::string& cmd_str) result.clear(); // Print info for rank 0 succeed = cmd_info_remote(tokens); - std::cout << result.str(); + dout << result.str(); // Clear R0 result string result.str(""); result.clear(); // Send to remote ranks, all threads succeed2 = sendCommandAll(cmd_str); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed || succeed2; } else { @@ -1007,14 +1093,15 @@ DebugConsole::cmd_info_rank_parallel(std::string& cmd_str) result.clear(); // Print info for rank 0 succeed = handleCommandAll(); - std::cout << result.str(); + dout << result.str(); // Clear result string result.str(""); result.clear(); // Print info for other ranks, all threads succeed2 = sendCommandAll(cmd_str); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed || succeed2; } else { @@ -1389,16 +1476,17 @@ DebugConsole::cmd_pwd_rank_parallel(std::string& cmd_str) bool DebugConsole::cmd_pwd_remote(std::vector& UNUSED(tokens)) { - // std::string path = obj_->getName(); - // std::string slash("/"); - // // path = slash + path; - // SST::Core::Serialization::ObjectMap* curr = obj_->getParent(); - // while ( curr != nullptr ) { - // path = curr->getName() + slash + path; - // curr = curr->getParent(); - // } - - result << obj_->getFullName() << " (" << obj_->getType() << ")\n"; + std::string path = "/"; + if ( !curObj_->isRoot() ) { + SST::Core::Serialization::ObjTreeCont* parent = curObj_->getParent(); + path.append(curObj_->getObjName()); + while ( parent && !parent->isRoot() ) { + path.insert(0, parent->getObjName()); + path.insert(0, "/"); + parent = parent->getParent(); + } + } + result << path << std::endl; return true; } @@ -1477,17 +1565,21 @@ DebugConsole::cmd_ls_rank_parallel(std::string& cmd_str) } bool -DebugConsole::cmd_ls_remote(std::vector& UNUSED(tokens)) +DebugConsole::cmd_ls_remote(std::vector& tokens) { - auto& vars = obj_->getVariables(); - for ( auto& x : vars ) { - if ( x.second->isFundamental() ) { - result << x.first << " = " << x.second->get() << " (" << x.second->getType() << ")" << std::endl; - } - else { - result << x.first.c_str() << "/ (" << x.second->getType() << ")\n"; - } - } + + unsigned verbosity = 0; + if ( tokens.size() > 1 ) { + if ( "-l" == tokens[1] ) + verbosity = 2; + else if ( "-ll" == tokens[1] ) + verbosity = 3; + } + // Dump all the components + curObj_->applyRecursive([verbosity](SST::Core::Serialization::ObjTreeCont* child) { + child->Dump(verbosity, std::ios_base::dec, result); + }); + return true; } @@ -1496,13 +1588,8 @@ void DebugConsole::get_listing_strings(std::list& list) { list.clear(); - auto& vars = obj_->getVariables(); - for ( auto& x : vars ) { - std::stringstream s; - s << x.first; - if ( !x.second->isFundamental() ) s << "/"; - list.emplace_back(s.str()); - } + curObj_->applyRecursive( + [&](SST::Core::Serialization::ObjTreeCont* child) { list.emplace_back(child->getObjName()); }); list.sort(); } @@ -1606,48 +1693,63 @@ DebugConsole::cmd_cd_remote(std::vector& tokens) // Check for .. if ( selection == ".." ) { - auto* parent = obj_->selectParent(); - if ( parent == nullptr ) { - result << "Already at top of object hierarchy" << std::endl; + auto* parent = curObj_->getParent(); + if ( parent ) { + curObj_ = parent; + } + else { + printf("Already at top of object hierarchy\n"); return false; } - - // See if this is the top level component, and if so, set it to nullptr - if ( dynamic_cast(base_comp_) == obj_ ) base_comp_ = nullptr; - - obj_ = parent; return true; } - bool loop_detected = false; - SST::Core::Serialization::ObjectMap* new_obj = obj_->selectVariable(selection, loop_detected, confirm_); - if ( !new_obj || (new_obj == obj_) ) { - result << "Unknown object in cd command: " << selection << std::endl; + // Search children by name + SST::Core::Serialization::ObjTreeCont* target = curObj_->findByName(selection); + if ( !target ) { + printf("Unknown object in cd command: %s\n", selection.c_str()); return false; } - if ( new_obj->isFundamental() ) { - result << "Object" << selection << " is a fundamental type so you cannot cd into it" << std::endl; - new_obj->selectParent(); - return false; + // If it's a ComponentObj that hasn't been serialized yet, serialize it + if ( auto* comp = dynamic_cast(target) ) { + if ( comp->getChildren().empty() ) { + Core::Serialization::ObjectMapToTree::serializeComponent(comp, true); + } } - if ( loop_detected ) { - result << "Loop detected in cd. New working directory will be set to level of looped object: " - << new_obj->getFullName() << std::endl; + // Only descend if the target has children (or is a component that just got serialized) + if ( target->getChildren().empty() ) { + printf("Cannot cd into %s: no children\n", selection.c_str()); + return false; } - obj_ = new_obj; - // If we don't already have the top level component, check to see - // if this is it - if ( nullptr == base_comp_ ) { - Core::Serialization::ObjectMapDeferred* base_comp = - dynamic_cast*>(obj_); - if ( base_comp ) base_comp_ = base_comp; - } + curObj_ = target; + return true; } +std::vector +DebugConsole::parseBracketIndices(std::string& token) +{ + std::vector indices; + + size_t pos = token.find('['); + while ( pos != std::string::npos ) { + size_t pos2 = token.find(']', pos); + if ( pos2 == std::string::npos ) break; + + std::string key = token.substr(pos + 1, (pos2 - pos) - 1); + indices.push_back(std::atoi(key.c_str())); + token.erase(pos, (pos2 - pos) + 1); + + // Search again from the same position since we erased + pos = token.find('[', pos); + } + + return indices; +} + // time: print current simulation cycle bool DebugConsole::cmd_time(std::string& UNUSED(cmd_str)) @@ -1671,7 +1773,8 @@ DebugConsole::cmd_print_serial(std::string& UNUSED(cmd_str)) result.clear(); succeed = cmd_print_remote(tokens); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -1689,7 +1792,8 @@ DebugConsole::cmd_print_thread(std::string& UNUSED(cmd_str)) result.clear(); succeed = handleCommand(); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -1709,13 +1813,14 @@ DebugConsole::cmd_print_rank_serial(std::string& cmd_str) if ( current_rank == 0 ) { succeed = cmd_print_remote(tokens); - std::cout << result.str(); + dout << result.str(); } else { // Send to remote rank succeed = sendCommand(current_rank, current_thread, cmd_str); - std::cout << result.str(); + dout << result.str(); } + dout << dreset; return succeed; } @@ -1735,14 +1840,14 @@ DebugConsole::cmd_print_rank_parallel(std::string& cmd_str) if ( current_rank == 0 ) { // Execute in correct local thread succeed = handleCommand(); - std::cout << result.str(); + dout << result.str(); } else { // Send to remote rank succeed = sendCommand(current_rank, current_thread, cmd_str); - std::cout << result.str(); + dout << result.str(); } - + dout << dreset; return succeed; } @@ -1752,12 +1857,22 @@ DebugConsole::cmd_print_remote(std::vector& tokens) // Index in tokens array where we may find the variable name size_t var_index = 1; + if ( tokens.size() < 2 ) { + printf("Invalid format for print command (print [-r N] [-v N] [-f ] [][[idx][idx]])\n"); + return false; + } + + size_t pos = containsArg(tokens, "-r"); // See if have a -r or not - int recurse = 4; // default -r depth + int recurse = 0; // default -r depth std::string tok = tokens[1]; if ( (tok.size() >= 2) && (tok[0] == '-') && (tok[1] == 'r') ) { // Got a -r - std::string num = tok.substr(2); + if ( tokens.size() < (pos + 2) ) { + printf("Invalid format for print command (print [-r N] [-v N] [-f ] [][[idx][idx]])\n"); + return false; + } + std::string num = tokens[pos + 1]; if ( num.size() != 0 ) { try { recurse = SST::Core::from_string(num); @@ -1779,32 +1894,126 @@ DebugConsole::cmd_print_remote(std::vector& tokens) } } } - var_index = 2; + + var_index = (pos + 2 > var_index) ? pos += 2 : var_index; } - if ( tokens.size() == var_index ) { - // Print current object - obj_->list(recurse); - return true; + // See if have a -v or not + int print_verbose = 0; + pos = containsArg(tokens, "-v"); + if ( std::string::npos != pos ) { + // Got a -v + if ( tokens.size() < (pos + 2) ) { + printf("Invalid format for print command (print [-r N] [-v N] [-f ] [][[idx][idx]])\n"); + return false; + } + std::string num = tokens[pos + 1]; + if ( num.size() != 0 ) { + try { + print_verbose = std::stoi(num, nullptr, 10); + } + catch ( const std::invalid_argument& e ) { + printf("Invalid number format specified with -v: %s\n", num.c_str()); + return false; + } + } + else { + print_verbose = 0; // default -v depth + } + + var_index = (pos + 2 > var_index) ? pos += 2 : var_index; + } + + // check for format specifier + pos = containsArg(tokens, "-f"); + std::string fmt = "dec"; + std::ios_base::fmtflags base = std::ios_base::dec; + if ( std::string::npos != pos ) { + // found format specifier + fmt = tokens[pos + 1]; + + if ( "hex" == fmt ) { + base = std::ios_base::hex; + } + else if ( "oct" == fmt ) { + base = std::ios_base::oct; + } + else { + base = std::ios_base::dec; + } + + var_index = (pos + 2 > var_index) ? pos += 2 : var_index; } if ( tokens.size() != (var_index + 1) ) { - result << "Invalid format for print command (print [-rN] [])" << std::endl; + printf("Invalid format for print command (print [-r N] [-v N] [-f ] [][[idx][idx]])\n"); return false; } - bool found; - std::string listing = obj_->listVariable(tokens[var_index], found, recurse); - if ( !found ) { - result << "Unknown object in print command: " << tokens[var_index] << std::endl; - return false; + // Check for [ ] [ ] + std::vector indices = parseBracketIndices(tokens[var_index]); + + auto* target = curObj_->findByName(tokens[var_index]); + if ( target ) { + if ( !indices.empty() ) { + SST::Core::Serialization::ContainerObj* tmp = dynamic_cast(target); + if ( tmp ) { + tmp->printElementAt(indices, print_verbose + 1, base, result); + } + else { + std::cout << "WARNING: Object not indexable" << std::endl; + target->Dump(print_verbose + 1, base, result); + } + } + else { + target->Dump(print_verbose + 1, base, result); + if ( recurse > 0 ) { + if ( target->getChildren().empty() ) { + // Object we are trying to recursively print has (potentially) not yet been serialized + // If it's a ComponentObj that hasn't been serialized yet, serialize it + if ( auto* comp = dynamic_cast(target) ) { + if ( comp->getChildren().empty() ) { + Core::Serialization::ObjectMapToTree::serializeComponent(comp, true); + } + } + } + target->applyRecursive([print_verbose, base](SST::Core::Serialization::ObjTreeCont* child) { + child->Dump(print_verbose + 1, base, result); + }); + } + } } else { - result << listing; + result << "Unknown object in print command: " << tokens[var_index] << std::endl; + // result << "Invalid format for print command (print [-rN] [])" << std::endl; + return false; } return true; } +bool +DebugConsole::containsArg(const std::string tok, const char arg) +{ + for ( size_t i = 0; i + 1 < tok.size(); ++i ) { + if ( (tok[i] == '-' && tok[i + 1] == arg) ) { + return true; + } + } + return false; +} + +size_t +DebugConsole::containsArg(const std::vector tokens, const std::string& arg) +{ + for ( size_t i = 0; i < tokens.size(); ++i ) { + if ( tokens[i] == arg ) { + return i; + } + } + return std::string::npos; +} + + // set : set object to value bool DebugConsole::cmd_set_serial(std::string& UNUSED(cmd_str)) @@ -1906,63 +2115,52 @@ DebugConsole::cmd_set_remote(std::vector& tokens) // Sanitizer indicated use of previously freed memory. // - if ( obj_->isContainer() ) { - bool found = false; - bool read_only = false; - obj_->set(tokens[1], tokens[2], found, read_only); - if ( !found ) { - result << "Unknown object in set command for container: " << tokens[1] << std::endl; - return false; - } - if ( read_only ) { - result << "Object specified in set command is read-only for container: " << tokens[1] << std::endl; - return false; - } - // TODO do we need var->selectParent() here? - return true; - } + // DDD: Do we need to check for ReadOnly in the ObjectMap? - bool loop_detected = false; - auto* var = obj_->selectVariable(tokens[1], loop_detected); - assert(var); - if ( !var || (var == obj_) ) { - result << "Unknown object in set command: " << tokens[1] << std::endl; - // TODO make sure selectVariable hasn't altered any state. - return false; + // NOTE: We assume that if there are more than 3 tokens you are setting a string. + if ( tokens.size() > 3 ) { + int totalTokens = tokens.size(); + for ( int t = 3; t < totalTokens; t++ ) { + tokens[2].push_back(' '); + tokens[2].append(tokens[t]); // pack all the other tokens into the string value that will be set. + } } - // Once we have a valid object, be sure to use var->selectParent() or - // future commands may attempt to use free'd memory. - - if ( var->isReadOnly() ) { - result << "Object specified in set command is read-only: " << tokens[1] << std::endl; - var->selectParent(); - return false; - } + // Check for [ ] [ ] + std::vector indices = parseBracketIndices(tokens[1]); - if ( !var->isFundamental() ) { - result << "Invalid object in set command: " << tokens[1] << " is not a fundamental type" << std::endl; - var->selectParent(); - return false; - } - std::string value = tokens[2]; - if ( var->getType() == "std::string" ) { - for ( size_t index = 3; index < tokens.size(); index++ ) { - value = value + " " + tokens[index]; + auto* target = curObj_->findByName(tokens[1]); + if ( target ) { + if ( !indices.empty() ) { + SST::Core::Serialization::ContainerObj* tmp = dynamic_cast(target); + if ( tmp ) { + if ( tmp->setElementFromString(indices, tokens[2]) ) { + return true; + } + else { + result << "Failed to set " << tokens[1] << " to " << tokens[2] << " (type: " << target->getType() + << ")" << std::endl; + return false; + } + } + else { + result << "ERROR: Unable to set value - object not indexable" << std::endl; + return false; + } + } + else { + if ( !target->setFromString(tokens[2]) ) { + result << "Failed to set " << tokens[1] << " to " << tokens[2] << " (type: " << target->getType() << ")" + << std::endl; + return false; + } } } else { - value = tokens[2]; - } - - try { - var->set(value); - } - catch ( const std::exception& e ) { - result << "Invalid format: " << tokens[2] << std::endl; + result << "Unknown object in set command: " << tokens[1] << std::endl; return false; } - var->selectParent(); + return true; } @@ -2270,24 +2468,19 @@ DebugConsole::cmd_addTraceVar_remote(std::vector& tokens) const std::string& tvar = tokens[tindex++]; // Find and check trace variable - Core::Serialization::ObjectMap* map = obj_->findVariable(tvar); + auto* map = curObj_->findByName(tvar); if ( nullptr == map ) { result << "Unknown variable: " << tvar << std::endl; return false; } - // Is variable fundamental - if ( !map->isFundamental() ) { - result << "Traces can only be placed on fundamental types; " << tvar << " is not fundamental" << std::endl; - return false; - } size_t bufsize = wp->getBufferSize(); if ( bufsize == 0 ) { result << "Watchpoint " << wpIndex << " does not have tracing enabled" << std::endl; return false; } - auto* ob = map->getObjectBuffer(obj_->getFullName() + "/" + tvar, bufsize); - wp->addObjectBuffer(ob); + std::unique_ptr map_uniq(map->clone()); + wp->addObjectBuffer(std::move(map_uniq)); } return true; } @@ -2427,7 +2620,8 @@ DebugConsole::cmd_printTrace_serial(std::string& UNUSED(cmd_str)) result.clear(); succeed = cmd_printTrace_remote(tokens); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -2446,7 +2640,8 @@ DebugConsole::cmd_printTrace_thread(std::string& UNUSED(cmd_str)) result.clear(); succeed = handleCommand(); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -2466,13 +2661,14 @@ DebugConsole::cmd_printTrace_rank_serial(std::string& cmd_str) if ( current_rank == 0 ) { succeed = cmd_printTrace_remote(tokens); - std::cout << result.str(); + dout << result.str(); } else { // Send to remote rank succeed = sendCommand(current_rank, current_thread, cmd_str); - std::cout << result.str(); + dout << result.str(); } + dout << dreset; return succeed; } @@ -2492,13 +2688,14 @@ DebugConsole::cmd_printTrace_rank_parallel(std::string& cmd_str) if ( current_rank == 0 ) { // Execute in correct local thread succeed = handleCommand(); - std::cout << result.str(); + dout << result.str(); } else { // Send to remote rank succeed = sendCommand(current_rank, current_thread, cmd_str); - std::cout << result.str(); + dout << result.str(); } + dout << dreset; return succeed; } @@ -2529,7 +2726,7 @@ DebugConsole::cmd_printTrace_remote(std::vector& tokens) return false; } - wp->printTrace(); + wp->printTrace(result); return true; } @@ -2666,8 +2863,13 @@ DebugConsole::cmd_logging(std::string& UNUSED(cmd_str)) return false; } if ( tokens.size() > 1 ) { + if ( tokens[1] == replayFilePath ) { + std::cout << "Logging file path and replay file path cannot be the same" << std::endl; + return false; + } loggingFilePath = tokens[1]; } + // Attempt to open an SST output file loggingFile.open(loggingFilePath); if ( !loggingFile.is_open() ) { @@ -2687,6 +2889,10 @@ DebugConsole::cmd_replay(std::string& UNUSED(cmd_str)) return false; } if ( tokens.size() > 1 ) { + if ( tokens[1] == loggingFilePath ) { + std::cout << "Replay file path and logging file path cannot be the same" << std::endl; + return false; + } replayFilePath = tokens[1]; } @@ -2741,7 +2947,8 @@ DebugConsole::cmd_watchlist_serial(std::string& UNUSED(cmd_str)) result.clear(); succeed = cmd_watchlist_remote(tokens); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -2755,7 +2962,8 @@ DebugConsole::cmd_watchlist_thread(std::string& UNUSED(cmd_str)) result.clear(); succeed = handleCommandAll(); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed; } @@ -2767,13 +2975,14 @@ DebugConsole::cmd_watchlist_rank_serial(std::string& cmd_str) result.str(""); result.clear(); bool succeed = cmd_watchlist_remote(tokens); - std::cout << result.str(); + dout << result.str(); // Send to remote rank result.str(""); result.clear(); bool succeed2 = sendCommandAll(cmd_str); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed || succeed2; } @@ -2786,14 +2995,15 @@ DebugConsole::cmd_watchlist_rank_parallel(std::string& cmd_str) result.clear(); // Handle local threads bool succeed = handleCommandAll(); - std::cout << result.str(); + dout << result.str(); // Clear R0 result string result.str(""); result.clear(); // Send to remote ranks bool succeed2 = sendCommandAll(cmd_str); - std::cout << result.str(); + dout << result.str(); + dout << dreset; return succeed || succeed2; } @@ -2844,7 +3054,7 @@ DebugConsole::cmd_define(std::string& UNUSED(cmd_str)) } // Create a user command entry (or clear existing one) - if ( cmdRegistry.beginUserCommand(tokens[1]) ) line_entry_mode = LINE_ENTRY_MODE::DEFINE; + if ( cmdRegistry.beginUserCommand(tokens[1], confirm_) ) line_entry_mode = LINE_ENTRY_MODE::DEFINE; return true; } @@ -2862,6 +3072,140 @@ DebugConsole::cmd_document(std::string& UNUSED(cmd_str)) return true; } +// Create a helper object that contains the paths to the objects, the types being compared +// as well as the operators used. Creates and returns a new ObjTreeComparison that the caller owns. +// nullptr returned as an error condition. +Core::Serialization::ObjTreeComparison* +parseComparison(std::vector& tokens, size_t& index, Core::Serialization::ObjTreeCont* curObj, + Core::Serialization::ObjTreeComparison* op = nullptr) +{ + + const std::string& var = tokens[index++]; + if ( index >= tokens.size() ) { + std::cout << "Invalid format for trigger test" << std::endl; + return nullptr; + } + const std::string& opstr = tokens[index++]; + if ( nullptr == op ) { + op = new Core::Serialization::ObjTreeComparison(); + } + op->operators.push_back(Core::Serialization::ObjTreeComparison::getOperationFromString(opstr)); + + std::string v2; + if ( Core::Serialization::ObjTreeComparison::Op::CHANGED != op->operators.back() ) { + if ( index >= tokens.size() ) { + std::cout << "Invalid format for trigger test. Valid formats are changed and " + << std::endl; + return nullptr; + } + v2 = tokens[index++]; + } + + // Is operator valid + if ( op->operators.back() == Core::Serialization::ObjTreeComparison::Op::INVALID ) { + std::cout << "Unknown comparison operation specified in trigger test" << std::endl; + return nullptr; + } + + // DDD: There is a lot of code duplicated ... this can clearly be a loop + SST::Core::Serialization::ObjTreeCont* opObj = curObj->findByName(var); + SST::Core::Serialization::ObjTreeCont* parent = nullptr; + std::deque path; + if ( nullptr != opObj ) { + if ( !opObj->isLeaf() ) { + std::cout << "WARNING: Unsupported object " << opObj->getObjName() << " in watchpoint" << std::endl; + } + parent = opObj->getParent(); + path.push_front(opObj->getObjName()); + while ( parent && !parent->isRoot() ) { + path.push_front(parent->getObjName()); + parent = parent->getParent(); + } + op->objectsToCompare.emplace_back( + std::move(path), Core::Serialization::ObjTreeComparison::valType::OBJ, opObj->clone()); + + // In changed mode, we do not use v2, but add a "placeholder" object to the compairson list. This is a touch + // wasteful, but makes our life a lot easier later + if ( op->operators.back() == Core::Serialization::ObjTreeComparison::Op::CHANGED ) { + std::deque tmpPath; + tmpPath.push_front("unnit"); + op->objectsToCompare.emplace_back( + std::move(tmpPath), Core::Serialization::ObjTreeComparison::valType::UNKNOWN, opObj->clone()); + return op; + } + } + else { + std::unique_ptr constNode = nullptr; + // Convert the string value to an Integer or FloatObj + try { + int64_t v = std::stoll(var); + constNode = std::make_unique(v, nullptr); + } + catch ( ... ) { + } + try { + double v = std::stod(var); + constNode = std::make_unique(v, nullptr); + } + catch ( ... ) { + } + if ( constNode == nullptr ) { + std::cout << "Unknown Constant in expression" << std::endl; + return nullptr; + } + std::deque const_arg; + const_arg.push_back(var); + op->objectsToCompare.emplace_back( + std::move(const_arg), Core::Serialization::ObjTreeComparison::valType::CONST, constNode->clone()); + } + + + // Check if v2 is a variable + Core::Serialization::ObjTreeCont* opObj2 = curObj->findByName(v2); + + // V2 is valid variable + if ( nullptr != opObj2 ) { + if ( !opObj2->isLeaf() ) { + std::cout << "WARNING: Unsupported object " << opObj2->getObjName() << " in watchpoint" << std::endl; + } + parent = opObj2->getParent(); + path.clear(); + path.push_front(opObj2->getObjName()); + while ( parent && !parent->isRoot() ) { + path.push_front(parent->getObjName()); + parent = parent->getParent(); + } + op->objectsToCompare.emplace_back( + std::move(path), Core::Serialization::ObjTreeComparison::valType::OBJ, opObj2->clone()); + } + else { // V2 is value string + std::unique_ptr constNode = nullptr; + // Convert the string value to an Integer or FloatObj + try { + int64_t v = std::stoll(v2); + constNode = std::make_unique(v, nullptr); + } + catch ( ... ) { + } + try { + double v = std::stod(v2); + constNode = std::make_unique(v, nullptr); + } + catch ( ... ) { + } + if ( constNode == nullptr ) { + std::cout << "Unknown Constant in expression" << std::endl; + return nullptr; + } + std::deque const_arg; + const_arg.push_back(v2); + op->objectsToCompare.emplace_back( + std::move(const_arg), Core::Serialization::ObjTreeComparison::valType::CONST, constNode->clone()); + } + + return op; +} + // helper function to parse watchpoint comparison string Core::Serialization::ObjectMapComparison* parseComparison(std::vector& tokens, size_t& index, Core::Serialization::ObjectMap* obj, std::string& name) @@ -2955,7 +3299,7 @@ parseComparison(std::vector& tokens, size_t& index, Core::Serializa // helper function to parse watchpoint action string WatchPoint::WPAction* -parseAction(std::vector& tokens, size_t& index, Core::Serialization::ObjectMap* obj) +parseAction(std::vector& tokens, size_t& index, Core::Serialization::ObjTreeCont* obj) { const std::string& action = tokens[index++]; @@ -2988,32 +3332,41 @@ parseAction(std::vector& tokens, size_t& index, Core::Serialization const std::string& tval = tokens[index++]; // Find and check variable - Core::Serialization::ObjectMap* map = obj->findVariable(tvar); + Core::Serialization::ObjTreeCont* map = obj->findByName(tvar); if ( nullptr == map ) { std::cout << "Unknown variable: " << tvar << std::endl; return nullptr; } // Is variable fundamental - if ( !map->isFundamental() ) { - std::cout << "Can only set fundamental variable, " << tvar << " is not fundamental" << std::endl; - return nullptr; - } + // if ( !map->isFundamental() ) { + // std::cout << "Can only set fundamental variable, " << tvar << " is not fundamental" << std::endl; + // return nullptr; + // } // Is variable read-only - if ( map->isReadOnly() ) { - std::cout << "Object specified in set command is read-only: " << tvar << std::endl; - return nullptr; - } + // if ( map->isReadOnly() ) { + // std::cout << "Object specified in set command is read-only: " << tvar << std::endl; + // return nullptr; + // } // Check for valid value - if ( !map->checkValue(tval) ) { - return nullptr; + // if ( !map->checkValue(tval) ) { + // return nullptr; + // } + + + std::string name; + Core::Serialization::ObjTreeCont* parent = obj->getParent(); + name.append("/" + tvar); + name.insert(0, obj->getObjName()); + while ( parent && !parent->isRoot() ) { + name.insert(0, "/"); + name.insert(0, parent->getObjName()); + parent = parent->getParent(); } - std::string name = obj->getFullName() + "/" + tvar; - - return new WatchPoint::SetVarWPAction(name, map, tval); + return new WatchPoint::SetVarWPAction(name, map->clone(), tval); } #if 0 // Do users want a heartbeat action? else if (action == "heartbeat") { @@ -3028,6 +3381,7 @@ parseAction(std::vector& tokens, size_t& index, Core::Serialization } } + // watch where // is OR ... // is changed OR OR @@ -3128,18 +3482,22 @@ DebugConsole::cmd_watch_rank_parallel(std::string& cmd_str) bool DebugConsole::cmd_watch_remote(std::vector& tokens) { - size_t index = 1; - std::string name = ""; + size_t index = 1; + std::string name = ""; + std::stringstream ss; try { // Get first comparison - Core::Serialization::ObjectMapComparison* c = parseComparison(tokens, index, obj_, name); + // allocate ObjTreeCompairson + Core::Serialization::ObjTreeComparison* c = parseComparison(tokens, index, curObj_, nullptr); if ( c == nullptr ) { result << "Invalid comparison argument passed to watch command" << std::endl; return false; } size_t wpIndex = watch_points_.size(); - auto* pt = new WatchPoint(wpIndex, name, c); + c->print(ss, 0, c->operators.size() * 2); + name = ss.str(); + auto* pt = new WatchPoint(wpIndex, name, c); #if 0 // watch variables currently don't trace, but they could automatically // trace test vars @@ -3168,13 +3526,11 @@ DebugConsole::cmd_watch_remote(std::vector& tokens) } // Get next comparison - Core::Serialization::ObjectMapComparison* c = parseComparison(tokens, index, obj_, name); + c = parseComparison(tokens, index, curObj_, c); if ( c == nullptr ) { result << "Invalid comparison argument passed to watch command" << std::endl; return false; } - pt->addComparison(c); - } // while index < tokens.size(), add another logic op and test comparision // Parse action @@ -3191,7 +3547,12 @@ DebugConsole::cmd_watch_remote(std::vector& tokens) } // Get the top level component to set the watch point - BaseComponent* comp = static_cast(base_comp_->getAddr()); + BaseComponent* comp = nullptr; + Core::Serialization::ObjTreeCont* parent = curObj_; + while ( !parent->isComponent() && !parent->isRoot() ) { + parent = parent->getParent(); + } + comp = static_cast(parent)->getVal(); if ( comp ) { comp->addWatchPoint(pt); watch_points_.emplace_back(pt, comp); @@ -3494,9 +3855,8 @@ DebugConsole::cmd_unwatch_remote(std::vector& tokens) return true; } -// parse trace buffer string to create new trace -Core::Serialization::TraceBuffer* -parseTraceBuffer(std::vector& tokens, size_t& index, Core::Serialization::ObjectMap* obj) +Core::Serialization::ObjTreeTraceBuffer* +parseTraceBuffer(std::vector& tokens, size_t& index) { size_t bufsize = 32; size_t pdelay = 0; @@ -3543,7 +3903,7 @@ parseTraceBuffer(std::vector& tokens, size_t& index, Core::Serializ try { // Setup Trace Buffer - return new Core::Serialization::TraceBuffer(obj, bufsize, pdelay); + return new Core::Serialization::ObjTreeTraceBuffer(bufsize, pdelay); } catch ( const std::exception& e ) { std::cout << "Invalid buffer argument passed to trace command\n"; @@ -3551,24 +3911,16 @@ parseTraceBuffer(std::vector& tokens, size_t& index, Core::Serializ } } -// Parse trace variable string -Core::Serialization::ObjectBuffer* -parseTraceVar(std::string& tvar, Core::Serialization::ObjectMap* obj, Core::Serialization::TraceBuffer* tb) +Core::Serialization::ObjTreeCont* +parseTraceVar(std::string& tvar, Core::Serialization::ObjTreeCont* obj) { // Find and check trace variable - Core::Serialization::ObjectMap* map = obj->findVariable(tvar); + auto* map = obj->findByName(tvar); if ( nullptr == map ) { std::cout << "Unknown variable: " << tvar << std::endl; return nullptr; } - - // Is variable fundamental - if ( !map->isFundamental() ) { - std::cout << "Traces can only be placed on fundamental types; " << tvar << "is not fundamental\n"; - return nullptr; - } - std::string name = obj->getFullName() + "/" + tvar; - return map->getObjectBuffer(name, tb->getBufferSize()); + return map; } // trace : : ... : @@ -3673,17 +4025,20 @@ DebugConsole::cmd_trace_rank_parallel(std::string& cmd_str) bool DebugConsole::cmd_trace_remote(std::vector& tokens) { - size_t index = 1; - std::string name = ""; + size_t index = 1; + std::string name = ""; + std::stringstream ss; // Get first comparison - Core::Serialization::ObjectMapComparison* c = parseComparison(tokens, index, obj_, name); + Core::Serialization::ObjTreeComparison* c = parseComparison(tokens, index, curObj_, nullptr); if ( c == nullptr ) { std::cout << "Invalid argument passed in comparison trigger command" << std::endl; return false; } size_t wpIndex = watch_points_.size(); - auto* pt = new WatchPoint(wpIndex, name, c); + c->print(ss, 0, c->operators.size() * 2); + name = ss.str(); + auto* pt = new WatchPoint(wpIndex, name, c); // Add additional comparisons and logical ops while ( index < tokens.size() ) { @@ -3707,17 +4062,16 @@ DebugConsole::cmd_trace_remote(std::vector& tokens) } // Get next comparison - Core::Serialization::ObjectMapComparison* c = parseComparison(tokens, index, obj_, name); + c = parseComparison(tokens, index, curObj_, c); if ( c == nullptr ) { std::cout << "Invalid argument in comparison of trace command\n"; return false; } - pt->addComparison(c); } // while index < tokens.size(), add another logic op and test comparision try { - auto* tb = parseTraceBuffer(tokens, index, obj_); + auto* tb = parseTraceBuffer(tokens, index); if ( tb == nullptr ) { std::cout << "Invalid trace buffer argument in trace command\n"; return false; @@ -3732,18 +4086,19 @@ DebugConsole::cmd_trace_remote(std::vector& tokens) break; } - auto* objBuf = parseTraceVar(tvar, obj_, tb); + auto* objBuf = parseTraceVar(tvar, curObj_); if ( objBuf == nullptr ) { std::cout << "Invalid trace variable argument passed to trace command\n"; return false; } - pt->addObjectBuffer(objBuf); + std::unique_ptr obj_uniq(objBuf->clone()); + pt->addObjectBuffer(std::move(obj_uniq)); } // end while get trace vars // Parse action std::string action = tokens[index]; - WatchPoint::WPAction* actionObj = parseAction(tokens, index, obj_); + WatchPoint::WPAction* actionObj = parseAction(tokens, index, curObj_); if ( actionObj == nullptr ) { std::cout << "Error in action: " << action << std::endl; return false; @@ -3759,7 +4114,13 @@ DebugConsole::cmd_trace_remote(std::vector& tokens) } // Get the top level component to set the watch point - BaseComponent* comp = static_cast(base_comp_->getAddr()); + BaseComponent* comp = nullptr; + Core::Serialization::ObjTreeCont* parent = curObj_; + while ( !parent->isComponent() && !parent->isRoot() ) { + parent = parent->getParent(); + } + + comp = static_cast(parent)->getVal(); if ( comp ) { comp->addWatchPoint(pt); watch_points_.emplace_back(pt, comp); @@ -3803,7 +4164,7 @@ DebugConsole::cmd_exit_thread(std::string& UNUSED(cmd_str)) std::cout << "Removing all watchpoints and exiting ObjectExplorer\n"; } else { - std::cout << "Exiting ObjectExplorer without clearning watchpoints\n"; + std::cout << "Exiting ObjectExplorer without clearing watchpoints\n"; } exit_console = true; return true; @@ -3823,7 +4184,7 @@ DebugConsole::cmd_exit_rank_serial(std::string& cmd_str) std::cout << "Removing all watchpoints and exiting ObjectExplorer\n"; } else { - std::cout << "Exiting ObjectExplorer without clearning watchpoints\n"; + std::cout << "Exiting ObjectExplorer without clearing watchpoints\n"; } exit_console = true; return true; @@ -3843,7 +4204,7 @@ DebugConsole::cmd_exit_rank_parallel(std::string& cmd_str) std::cout << "Removing all watchpoints and exiting ObjectExplorer\n"; } else { - std::cout << "Exiting ObjectExplorer without clearning watchpoints\n"; + std::cout << "Exiting ObjectExplorer without clearing watchpoints\n"; } exit_console = true; return true; @@ -4095,7 +4456,20 @@ CommandRegistry::seek(std::string token, SEARCH_TYPE search_type) } bool -CommandRegistry::beginUserCommand(std::string name) +CommandRegistry::replace_user_cmd(std::string token) +{ + for ( auto consoleCommand : user_registry ) { + if ( consoleCommand.match(token) ) { + consoleCommand = ConsoleCommand(token); + return true; + } + } + + return false; +} + +bool +CommandRegistry::beginUserCommand(std::string name, bool confirm) { // Make sure not a built-in command auto res = seek(name, CommandRegistry::SEARCH_TYPE::BUILTIN); @@ -4103,6 +4477,23 @@ CommandRegistry::beginUserCommand(std::string name) std::cout << "Cannot overwrite built-in command \"" << name << "\"" << std::endl; return false; } + // Make sure it is not already user defined + auto res2 = seek(name, CommandRegistry::SEARCH_TYPE::USER); + if ( res2.second ) { + if ( !confirm ) { + std::cout << "Re-defining user command \"" << name << "\"" << std::endl; + } + else { + std::string line; + std::cout << "User-defined command \"" << name << "\" already exists\n"; + std::cout << "--Type r to re-define \"" << name << "\" or a to abort define" << std::endl; + std::getline(std::cin, line); + if ( line.size() == 0 || !(line == "r") ) { + std::cout << "Ignoring command to define \"" << name << "\"" << std::endl; + return false; + } + } + } user_command_wip = name; // Create or overwrite existing user defined command user_defined_commands[user_command_wip] = {}; @@ -4139,6 +4530,19 @@ CommandRegistry::appendUserCommand(std::string token0, std::string line) void CommandRegistry::commitUserCommand() { + // Check if empty command + if ( user_defined_commands[user_command_wip].size() == 0 ) { + std::cout << "Ignore empty user-defined command\n"; + return; + } + + // Replace if it already exists + bool res = replace_user_cmd(user_command_wip); + if ( res ) { + std::cout << "Committing re-defined command \"" << user_command_wip << "\"" << std::endl; + return; + } + std::cout << "Committing definition for " << user_command_wip << std::endl; user_registry.emplace_back(ConsoleCommand(user_command_wip)); user_command_wip = ""; @@ -4229,12 +4633,15 @@ DebugConsole::handleCommand() else if ( !done ) { // If I am target thread, handle the incoming command if ( current_thread == rank_.thread ) { - if ( obj_ == nullptr ) { - // Create a new ObjectMap - obj_ = getComponentObjectMap(); - // Descend into the name_stack + // if(curObj_== nullptr || objTree_->isEmpty()){ + if ( objTree_->isEmpty() ) { + objTree_->BuildTree(getComponentInfoMap()); + curObj_ = objTree_; cd_name_stack(); } + if ( curObj_ == nullptr ) { + curObj_ = objTree_; + } auto consoleCommand = cmdRegistry.seek(tokens[0], CommandRegistry::SEARCH_TYPE::BUILTIN); succeed = consoleCommand.first.exec_remote(tokens); } @@ -4376,6 +4783,7 @@ DebugConsole::receiveCommandRankSerial() // Set done for all threads if ( tokens[0] == "done" ) { + save_name_stack(); done = true; } else if ( tokens[0] == "summary" ) { @@ -4396,12 +4804,15 @@ DebugConsole::receiveCommandRankSerial() auto consoleCommand = cmdRegistry.seek(tokens[0], CommandRegistry::SEARCH_TYPE::BUILTIN); if ( consoleCommand.second ) { // Execute in target thread - if ( obj_ == nullptr ) { - // Create a new ObjectMap - obj_ = getComponentObjectMap(); - // Descend into the name_stack + // if(curObj_ == nullptr || objTree_->isEmpty()){ + if ( objTree_->isEmpty() ) { + objTree_->BuildTree(getComponentInfoMap()); + curObj_ = objTree_; cd_name_stack(); } + if ( curObj_ == nullptr ) { + curObj_ = objTree_; + } succeed = consoleCommand.first.exec_remote(tokens); // Output::getDefaultObject().output("ReceiveCmdRankSerial: succeed %d\n", succeed); } @@ -4476,6 +4887,7 @@ DebugConsole::receiveCommandRankParallel() // Set done for all threads if ( tokens[0] == "done" ) { handleCommand(); + save_name_stack(); } else if ( tokens[0] == "summary" ) { handleCommandAll(); @@ -4655,13 +5067,16 @@ DebugConsole::executeThread(const std::string& msg) handleCommand(); } else { - // Init object map - if ( obj_ == nullptr ) { - // Create a new ObjectMap - obj_ = getComponentObjectMap(); - // Descend into the name_stack + // Init object tree + // if( curObj_ == nullptr || objTree_->isEmpty() ){ + if ( objTree_->isEmpty() ) { + objTree_->BuildTree(getComponentInfoMap()); + curObj_ = objTree_; cd_name_stack(); } + if ( curObj_ == nullptr ) { + curObj_ = objTree_; + } // Enter done loop while ( !done ) { @@ -4680,6 +5095,9 @@ DebugConsole::executeRankSerial(const std::string& UNUSED_WO_MPI(msg)) // -- Rank 0 // Executes the console and sends commands to other threads/ranks as needed if ( rank_.rank == 0 ) { + // Set autoCompleteEnable = false for MPI runs + autoCompleteEnable = false; + // Clear R0 result string result.str(""); result.clear(); @@ -4730,9 +5148,13 @@ DebugConsole::executeRankParallel(const std::string& UNUSED_WO_MPI(msg)) // -- Rank 0, Thread 0 // Executes the console and sends commands to other threads/ranks as needed if ( rank_.rank == 0 && rank_.thread == 0 ) { + // Set autoCompleteEnable = false for MPI runs + autoCompleteEnable = false; + // Clear R0 result string result.str(""); result.clear(); + // Print Summary std::cout << "\nINTERACTIVE CONSOLE" << std::endl; const std::string& str = "summary"; diff --git a/src/sst/core/impl/interactive/debugConsole.h b/src/sst/core/impl/interactive/debugConsole.h index f2ebd294c..2ee7b0598 100644 --- a/src/sst/core/impl/interactive/debugConsole.h +++ b/src/sst/core/impl/interactive/debugConsole.h @@ -17,6 +17,7 @@ #include "sst/core/impl/interactive/debugCommands.h" #include "sst/core/impl/interactive/debugStream.h" #include "sst/core/interactiveConsole.h" +#include "sst/core/serialization/ObjTree.h" #include "sst/core/serialization/objectMapDeferred.h" #include "sst/core/sst_mpi.h" #include "sst/core/threadsafe.h" @@ -78,10 +79,13 @@ class DebugConsole : public SST::InteractiveConsole // directory as far as we can. std::deque name_stack; - SST::Core::Serialization::ObjectMap* obj_ = nullptr; - bool done = false; - bool exit_console = false; - int retState = -1; // -1 DONE, -2 SUMMARY, positive number is threadID + bool done = false; + SST::Core::Serialization::ComponentObj* objTree_ = nullptr; + ; + SST::Core::Serialization::ObjTreeCont* curObj_ = nullptr; + ; + bool exit_console = false; + int retState = -1; // -1 DONE, -2 SUMMARY, positive number is threadID void save_name_stack(); void cd_name_stack(); @@ -106,9 +110,6 @@ class DebugConsole : public SST::InteractiveConsole ExecState eState = {}; std::stack eStack = {}; - // Keep a pointer to the ObjectMap for the top level Component - SST::Core::Serialization::ObjectMapDeferred* base_comp_ = nullptr; - // Keep track of all the WatchPoints std::vector> watch_points_; bool query_clear_watchlist(); @@ -119,6 +120,7 @@ class DebugConsole : public SST::InteractiveConsole // Navigation bool cmd_help(std::string& cmd_str); + bool cmd_show(std::string& cmd_str); bool cmd_verbose_query(); bool cmd_verbose_serial(std::string& cmd_str); @@ -278,8 +280,12 @@ class DebugConsole : public SST::InteractiveConsole uint32_t verbosity = 0; void msg(VERBOSITY_MASK mask, std::string message); + // Parse arguments in command + bool containsArg(const std::string tok, const char arg); + size_t containsArg(const std::vector tokens, const std::string& arg); + std::vector parseBracketIndices(std::string& token); // Pagination support - DebuggerStream dout; + DebuggerStream dout; // Support for serial, threaded, rank serial, rank parallel execution static uint32_t current_thread; diff --git a/src/sst/core/impl/interactive/debugStream.h b/src/sst/core/impl/interactive/debugStream.h index 32496895e..a0d2b2a5e 100644 --- a/src/sst/core/impl/interactive/debugStream.h +++ b/src/sst/core/impl/interactive/debugStream.h @@ -55,7 +55,8 @@ class DebuggerStreamBuf : public std::streambuf paginate_(true), quit_(false), charsPerLine_(charsPerLine), - curChars_(0) + curChars_(0), + confirm_(true) {} void reset() diff --git a/src/sst/core/interactiveConsole.cc b/src/sst/core/interactiveConsole.cc index 9b328d325..bedcd105d 100644 --- a/src/sst/core/interactiveConsole.cc +++ b/src/sst/core/interactiveConsole.cc @@ -112,6 +112,12 @@ InteractiveConsole::getComponentObjectMap() return Simulation::getSimulation()->getComponentObjectMap(); } +const ComponentInfoMap& +InteractiveConsole::getComponentInfoMap() +{ + return Simulation::getSimulation()->getComponentInfoMap(); +} + void InteractiveConsole::simulationShutdown() { diff --git a/src/sst/core/interactiveConsole.h b/src/sst/core/interactiveConsole.h index 4e60557fb..0cb74bdb9 100644 --- a/src/sst/core/interactiveConsole.h +++ b/src/sst/core/interactiveConsole.h @@ -13,6 +13,7 @@ #define SST_CORE_INTERACTIVE_CONSOLE_H #include "sst/core/action.h" +#include "sst/core/componentInfo.h" #include "sst/core/cputimer.h" #include "sst/core/eli/elementinfo.h" #include "sst/core/output.h" @@ -128,6 +129,8 @@ class InteractiveConsole SST::Core::Serialization::ObjectMap* getComponentObjectMap(); + const SST::ComponentInfoMap& getComponentInfoMap(); + void simulationShutdown(); private: diff --git a/src/sst/core/serialization/CMakeLists.txt b/src/sst/core/serialization/CMakeLists.txt index 825693571..d863034dc 100644 --- a/src/sst/core/serialization/CMakeLists.txt +++ b/src/sst/core/serialization/CMakeLists.txt @@ -19,6 +19,9 @@ add_subdirectory(impl) set(SSTSerializationHeaders objectMap.h objectMapDeferred.h + objectMapTreeBuilder.h + ObjTree.h + ObjTreeLeaves.h serializable.h serializable_base.h serialize.h diff --git a/src/sst/core/serialization/ObjTree.h b/src/sst/core/serialization/ObjTree.h new file mode 100644 index 000000000..05d0c4c1a --- /dev/null +++ b/src/sst/core/serialization/ObjTree.h @@ -0,0 +1,135 @@ +// 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_CORE_SERIALIZATION_OBJECTTREE_DEBUGGER_H +#define SST_CORE_SERIALIZATION_OBJECTTREE_DEBUGGER_H + +#include "sst/core/baseComponent.h" +#include "sst/core/componentInfo.h" +#include "sst/core/from_string.h" +#include "sst/core/serialization/ObjTreeLeaves.h" +#include "sst/core/serialization/objectMapDeferred.h" +#include "sst/core/warnmacros.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SST::Core::Serialization { + + +class ComponentObj : public ObjTree +{ + +private: + BaseComponent* val_ = nullptr; + ComponentInfo* compInfo_ = nullptr; + +public: + ComponentObj() = default; + ComponentObj(BaseComponent* v, ComponentInfo* ci) : + ObjTree(NodeKind::Component), + val_(v), + compInfo_(ci) + { + setName(v->getName()); + } + + ComponentObj(const ComponentObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + compInfo_(rhs.compInfo_) + {} + + ComponentObj& operator=(const ComponentObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + compInfo_ = rhs.compInfo_; + return *this; + } + + ObjTreeCont* clone() const override { return new ComponentObj(*this); } + + BaseComponent* getVal() const { return val_; } + ComponentInfo* getInfo() const { return compInfo_; } + + void setVal(BaseComponent* v) { val_ = v; } + + void apply() override { std::cout << "Processing component: " << val_->getName() << std::endl; } + void Dump([[maybe_unused]] const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + if ( verbosity < 3 ) { + os << val_->getName() << "/" << std::endl; + } + else { + os << val_->getName() << "/ (" << compInfo_->getType() << ")" << std::endl; + } + } + + ComponentObj* find(const std::string name) + { + ComponentObj* result = nullptr; + applyRecursiveByType([&result, &name](ComponentObj* obj) { + if ( obj->getVal()->getName() == name ) { + result = obj; + } + }); + return result; + } +}; + +template +void +ObjTree::BuildTree(const ComponentInfoMap& compMap) +{ + if ( !children_.empty() ) { + std::cout << "WARNING: Calling BuildTree on non-empty ObjTree" << std::endl; + } + for ( auto comp = compMap.begin(); comp != compMap.end(); comp++ ) { + ComponentInfo* compinfo = *comp; + BaseComponent* bc = compinfo->getComponent(); + ComponentObj* c = new ComponentObj(bc, compinfo); + addChildObj(c); + } + + std::sort(children_.begin(), children_.end(), + [](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->getObjName() < b->getObjName(); + }); +} + + +} // namespace SST::Core::Serialization + +#endif diff --git a/src/sst/core/serialization/ObjTreeLeaves.h b/src/sst/core/serialization/ObjTreeLeaves.h new file mode 100644 index 000000000..57b5ab1bb --- /dev/null +++ b/src/sst/core/serialization/ObjTreeLeaves.h @@ -0,0 +1,996 @@ +// 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_CORE_SERIALIZATION_OBJECTTREELEAVES_DEBUGGER_H +#define SST_CORE_SERIALIZATION_OBJECTTREELEAVES_DEBUGGER_H +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace SST { +class ComponentInfoMap; +} + +namespace SST::Core::Serialization { +class ObjTreeCont +{ +public: + enum class NodeKind { Generic, Integer, Float, String, Bool, Component, Container, FRef, GenericVal }; + + ObjTreeCont() : + parent_(nullptr), + children_(), + name_("uninit"), + type_("uninit"), + kind_(NodeKind::Generic), + readOnly_(false) {}; + ObjTreeCont(const std::string& name, const std::string& type, NodeKind kind = NodeKind::Generic) : + parent_(nullptr), + children_(), + name_(name), + type_(type), + kind_(kind), + readOnly_(false) + {} + virtual ~ObjTreeCont() = default; + + ObjTreeCont(const ObjTreeCont& rhs) : + parent_(nullptr), + children_(), + name_(rhs.name_), + type_(rhs.type_), + kind_(rhs.kind_), + readOnly_(rhs.readOnly_) + { + children_.reserve(rhs.children_.size()); + for ( const auto& child : rhs.children_ ) { + auto* cloned = child->clone(); + cloned->parent_ = this; + children_.emplace_back(cloned); + } + } + + ObjTreeCont& operator=(const ObjTreeCont& rhs) + { + if ( this == &rhs ) return *this; + parent_ = nullptr; + name_ = rhs.name_; + type_ = rhs.type_; + kind_ = rhs.kind_; + children_.clear(); + children_.reserve(rhs.children_.size()); + for ( const auto& child : rhs.children_ ) { + auto* cloned = child->clone(); + cloned->parent_ = this; + children_.emplace_back(cloned); + } + return *this; + } + + virtual ObjTreeCont* clone() const { return new ObjTreeCont(*this); } + + void addChildObj(ObjTreeCont* obj) + { + children_.push_back(std::unique_ptr(obj)); + obj->parent_ = this; + } + + void setParent(ObjTreeCont* p) { parent_ = p; } + ObjTreeCont* getParent() const { return parent_; } + const std::vector>& getChildren() const { return children_; } + + const std::string& getObjName() const { return name_; } + const std::string& getType() const { return type_; } + void setName(const std::string& name) { name_ = name; } + void setType(const std::string& type) { type_ = prettifyType(type); } + bool isRoot() { return parent_ == nullptr; } + void makeReadOnly() { readOnly_ = true; } + bool isReadOnly() { return readOnly_; } + + template + void applyRecursive(Func&& func) + { + for ( auto& child : children_ ) { + func(child.get()); + } + } + + template + void applyRecursiveByType(Func&& func) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + func(child_t); + } + } + } + + template + ObjectType* findByType(Func&& predicate) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + if ( predicate(child_t) ) return child_t; + } + } + return nullptr; + } + + ObjTreeCont* findByName(const std::string name) + { + for ( size_t i = 0; i < children_.size(); i++ ) { + if ( children_[i]->getObjName() == name ) { + return children_[i].get(); + } + } + return nullptr; + } + + virtual void apply() {}; + virtual std::string getTypeName() const { return type_; }; + virtual void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) + { + os << name_ << "/ " << std::endl; //(" << type_ << ")" << std::endl; + if ( verbosity > 0 ) { + applyRecursive([&](ObjTreeCont* child) { child->Dump(verbosity - 1, base, os); }); + } + } + + virtual bool setFromString([[maybe_unused]] const std::string& value) { return false; } + virtual void syncFromSim() {}; + virtual bool hasChanged() { return false; } + + NodeKind getKind() const { return kind_; } + bool isComponent() const { return kind_ == NodeKind::Component; } + bool isLeaf() const + { + return kind_ == NodeKind::Integer || kind_ == NodeKind::Float || kind_ == NodeKind::String || + kind_ == NodeKind::Bool || kind_ == NodeKind::GenericVal; + } + + virtual void clear() { children_.clear(); } + +protected: + ObjTreeCont* parent_; + std::vector> children_; + std::string name_; + std::string type_; + NodeKind kind_; + bool readOnly_; + + static void replaceAll(std::string& s, std::string_view from, std::string_view to) + { + if ( from.empty() ) return; + size_t pos = 0; + while ( (pos = s.find(from, pos)) != std::string::npos ) { + s.replace(pos, from.size(), to); + pos += to.size(); + } + } + + static std::string prettifyType(std::string t) + { + replaceAll(t, "std::__1::", "std::"); + replaceAll(t, "std::__cxx11::", "std::"); + replaceAll(t, " ", " "); + return t; + } +}; + +template +class ObjTree : public ObjTreeCont +{ +public: + ObjTree() = default; + ObjTree(NodeKind kind) : + ObjTreeCont("", "", kind) + {} + + ObjTree(const ObjTree& rhs) : + ObjTreeCont(rhs), + objects_() + { + objects_.reserve(rhs.objects_.size()); + for ( const auto& obj : rhs.objects_ ) { + auto* cloned = obj->clone(); + cloned->setParent(this); + objects_.emplace_back(cloned); + } + } + + ObjTree& operator=(const ObjTree& other) + { + if ( this == &other ) return *this; + ObjTreeCont::operator=(other); + objects_.clear(); + objects_.reserve(other.objects_.size()); + for ( const auto& obj : other.objects_ ) { + auto* cloned = obj->clone(); + cloned->setParent(this); + objects_.emplace_back(cloned); + } + return *this; + } + + void BuildTree(const ComponentInfoMap& compMap); + + Obj_T& getObj() { return static_cast(*this); } + const Obj_T& getObj() const { return static_cast(*this); } + + + template + void applyRecursiveByType(Func&& func) + { + for ( auto& child : children_ ) { + if ( auto* child_t = dynamic_cast(child.get()) ) { + func(child_t); + } + } + } + + std::string getTypeName() const override { return typeid(Obj_T).name(); } + + bool isEmpty() { return objects_.empty() && children_.empty(); } + + void Dump([[maybe_unused]] const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + os << "Root/" << std::endl; + } + void clear() override + { + ObjTreeCont::clear(); + objects_.clear(); + } + +protected: + std::vector> objects_; +}; + +class IntegerObj : public ObjTree +{ +public: + using IntVariant = std::variant; + +private: + IntVariant val_; + void* addr_ = nullptr; + std::function getter_; // accessor-callback mode + std::function setter_; + bool useAccessor_ = false; + +public: + template + IntegerObj(T v, void* addr) : + ObjTree(NodeKind::Integer), + val_(v), + addr_(addr) + {} + IntegerObj(std::function getter, std::function setter) : + ObjTree(NodeKind::Integer), + val_(int64_t { 0 }), + getter_(std::move(getter)), + setter_(std::move(setter)), + useAccessor_(true) + { + if ( getter_ ) val_ = static_cast(getter_()); + if ( !setter_ ) readOnly_ = true; + } + + IntegerObj(const IntegerObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_), + getter_(rhs.getter_), + setter_(rhs.setter_), + useAccessor_(rhs.useAccessor_) + {} + IntegerObj& operator=(const IntegerObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + getter_ = rhs.getter_; + setter_ = rhs.setter_; + useAccessor_ = rhs.useAccessor_; + return *this; + } + ObjTreeCont* clone() const override { return new IntegerObj(*this); } + + template + T getVal() const + { + return std::get(val_); + } + + template + void setVal(T v) + { + val_ = v; + } + + template + void setSimVal(T v) + { + val_ = v; + syncToSim(); + } + + virtual void syncFromSim() override + { + if ( useAccessor_ && getter_ ) { + const int64_t live = getter_(); + std::visit([live](auto& v) { v = static_cast>(live); }, val_); + } + else if ( addr_ ) { + std::visit([this](auto& v) { v = *static_cast*>(addr_); }, val_); + } + } + + virtual bool hasChanged() override + { + if ( useAccessor_ && getter_ ) { + const int64_t live = getter_(); + return std::visit([live](const auto& v) -> bool { return static_cast(v) != live; }, val_); + } + else if ( addr_ ) { + return std::visit( + [this](const auto& v) -> bool { return v != *static_cast*>(addr_); }, val_); + } + return false; + } + + template + auto visit(Visitor&& visitor) + { + return std::visit(std::forward(visitor), val_); + } + + template + auto visit(Visitor&& visitor) const + { + return std::visit(std::forward(visitor), val_); + } + + void apply() override + { + visit([](auto val) { std::cout << "Processing integer: " << static_cast(val) << std::endl; }); + } + + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + visit([&](auto val) { + auto old_flags = os.flags(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << " = " << static_cast(val) << std::endl; + os.flags(old_flags); + }); + } + else { + visit([&](auto val) { + auto old_flags = os.flags(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << " = " << static_cast(val) << " (" << getType() << ")" << std::endl; + os.flags(old_flags); + }); + } + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + std::cout << "WARNING Cannot set ReadOnly Obj " << name_ << std::endl; + return false; + } + try { + visit([&](auto& current) { + using T = std::decay_t; + setSimVal(static_cast(std::stoll(value))); + }); + return true; + } + catch ( ... ) { + return false; + } + } + +private: + void syncToSim() + { + if ( !addr_ ) return; + std::visit([this](auto& v) { *static_cast*>(addr_) = v; }, val_); + } +}; + +class FloatObj : public ObjTree +{ +public: + using FloatVariant = std::variant; + +private: + FloatVariant val_; + void* addr_; + std::function getter_; // accessor-callback mode + std::function setter_; + bool useAccessor_ = false; + +public: + template + FloatObj(T v, void* addr) : + ObjTree(NodeKind::Float), + val_(v), + addr_(addr) + {} + FloatObj(std::function getter, std::function setter) : + ObjTree(NodeKind::Integer), + val_(0.0), + getter_(std::move(getter)), + setter_(std::move(setter)), + useAccessor_(true) + { + if ( getter_ ) val_ = static_cast(getter_()); + if ( !setter_ ) readOnly_ = true; + } + + FloatObj(const FloatObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_), + getter_(rhs.getter_), + setter_(rhs.setter_), + useAccessor_(rhs.useAccessor_) + {} + + FloatObj& operator=(const FloatObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + getter_ = rhs.getter_; + setter_ = rhs.setter_; + useAccessor_ = rhs.useAccessor_; + return *this; + } + + ObjTreeCont* clone() const override { return new FloatObj(*this); } + + template + T getVal() const + { + return std::get(val_); + } + + template + void setVal(T v) + { + val_ = v; + } + + template + void setSimVal(T v) + { + val_ = v; + syncToSim(); + } + + virtual void syncFromSim() override + { + if ( useAccessor_ && getter_ ) { + const long double live = getter_(); + std::visit([live](auto& v) { v = static_cast>(live); }, val_); + } + else if ( addr_ ) { + std::visit([this](auto& v) { v = *static_cast*>(addr_); }, val_); + } + } + + virtual bool hasChanged() override + { + if ( useAccessor_ && getter_ ) { + const long double live = getter_(); + return std::visit( + [live](const auto& v) -> bool { return static_cast(v) != static_cast(live); }, + val_); + } + else if ( addr_ ) { + return std::visit( + [this](const auto& v) -> bool { return v != *static_cast*>(addr_); }, val_); + } + return false; + } + + template + auto visit(Visitor&& visitor) + { + return std::visit(std::forward(visitor), val_); + } + + template + auto visit(Visitor&& visitor) const + { + return std::visit(std::forward(visitor), val_); + } + + void apply() override + { + visit([](auto val) { std::cout << "Processing float: " << val << std::endl; }); + } + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + visit([&](auto val) { + auto old_flags = os.flags(); + auto old_prec = os.precision(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << std::fixed << std::setprecision(12) << " = " << val << std::endl; + os.flags(old_flags); + os.precision(old_prec); + }); + } + else { + visit([&](auto val) { + auto old_flags = os.flags(); + auto old_prec = os.precision(); + os.setf(base, std::ios_base::basefield); + if ( base != std::ios_base::dec ) { + os.setf(std::ios_base::showbase); + } + os << getObjName() << ro << std::fixed << std::setprecision(12) << " = " << val << " (" << getType() + << ")" << std::endl; + os.flags(old_flags); + os.precision(old_prec); + }); + } + } + + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + std::cout << "WARNING Cannot set ReadOnly Obj " << name_ << std::endl; + return false; + } + try { + visit([&](auto& current) { + using T = std::decay_t; + setSimVal(static_cast(std::stold(value))); + }); + return true; + } + catch ( ... ) { + return false; + } + } + +private: + void syncToSim() + { + if ( !addr_ ) return; + std::visit([this](auto& v) { *static_cast*>(addr_) = v; }, val_); + } +}; + +class ContainerObj : public ObjTree +{ + size_t size_ = 0; + ObjectMap* sourceMap_ = nullptr; + +public: + ContainerObj(const std::string& name, const std::string& type, size_t size, ObjectMap* source) : + ObjTree(NodeKind::Container), + size_(size), + sourceMap_(source) + { + setName(name); + setType(type); + } + + ContainerObj(const ContainerObj& rhs) : + ObjTree(rhs), + size_(rhs.size_), + sourceMap_(rhs.sourceMap_) + { + setName(rhs.name_); + setType(rhs.type_); + } + + ContainerObj& operator=(const ContainerObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + name_ = rhs.name_; + type_ = rhs.type_; + size_ = rhs.size_; + sourceMap_ = rhs.sourceMap_; + return *this; + } + + ObjTreeCont* clone() const override { return new ContainerObj(*this); } + + + const std::string& getContainerType() const { return type_; } + size_t getSize() const { return size_; } + + void syncFromSim() override + { + if ( !sourceMap_ ) return; + size_ = sourceMap_->getVariables().size(); // or cheaper accessor if available + } + + bool hasChanged() override + { + if ( !sourceMap_ ) return false; + return size_ != sourceMap_->getVariables().size(); + } + + void apply() override { std::cout << "Container: " << name_ << " (" << type_ << ") size=" << size_ << std::endl; } + + void Dump( + const int verbosity, std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) override + { + if ( verbosity == 0 ) { + os << name_ << " [" << size_ << " elements] (" << type_ << ")" << std::endl; + } + else { + os << name_ << " [" << size_ << " elements] (" << type_ << ")" << std::endl; + applyRecursive([&](ObjTreeCont* child) { child->Dump(verbosity - 1, base, os); }); + } + } + + ObjTreeCont* getElementAt(std::vector indices) const + { + ObjTreeCont* current = const_cast(this); + + for ( size_t idx : indices ) { + if ( !current ) return nullptr; + + auto& elems = current->getChildren(); + if ( idx >= elems.size() ) return nullptr; + + current = elems[idx].get(); + } + return current; + } + + void printElementAt(std::vector indices, int verbosity = 1, + std::ios_base::fmtflags base = std::ios_base::dec, std::ostream& os = std::cout) const + { + ObjTreeCont* elem = getElementAt(indices); + if ( elem ) { + elem->Dump(verbosity, base, os); + } + else { + os << "Element not found at path {"; + bool first = true; + for ( auto i : indices ) { + if ( !first ) os << ", "; + os << i; + first = false; + } + os << "}" << std::endl; + } + } + + bool setElementFromString(std::vector indices, std::string val) + { + ObjTreeCont* elem = getElementAt(indices); + bool success = elem != nullptr; + if ( elem ) { + success = elem->setFromString(val); + } + if ( !success ) { + std::cout << "Element not found at path {"; + bool first = true; + for ( auto i : indices ) { + if ( !first ) std::cout << ", "; + std::cout << i; + first = false; + } + std::cout << "}" << std::endl; + } + return success; + } +}; + +// Node for string types (treated specially since they're fundamental-like) +class StringObj : public ObjTree +{ + std::string val_; + void* addr_; + +public: + StringObj(const std::string& v, void* addr) : + ObjTree(NodeKind::String), + val_(v), + addr_(addr) + {} + StringObj(const StringObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_) + {} + + StringObj& operator=(const StringObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + return *this; + } + + ObjTreeCont* clone() const override { return new StringObj(*this); } + + const std::string& getVal() const { return val_; } + void setVal(const std::string& v) { val_ = v; } + void setSimVal(const std::string& v) + { + val_ = v; + *static_cast(addr_) = val_; + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + std::cout << "WARNING Cannot set ReadOnly Obj " << name_ << std::endl; + return false; + } + setSimVal(value); + return true; + } + virtual void syncFromSim() override { val_ = *static_cast(addr_); } + virtual bool hasChanged() override + { + if ( !addr_ ) return false; + return val_ != *static_cast(addr_); + } + + void apply() override { std::cout << "Processing string: " << val_ << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = \"" << val_ << "\"" << std::endl; + } + else { + os << getObjName() << ro << " = \"" << val_ << "\"" << " (" << getType() << ")" << std::endl; + } + } +}; + +// Node for bool (separate from integer for clarity) +class BoolObj : public ObjTree +{ +private: + bool val_; + void* addr_ = nullptr; // This points back to the ObjectMap + std::function getter_; // accessor-callback mode. these are used to access bitset and vector types + std::function setter_; // These will be set by ObjectMapFundamentalReference if needed + bool useAccessor_ = false; // control if we use addr_ to update the value from the sim or do we use getter_/setter_ + +public: + BoolObj(bool v, void* addr) : + ObjTree(NodeKind::Bool), + val_(v), + addr_(addr) + {} + BoolObj(std::function getter, std::function setter) : + ObjTree(NodeKind::Bool), + getter_(std::move(getter)), + setter_(std::move(setter)), + useAccessor_(true) + { + if ( getter_ ) val_ = getter_(); + if ( !setter_ ) readOnly_ = true; + } + + BoolObj(const BoolObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_), + getter_(rhs.getter_), + setter_(rhs.setter_), + useAccessor_(rhs.useAccessor_) + {} + + BoolObj& operator=(const BoolObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + getter_ = rhs.getter_; + setter_ = rhs.setter_; + useAccessor_ = rhs.useAccessor_; + return *this; + } + + ObjTreeCont* clone() const override { return new BoolObj(*this); } + + bool getVal() const { return val_; } + void setVal(bool v) { val_ = v; } + void setSimVal(bool v) + { + if ( readOnly_ ) { + return; + } + if ( useAccessor_ ) { + if ( setter_ ) { + setter_(v); + } + } + else if ( addr_ ) { + *(static_cast(addr_)) = v; + val_ = v; + } + } + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + std::cout << "WARNING Cannot set ReadOnly Obj " << name_ << std::endl; + return false; + } + setSimVal(value == "true" || value == "1"); + return true; + } + virtual void syncFromSim() override + { + if ( useAccessor_ && getter_ ) { + val_ = getter_(); + } + else if ( addr_ ) { + val_ = *(static_cast(addr_)); + } + } + virtual bool hasChanged() override + { + if ( useAccessor_ && getter_ ) { + return val_ != getter_(); + } + if ( addr_ ) { + return val_ != *static_cast(addr_); + } + return false; + } + + void apply() override { std::cout << "Processing bool: " << (val_ ? "true" : "false") << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = " << (val_ ? "true" : "false") << std::endl; + } + else { + os << getObjName() << ro << " = " << (val_ ? "true" : "false") << " (" << getType() << ")" << std::endl; + } + } +}; + +class GenericValObj : public ObjTree +{ + std::string val_; + void* addr_ = nullptr; + ObjectMap* sourceMap_ = nullptr; // for write-back via string interface + +public: + GenericValObj(const std::string& val, void* addr, ObjectMap* source) : + ObjTree(NodeKind::GenericVal), + val_(val), + addr_(addr), + sourceMap_(source) + {} + + GenericValObj(const GenericValObj& rhs) : + ObjTree(rhs), + val_(rhs.val_), + addr_(rhs.addr_), + sourceMap_(rhs.sourceMap_) + {} + + GenericValObj& operator=(const GenericValObj& rhs) + { + if ( this == &rhs ) return *this; + ObjTree::operator=(rhs); + val_ = rhs.val_; + addr_ = rhs.addr_; + sourceMap_ = rhs.sourceMap_; + return *this; + } + + ObjTreeCont* clone() const override { return new GenericValObj(*this); } + + const std::string& getVal() const { return val_; } + + // Write-back through ObjectMap's string-based set interface, + // which knows the real type and handles conversion internally. + bool setFromString(const std::string& value) override + { + if ( readOnly_ ) { + std::cout << "WARNING Cannot set ReadOnly Obj " << name_ << std::endl; + return false; + } + if ( !sourceMap_ ) return false; + if ( sourceMap_->isReadOnly() ) return false; + sourceMap_->set(value); + // Re-read to confirm the value was accepted + val_ = sourceMap_->get(); + return true; + } + + // NOTE: we are currently not carrying around sourceMap so this + // will ALWAYS return false + bool hasChanged() override + { + if ( !sourceMap_ ) return false; + return val_ != sourceMap_->get(); + } + + void apply() override { std::cout << "Processing generic: " << val_ << std::endl; } + + void Dump(const int verbosity, [[maybe_unused]] std::ios_base::fmtflags base = std::ios_base::dec, + std::ostream& os = std::cout) override + { + std::string ro = (readOnly_) ? " (ro)" : ""; + if ( verbosity == 0 ) { + os << getObjName() << ro << std::endl; + } + else if ( verbosity == 1 ) { + os << getObjName() << ro << " = " << val_ << std::endl; + } + else { + os << getObjName() << ro << " = " << val_ << " (" << getType() << ")" << std::endl; + } + } +}; + +} // namespace SST::Core::Serialization + +#endif diff --git a/src/sst/core/serialization/objectMap.h b/src/sst/core/serialization/objectMap.h index f0a9b8bde..91052cdaa 100644 --- a/src/sst/core/serialization/objectMap.h +++ b/src/sst/core/serialization/objectMap.h @@ -41,6 +41,7 @@ // #define _OBJMAP_DEBUG_ namespace SST::Core::Serialization { +class ObjTreeCont; // Comparison of two keys: If both keys are integers, use numeric comparison, else lexicographic struct ObjectMultimapCmp @@ -186,6 +187,9 @@ class ObjectMapComparison */ class ObjectMap { +public: + enum class ObjectCategory : uint8_t { Generic = 0, Component, SubComponent, Module }; + protected: /** Metadata object for walking the object hierarchy. When this @@ -203,7 +207,9 @@ class ObjectMap will return to the highest level path and the metadata from that path to the current path will be erased. */ - ObjectMapMetaData* mdata_ = nullptr; + ObjectMapMetaData* mdata_ = nullptr; + ObjectCategory category_ = ObjectCategory::Generic; + /** Indicates whether or not the variable is read-only @@ -349,6 +355,9 @@ class ObjectMap */ size_t getRefCount() const { return refCount_; } + ObjectCategory getCategory() const { return category_; } + void setCategory(ObjectCategory cat) { category_ = cat; } + /** Get a watch point for this object. If it is not a valid object for a watch point, nullptr will be returned. @@ -559,6 +568,15 @@ class ObjectMap */ virtual void refresh() {} + /** + Helper function to build an ObjTreeCont representation of this + ObjectMap, if the subclass has type-specific knowledge of how + to do so. This is useful for reference proxy types (std::bitset + std::atomic<>, vector, etc). Returning nullptr means + "use the generic ObjMapToTree::convert path." + */ + virtual SST::Core::Serialization::ObjTreeCont* buildTreeNode(const std::string& UNUSED(name)) { return nullptr; } + private: /** Called to activate this ObjectMap. This will create the @@ -1336,67 +1354,69 @@ class ObjectMapFundamental : public ObjectMap // Create ObjectMapComparison_var which compares two variables // Only support arithmetic types for now if constexpr ( std::is_arithmetic_v ) { - if ( type == "int" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "unsigned" || type == "unsigned int" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "long" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "unsigned long" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "char" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "signed char" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "unsigned char" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "short" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "unsigned short" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "long long" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "unsigned long long" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "bool" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "float" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "double" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - else if ( type == "long double" ) { - return new ObjectMapComparison_var( - name, addr_, op, name2, static_cast(var2->getAddr())); - } - } // end if first var is arithmetic + return new ObjectMapComparison_var(name, addr_, op, name2, static_cast(var2->getAddr())); + } /* + if ( type == "int" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "unsigned" || type == "unsigned int" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "long" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "unsigned long" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "char" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "signed char" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "unsigned char" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "short" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "unsigned short" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "long long" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "unsigned long long" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "bool" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "float" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "double" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + else if ( type == "long double" ) { + return new ObjectMapComparison_var( + name, addr_, op, name2, static_cast(var2->getAddr())); + } + } // end if first var is arithmetic*/ std::cout << "Invalid type for comparison: " << name2 << "(" << type << ")\n"; return nullptr; @@ -1472,8 +1492,15 @@ class ObjectMapFundamentalReference : public ObjectMapFundamental ObjectMapFundamentalReference(const ObjectMapFundamentalReference&) = default; ObjectMapFundamentalReference& operator=(const ObjectMapFundamentalReference&) = delete; ~ObjectMapFundamentalReference() override = default; + + ObjTreeCont* buildTreeNode(const std::string& name) override; }; } // namespace SST::Core::Serialization +//clang-format off +#include "sst/core/serialization/objectMapTreeBuilder.h" +//clang-format on + + #endif // SST_CORE_SERIALIZATION_OBJECTMAP_H diff --git a/src/sst/core/serialization/objectMapDeferred.h b/src/sst/core/serialization/objectMapDeferred.h index ca0126681..9eda20b1a 100644 --- a/src/sst/core/serialization/objectMapDeferred.h +++ b/src/sst/core/serialization/objectMapDeferred.h @@ -12,6 +12,7 @@ #ifndef SST_CORE_SERIALIZATION_OBJECTMAPDEFERRED_H #define SST_CORE_SERIALIZATION_OBJECTMAPDEFERRED_H +#include "sst/core/baseComponent.h" #include "sst/core/serialization/serializer.h" #include @@ -79,7 +80,12 @@ class ObjectMapDeferred : public ObjectMap ObjectMap(), addr_(addr), type_(demangle_name(type.c_str())) - {} + { + // Set category based on type + if constexpr ( std::is_base_of_v || std::is_base_of_v ) { + setCategory(ObjectCategory::Component); + } + } ~ObjectMapDeferred() override { delete obj_; } @@ -122,6 +128,25 @@ class ObjectMapDeferred : public ObjectMap std::string type_ = ""; }; +class ComponentSerializer : public ObjectMapDeferred +{ +public: + ComponentSerializer(BaseComponent* comp) : + ObjectMapDeferred(comp, typeid(*comp).name()) + {} + + // Expose the protected activate to trigger serialization + void serialize() { activate_callback(); } + + // Check if serialization produced results + bool hasSerialized() const + { + // After activate_callback, obj_ is set via addVariable("!proxy!", ...) + // getVariables() delegates to obj_->getVariables() + return !getVariables().empty(); + } +}; + } // namespace SST::Core::Serialization #endif // SST_CORE_SERIALIZATION_OBJECTMAPDEFERRED_H diff --git a/src/sst/core/serialization/objectMapTreeBuilder.h b/src/sst/core/serialization/objectMapTreeBuilder.h new file mode 100644 index 000000000..3fe8e3cd1 --- /dev/null +++ b/src/sst/core/serialization/objectMapTreeBuilder.h @@ -0,0 +1,51 @@ +#ifndef SST_CORE_SERIALIZATION_OBJECTMAP_TREE_BUILDERS_H +#define SST_CORE_SERIALIZATION_OBJECTMAP_TREE_BUILDERS_H + +#include "sst/core/serialization/ObjTreeLeaves.h" +#include "sst/core/serialization/objectMap.h" + +namespace SST::Core::Serialization { + +template +SST::Core::Serialization::ObjTreeCont* +ObjectMapFundamentalReference::buildTreeNode(const std::string& name) +{ + using namespace SST::Core::Serialization; + + // Capture the proxy by value. The proxy holds a back-pointer + // into the live storage (bitset/vector/atomic), so reads + // and writes on the captured copy reflect live state. + + REF proxy = ref; + ObjTreeCont* node = nullptr; + + // if order matters here - check bool first as is_integral may also match on bool + if constexpr ( std::is_same_v ) { + node = + new BoolObj([proxy]() mutable { return static_cast(proxy); }, [proxy](bool v) mutable { proxy = v; }); + } + else if constexpr ( std::is_integral_v ) { + node = new IntegerObj([proxy]() mutable { return static_cast(static_cast(proxy)); }, + [proxy](int64_t v) mutable { proxy = static_cast(v); }); + } + else if constexpr ( std::is_floating_point_v ) { + node = new FloatObj([proxy]() mutable { return static_cast(static_cast(proxy)); }, + [proxy](long double v) mutable { proxy = static_cast(v); }); + } + else { + return nullptr; + } + + node->setName(name); + node->setType(this->getType()); + if ( this->isReadOnly() ) { + if ( auto* b = dynamic_cast(node) ) b->makeReadOnly(); + if ( auto* i = dynamic_cast(node) ) i->makeReadOnly(); + if ( auto* f = dynamic_cast(node) ) f->makeReadOnly(); + } + return node; +} + +} // namespace SST::Core::Serialization + +#endif diff --git a/src/sst/core/watchPoint.cc b/src/sst/core/watchPoint.cc index 2a30f893f..31ce4b1d7 100644 --- a/src/sst/core/watchPoint.cc +++ b/src/sst/core/watchPoint.cc @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -69,7 +70,7 @@ void WatchPoint::SetVarWPAction::invokeAction(WatchPoint* wp) { try { - obj_->set(valStr_); + obj_->setFromString(valStr_); } catch ( const std::exception& e ) { printf("Invalid set var: %s\n", valStr_.c_str()); @@ -92,14 +93,13 @@ WatchPoint::ShutdownWPAction::invokeAction(WatchPoint* wp) return; } -WatchPoint::WatchPoint(size_t index, const std::string& name, Core::Serialization::ObjectMapComparison* obj) : +WatchPoint::WatchPoint(size_t index, const std::string& name, Core::Serialization::ObjTreeComparison* obj) : Clock::HandlerBase::AttachPoint(), Event::HandlerBase::AttachPoint(), + cmpObjects_(obj), name_(name), wpIndex(index) -{ - addComparison(obj); -} +{} void WatchPoint::genericHandler(HANDLER h) @@ -201,12 +201,12 @@ WatchPoint::printTriggerRecord() } void -WatchPoint::printTrace() +WatchPoint::printTrace(std::ostream& os) { if ( tb_ != nullptr ) { std::cout << "TriggerCount=" << triggerCount << "\n"; - tb_->dumpTriggerRecord(); - tb_->dumpTraceBufferT(); + tb_->dumpTriggerRecord(os); + tb_->dumpTraceBufferT(os); } else { printf(" No tracing enabled\n"); @@ -274,9 +274,7 @@ WatchPoint::printWatchpoint(std::stringstream& ss) ss << "TriggerCount " << triggerCount << " : "; printHandler(ss); // TODO: print the logic values - for ( size_t i = 0; i < numCmpObj_; i++ ) { // Print trigger tests - cmpObjects_[i]->print(ss); - } + cmpObjects_->print(ss, 0, cmpObjects_->operators.size() * 2); ss << " : "; if ( tb_ != nullptr ) { // print trace buffer config @@ -361,22 +359,15 @@ WatchPoint::printAction(std::stringstream& ss) } void -WatchPoint::addTraceBuffer(Core::Serialization::TraceBuffer* tb) +WatchPoint::addTraceBuffer(Core::Serialization::ObjTreeTraceBuffer* tb) { tb_ = tb; } void -WatchPoint::addObjectBuffer(Core::Serialization::ObjectBuffer* ob) +WatchPoint::addObjectBuffer(std::unique_ptr ob) { - tb_->addObjectBuffer(ob); -} - -void -WatchPoint::addComparison(Core::Serialization::ObjectMapComparison* cmp) -{ - cmpObjects_.push_back(cmp); - numCmpObj_++; + tb_->addObjectBuffer(std::move(ob)); } void @@ -393,23 +384,25 @@ WatchPoint::check() { bool result = false; - if ( cmpObjects_[0]->compare() ) { + if ( cmpObjects_->evaluateComparison(0, nullptr) ) { + result = true; } std::stringstream s; s << std::boolalpha; s << " WatchPoint " << name_.c_str() << " tests:\n"; s << " "; - cmpObjects_[0]->print(s); + cmpObjects_->print(s, 0, 1); s << " -> " << result << std::endl; - for ( size_t i = 1; i < numCmpObj_; i++ ) { + for ( size_t i = 1; i < cmpObjects_->operators.size(); i++ ) { bool result2 = false; - if ( cmpObjects_[i]->compare() ) { + if ( cmpObjects_->evaluateComparison(i, nullptr) ) { result2 = true; } + // printf(" comparison%ld = %d\n", i, result2); s << " "; - cmpObjects_[i]->print(s); + cmpObjects_->print(s, i * 2, i * 2 + 1); s << " -> " << result2 << std::endl; if ( logicOps_[i - 1] == LogicOp::AND ) { diff --git a/src/sst/core/watchPoint.h b/src/sst/core/watchPoint.h index 395b7e0d0..23cf38902 100644 --- a/src/sst/core/watchPoint.h +++ b/src/sst/core/watchPoint.h @@ -14,6 +14,7 @@ #include "sst/core/clock.h" #include "sst/core/event.h" +#include "sst/core/impl/interactive/ObjTreeHelpers.h" #include "sst/core/serialization/objectMap.h" #include "sst/core/stringize.h" @@ -99,7 +100,7 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler class SetVarWPAction : public WPAction { public: - SetVarWPAction(std::string vname, Core::Serialization::ObjectMap* obj, std::string tval) : + SetVarWPAction(std::string vname, Core::Serialization::ObjTreeCont* obj, std::string tval) : name_(vname), obj_(obj), valStr_(tval) @@ -109,9 +110,9 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler void invokeAction(WatchPoint* wp) override; private: - std::string name_ = ""; - Core::Serialization::ObjectMap* obj_ = nullptr; - std::string valStr_ = ""; + std::string name_ = ""; + Core::Serialization::ObjTreeCont* obj_ = nullptr; + std::string valStr_ = ""; }; // class SetVarWPAction class ShutdownWPAction : public WPAction @@ -124,7 +125,7 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler }; // class ShutdownWPAction // Construction - WatchPoint(size_t index, const std::string& name, Core::Serialization::ObjectMapComparison* obj); + WatchPoint(size_t index, const std::string& name, Core::Serialization::ObjTreeComparison* obj); ~WatchPoint() = default; // Inherited from both Event and Clock handler AttachPoints. @@ -143,7 +144,7 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler inline std::string getName() { return name_; } size_t getBufferSize(); void printTriggerRecord(); - void printTrace(); + void printTrace(std::ostream& os = std::cout); enum HANDLER : unsigned { // Select which handlers do check and sample @@ -173,9 +174,8 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler void resetTraceBuffer(); inline bool checkReset() { return reset_; } void printAction(std::stringstream& ss); - void addTraceBuffer(Core::Serialization::TraceBuffer* tb); - void addObjectBuffer(Core::Serialization::ObjectBuffer* ob); - void addComparison(Core::Serialization::ObjectMapComparison* cmp); + void addTraceBuffer(Core::Serialization::ObjTreeTraceBuffer* tb); + void addObjectBuffer(std::unique_ptr ob); enum LogicOp : unsigned { // Logical Op for trigger tests AND = 0, @@ -196,18 +196,18 @@ class WatchPoint : public Clock::HandlerBase::AttachPoint, public Event::Handler void simulationShutdown(); private: - size_t numCmpObj_ = 0; - std::vector cmpObjects_; - std::vector logicOps_; - std::string name_; - Core::Serialization::TraceBuffer* tb_ = nullptr; - size_t wpIndex; - HANDLER handler = ALL; - bool trigger = false; - HANDLER triggerHandler = HANDLER::NONE; - size_t triggerCount = 0; - bool reset_ = false; - WPAction* wpAction; + // size_t numCmpObj_ = 0; + std::unique_ptr cmpObjects_; + std::vector logicOps_; + std::string name_; + Core::Serialization::ObjTreeTraceBuffer* tb_ = nullptr; + size_t wpIndex; + HANDLER handler = ALL; + bool trigger = false; + HANDLER triggerHandler = HANDLER::NONE; + size_t triggerCount = 0; + bool reset_ = false; + WPAction* wpAction; void setBufferReset(); void check(); diff --git a/tests/Makefile.inc b/tests/Makefile.inc index a1e1e2e12..082999419 100644 --- a/tests/Makefile.inc +++ b/tests/Makefile.inc @@ -15,6 +15,7 @@ EXTRA_DIST += \ tests/cmd_DebugConsole_serial1.cmd \ tests/cmd_DebugConsole_thread0.cmd \ tests/cmd_DebugConsole_thread1.cmd \ + tests/cmd_DebugConsole_tracebuf.cmd \ tests/testsuite_default_Checkpoint.py \ tests/testsuite_default_Component.py \ tests/testsuite_default_ComponentExtension.py \ @@ -94,6 +95,7 @@ EXTRA_DIST += \ tests/refFiles/test_DebugConsole_serial1.out \ tests/refFiles/test_DebugConsole_thread0.out \ tests/refFiles/test_DebugConsole_thread1.out \ + tests/refFiles/test_DebugConsole_tracebuf.out \ tests/refFiles/test_PerfComponent.out \ tests/refFiles/test_DistribComponent_discrete.out \ tests/refFiles/test_DistribComponent_expon.out \ diff --git a/tests/cmd_DebugConsole_tracebuf.cmd b/tests/cmd_DebugConsole_tracebuf.cmd new file mode 100644 index 000000000..2543dab62 --- /dev/null +++ b/tests/cmd_DebugConsole_tracebuf.cmd @@ -0,0 +1,18 @@ +confirm false +cd component2 +ls -l +trace message_count_ changed : 32 4 : message_count_ : printTrace +sethandler 0 ae ac +printwatchpoint 0 +printtrace 0 +run 3000ps +wl +print message_count_ +printwatchpoint 0 +printtrace 0 +run 3000ps +wl +print message_count_ +printwatchpoint 0 +printtrace 0 +shutd diff --git a/tests/refFiles/test_DebugConsole_Checkpoint_serial0.out b/tests/refFiles/test_DebugConsole_Checkpoint_serial0.out index 894ea7cf3..3538e2ac3 100644 --- a/tests/refFiles/test_DebugConsole_Checkpoint_serial0.out +++ b/tests/refFiles/test_DebugConsole_Checkpoint_serial0.out @@ -8,7 +8,7 @@ c1, setup() c0, setup() ---- Rank0:Thread0: Entering interactive mode at time 0 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_checkpoint_serial0.cmd +> replay cmd_DebugConsole_Checkpoint_serial0.cmd > confirm false > # 0 watch @@ -31,7 +31,7 @@ c1 talkingc1, bounce 991, t=9000000 c0 talkingClock cycle count = 1 c0 talkingRNG: 4074790800, 774252441, 24684 c0 talkingDistributions: 1.500000, 5.000000, 0.721430, 0.919625, 0.000000, 1.000000 -# Simulation Checkpoint: Simulated Time 10 us (Real CPU time since last checkpoint 0.04483 seconds) +# Simulation Checkpoint: Simulated Time 10 us (Real CPU time since last checkpoint 0.01002 seconds) c1 talkingClock cycle count = 1 c1 talkingRNG: 4074790800, 774252441, 24684 c1 talkingDistributions: 1.500000, 1.000000, 0.721430, 0.919625, 0.000000, 1.000000 @@ -42,11 +42,11 @@ c3 talkingClock cycle count = 1 c3 talkingRNG: 4074790800, 774252441, 24684 c3 talkingDistributions: 1.500000, 1.000000, 0.721430, 0.919625, 0.000000, 1.000000 ---- Rank0:Thread0: Entering interactive mode at time 10000000 - Last Trigger: WP0: AC : c0/xorshift/w ... + Last Trigger: WP0: AC : /c0/xorshift/w CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 1 : ALL : c0/xorshift/w CHANGED : interactive -1: TriggerCount 1 : ALL : c0/xorshift/w CHANGED : bufsize = 16 postDelay = 0 : c0/xorshift/w : checkpoint +0: TriggerCount 1 : ALL : /c0/xorshift/w CHANGED : interactive +1: TriggerCount 1 : ALL : /c0/xorshift/w CHANGED : bufsize = 16 postDelay = 0 : w : checkpoint > unwatch 0 > unwatch 1 > shutd diff --git a/tests/refFiles/test_DebugConsole_Checkpoint_serial1.out b/tests/refFiles/test_DebugConsole_Checkpoint_serial1.out index af44d6723..f026f91e3 100644 --- a/tests/refFiles/test_DebugConsole_Checkpoint_serial1.out +++ b/tests/refFiles/test_DebugConsole_Checkpoint_serial1.out @@ -8,7 +8,7 @@ c1, setup() c0, setup() ---- Rank0:Thread0: Entering interactive mode at time 1000000 Interactive start at 1000000 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_Checkpoint_serial1.cmd +> replay cmd_DebugConsole_Checkpoint_serial1.cmd > confirm false > # 0 watch @@ -31,7 +31,7 @@ c1 talkingc1, bounce 991, t=9000000 c0 talkingClock cycle count = 1 c0 talkingRNG: 4074790800, 774252441, 24684 c0 talkingDistributions: 1.500000, 5.000000, 0.721430, 0.919625, 0.000000, 1.000000 -# Simulation Checkpoint: Simulated Time 10 us (Real CPU time since last checkpoint 0.03792 seconds) +# Simulation Checkpoint: Simulated Time 10 us (Real CPU time since last checkpoint 0.00859 seconds) c1 talkingClock cycle count = 1 c1 talkingRNG: 4074790800, 774252441, 24684 c1 talkingDistributions: 1.500000, 1.000000, 0.721430, 0.919625, 0.000000, 1.000000 @@ -42,11 +42,11 @@ c3 talkingClock cycle count = 1 c3 talkingRNG: 4074790800, 774252441, 24684 c3 talkingDistributions: 1.500000, 1.000000, 0.721430, 0.919625, 0.000000, 1.000000 ---- Rank0:Thread0: Entering interactive mode at time 10000000 - Last Trigger: WP0: AC : c0/xorshift/w ... + Last Trigger: WP0: AC : /c0/xorshift/w CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 1 : ALL : c0/xorshift/w CHANGED : interactive -1: TriggerCount 1 : ALL : c0/xorshift/w CHANGED : bufsize = 16 postDelay = 0 : c0/xorshift/w : checkpoint +0: TriggerCount 1 : ALL : /c0/xorshift/w CHANGED : interactive +1: TriggerCount 1 : ALL : /c0/xorshift/w CHANGED : bufsize = 16 postDelay = 0 : w : checkpoint > unwatch 0 > unwatch 1 > shutd diff --git a/tests/refFiles/test_DebugConsole_r2_rankserial0.out b/tests/refFiles/test_DebugConsole_r2_rankserial0.out index dcad7dfab..420f16d4d 100644 --- a/tests/refFiles/test_DebugConsole_r2_rankserial0.out +++ b/tests/refFiles/test_DebugConsole_r2_rankserial0.out @@ -1,3 +1,19 @@ +LastTriggerRecord:@cycle6000: SamplesLost=0: message_count_ = 24 +set component8/my_id_ 50 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 + Trigger action shutting down simulation +wp simulation shutdown +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 + Trigger action shutting down simulation +wp simulation shutdown +15 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages +11 received 34 messages +10 received 40 messages +9 received 39 messages +50 received 31 messages INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/1 (Triggered) @@ -24,7 +40,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_r2_rankserial0.cmd +> replay cmd_DebugConsole_r2_rankserial0.cmd > # Requires 2 ranks > confirm false @@ -85,10 +101,10 @@ component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 3000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 3 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 3 : ALL : /component0/message_count_ CHANGED : interactive R1,T0: Current watch points: > unwatch 0 > cd .. @@ -97,7 +113,7 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -127,7 +143,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R1,T0: Current watch points: > unwatch 1 > # 2 trace printTrace @@ -136,15 +152,15 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #2 > setHandler 2 ae -WP 2 - component5/message_count_ +WP 2 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=5 -LastTriggerRecord:@cycle5000: SamplesLost=0: component5/message_count_=16 -buf[0] AE @4000 (!) component5/message_count_=12 -buf[1] AE @4000 (+) component5/message_count_=13 -buf[2] AE @4000 (+) component5/message_count_=14 -buf[3] AE @5000 (+) component5/message_count_=15 -buf[4] AE @5000 (+) component5/message_count_=16 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 16 +buf[0] AE @4000 (!) message_count_ = 12 +buf[1] AE @4000 (+) message_count_ = 13 +buf[2] AE @4000 (+) message_count_ = 14 +buf[3] AE @5000 (+) message_count_ = 15 +buf[4] AE @5000 (+) message_count_ = 16 INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/1 (Triggered) @@ -173,7 +189,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: -2: TriggerCount 5 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +2: TriggerCount 5 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R1,T0: Current watch points: > unwatch 2 > # 3 trace set @@ -184,7 +200,7 @@ Interactive start at 0 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -215,7 +231,7 @@ Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 > #print my_id_ > unwatch 0 > # 4 trace interactive @@ -224,7 +240,7 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -255,7 +271,7 @@ Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -1: TriggerCount 7 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 7 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive > unwatch 1 > # 5 trace shutdown > cd .. @@ -401,19 +417,3 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- -LastTriggerRecord:@cycle6000: SamplesLost=0: component8/message_count_=24 -set component8/my_id_ 50 -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages diff --git a/tests/refFiles/test_DebugConsole_r2_rankserial1.out b/tests/refFiles/test_DebugConsole_r2_rankserial1.out index f58eb0cdc..5d41b1890 100644 --- a/tests/refFiles/test_DebugConsole_r2_rankserial1.out +++ b/tests/refFiles/test_DebugConsole_r2_rankserial1.out @@ -1,3 +1,19 @@ +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 21 +set component8/my_id_ 50 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 + Trigger action shutting down simulation +wp simulation shutdown +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 + Trigger action shutting down simulation +wp simulation shutdown +15 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages +11 received 34 messages +10 received 40 messages +9 received 39 messages +50 received 31 messages INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/1 (Triggered) @@ -24,7 +40,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_r2_rankserial1.cmd +> replay cmd_DebugConsole_r2_rankserial1.cmd > # Requires 4 ranks > confirm false @@ -59,10 +75,10 @@ component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 4 : ALL : /component0/message_count_ CHANGED : interactive R1,T0: Current watch points: > unwatch 0 > cd .. @@ -71,7 +87,7 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -101,7 +117,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R1,T0: Current watch points: > unwatch 1 > # 2 trace printTrace @@ -110,15 +126,15 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #2 > setHandler 2 ae -WP 2 - component5/message_count_ +WP 2 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=5 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=13 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 13 +buf[0] AE @3000 (!) message_count_ = 9 +buf[1] AE @3000 (+) message_count_ = 10 +buf[2] AE @3000 (+) message_count_ = 11 +buf[3] AE @4000 (+) message_count_ = 12 +buf[4] AE @4000 (+) message_count_ = 13 INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/1 (Triggered) @@ -147,7 +163,7 @@ component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: -2: TriggerCount 1 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +2: TriggerCount 1 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R1,T0: Current watch points: > unwatch 2 > # 3 trace set @@ -158,7 +174,7 @@ Interactive start at 1 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -189,7 +205,7 @@ Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 > #print my_id_ > unwatch 0 > # 4 trace interactive @@ -198,7 +214,7 @@ R1,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -229,7 +245,7 @@ Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 9 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive > unwatch 1 > # 5 trace shutdown > cd .. @@ -445,19 +461,3 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 -set component8/my_id_ 50 -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages diff --git a/tests/refFiles/test_DebugConsole_r4_rankserial0.out b/tests/refFiles/test_DebugConsole_r4_rankserial0.out index 10e93281a..12123b403 100644 --- a/tests/refFiles/test_DebugConsole_r4_rankserial0.out +++ b/tests/refFiles/test_DebugConsole_r4_rankserial0.out @@ -1,20 +1,30 @@ -TriggerCount=5 -LastTriggerRecord:@cycle5000: SamplesLost=0: component5/message_count_=16 -buf[0] AE @4000 (!) component5/message_count_=12 -buf[1] AE @4000 (+) component5/message_count_=13 -buf[2] AE @4000 (+) component5/message_count_=14 -buf[3] AE @5000 (+) component5/message_count_=15 -buf[4] AE @5000 (+) component5/message_count_=16 -7 received 25 messages -6 received 31 messages -5 received 28 messages -4 received 28 messages -LastTriggerRecord:@cycle6000: SamplesLost=0: component8/message_count_=24 +LastTriggerRecord:@cycle6000: SamplesLost=0: message_count_ = 24 set component8/my_id_ 50 11 received 34 messages 10 received 40 messages 9 received 39 messages 50 received 31 messages +TriggerCount=5 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 16 +buf[0] AE @4000 (!) message_count_ = 12 +buf[1] AE @4000 (+) message_count_ = 13 +buf[2] AE @4000 (+) message_count_ = 14 +buf[3] AE @5000 (+) message_count_ = 15 +buf[4] AE @5000 (+) message_count_ = 16 +7 received 25 messages +6 received 31 messages +5 received 28 messages +4 received 28 messages +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 + Trigger action shutting down simulation +wp simulation shutdown +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 + Trigger action shutting down simulation +wp simulation shutdown +15 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages INTERACTIVE CONSOLE -- Rank:0/4 Thread:0/1 (Triggered) @@ -47,7 +57,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankserial0.cmd +> replay cmd_DebugConsole_r4_rankserial0.cmd > # Requires 4 ranks > confirm false @@ -120,10 +130,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 3000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 3 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 3 : ALL : /component0/message_count_ CHANGED : interactive R1,T0: Current watch points: R2,T0: Current watch points: R3,T0: Current watch points: @@ -134,7 +144,7 @@ R3,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -170,7 +180,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R1,T0: Current watch points: R2,T0: Current watch points: R3,T0: Current watch points: @@ -184,7 +194,7 @@ Interactive start at 0 > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps INTERACTIVE CONSOLE @@ -221,7 +231,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -0: TriggerCount 5 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +0: TriggerCount 5 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R2,T0: Current watch points: R3,T0: Current watch points: > unwatch 0 @@ -233,7 +243,7 @@ Interactive start at 0 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -271,7 +281,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R1,T0: Current watch points: R2,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R3,T0: Current watch points: > #print my_id_ > unwatch 0 @@ -281,7 +291,7 @@ R3,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -319,7 +329,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R1,T0: Current watch points: R2,T0: Current watch points: -1: TriggerCount 7 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 7 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R3,T0: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -416,13 +426,3 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages diff --git a/tests/refFiles/test_DebugConsole_r4_rankserial1.out b/tests/refFiles/test_DebugConsole_r4_rankserial1.out index c765a34da..20762dad8 100644 --- a/tests/refFiles/test_DebugConsole_r4_rankserial1.out +++ b/tests/refFiles/test_DebugConsole_r4_rankserial1.out @@ -1,24 +1,7 @@ -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 -set component8/my_id_ 50 -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages -TriggerCount=5 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=13 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 -7 received 25 messages -6 received 31 messages -5 received 28 messages -4 received 28 messages -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 Trigger action shutting down simulation wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 Trigger action shutting down simulation wp simulation shutdown 15 received 28 messages @@ -57,7 +40,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankserial1.cmd +> replay cmd_DebugConsole_r4_rankserial1.cmd > # Requires 4 ranks > confirm false @@ -98,10 +81,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 4 : ALL : /component0/message_count_ CHANGED : interactive R1,T0: Current watch points: R2,T0: Current watch points: R3,T0: Current watch points: @@ -112,7 +95,7 @@ R3,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -148,7 +131,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R1,T0: Current watch points: R2,T0: Current watch points: R3,T0: Current watch points: @@ -162,7 +145,7 @@ Interactive start at 1 > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps INTERACTIVE CONSOLE @@ -199,7 +182,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R1,T0: Current watch points: -0: TriggerCount 1 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +0: TriggerCount 1 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R2,T0: Current watch points: R3,T0: Current watch points: > unwatch 0 @@ -211,7 +194,7 @@ Interactive start at 1 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -249,7 +232,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R1,T0: Current watch points: R2,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R3,T0: Current watch points: > #print my_id_ > unwatch 0 @@ -259,7 +242,7 @@ R3,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -297,7 +280,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R1,T0: Current watch points: R2,T0: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 9 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R3,T0: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -414,3 +397,20 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 21 +set component8/my_id_ 50 +11 received 34 messages +10 received 40 messages +9 received 39 messages +50 received 31 messages +TriggerCount=5 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 13 +buf[0] AE @3000 (!) message_count_ = 9 +buf[1] AE @3000 (+) message_count_ = 10 +buf[2] AE @3000 (+) message_count_ = 11 +buf[3] AE @4000 (+) message_count_ = 12 +buf[4] AE @4000 (+) message_count_ = 13 +7 received 25 messages +6 received 31 messages +5 received 28 messages +4 received 28 messages diff --git a/tests/refFiles/test_DebugConsole_rankparallel0.out b/tests/refFiles/test_DebugConsole_rankparallel0.out index 43073bccc..20600ccd5 100644 --- a/tests/refFiles/test_DebugConsole_rankparallel0.out +++ b/tests/refFiles/test_DebugConsole_rankparallel0.out @@ -1,3 +1,19 @@ +LastTriggerRecord:@cycle6000: SamplesLost=0: message_count_ = 24 +set component8/my_id_ 50 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 + Trigger action shutting down simulation +wp simulation shutdown +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 + Trigger action shutting down simulation +wp simulation shutdown +15 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages +11 received 34 messages +10 received 40 messages +9 received 39 messages +50 received 31 messages INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/2 (Triggered) @@ -30,7 +46,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankparallel0.cmd +> replay cmd_DebugConsole_rankparallel0.cmd > # Requires 2 ranks, each with 2 threads > confirm false @@ -103,10 +119,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 3000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 3 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 3 : ALL : /component0/message_count_ CHANGED : interactive R0,T1: Current watch points: R1,T0: Current watch points: R1,T1: Current watch points: @@ -117,7 +133,7 @@ R1,T1: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -153,7 +169,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R0,T1: Current watch points: R1,T0: Current watch points: R1,T1: Current watch points: @@ -167,15 +183,15 @@ Interactive start at 0 > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=5 -LastTriggerRecord:@cycle5000: SamplesLost=0: component5/message_count_=16 -buf[0] AE @4000 (!) component5/message_count_=12 -buf[1] AE @4000 (+) component5/message_count_=13 -buf[2] AE @4000 (+) component5/message_count_=14 -buf[3] AE @5000 (+) component5/message_count_=15 -buf[4] AE @5000 (+) component5/message_count_=16 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 16 +buf[0] AE @4000 (!) message_count_ = 12 +buf[1] AE @4000 (+) message_count_ = 13 +buf[2] AE @4000 (+) message_count_ = 14 +buf[3] AE @5000 (+) message_count_ = 15 +buf[4] AE @5000 (+) message_count_ = 16 INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/2 (Triggered) @@ -211,7 +227,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R0,T1: Current watch points: -0: TriggerCount 5 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +0: TriggerCount 5 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R1,T0: Current watch points: R1,T1: Current watch points: > unwatch 0 @@ -226,7 +242,7 @@ Interactive start at 0 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -264,7 +280,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R1,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R1,T1: Current watch points: > #print my_id_ > unwatch 0 @@ -274,7 +290,7 @@ R1,T1: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -312,7 +328,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R1,T0: Current watch points: -1: TriggerCount 7 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 7 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R1,T1: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -413,19 +429,3 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- -LastTriggerRecord:@cycle6000: SamplesLost=0: component8/message_count_=24 -set component8/my_id_ 50 -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages diff --git a/tests/refFiles/test_DebugConsole_rankparallel1.out b/tests/refFiles/test_DebugConsole_rankparallel1.out index a460b4054..70dd36b7c 100644 --- a/tests/refFiles/test_DebugConsole_rankparallel1.out +++ b/tests/refFiles/test_DebugConsole_rankparallel1.out @@ -1,19 +1,3 @@ -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 -set component8/my_id_ 50 -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/2 (Triggered) @@ -46,7 +30,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankparallel1.cmd +> replay cmd_DebugConsole_rankparallel1.cmd > # Requires 2 ranks, each with 2 threads > confirm false @@ -87,10 +71,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 4 : ALL : /component0/message_count_ CHANGED : interactive R0,T1: Current watch points: R1,T0: Current watch points: R1,T1: Current watch points: @@ -101,7 +85,7 @@ R1,T1: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps INTERACTIVE CONSOLE @@ -137,7 +121,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R0,T1: Current watch points: R1,T0: Current watch points: R1,T1: Current watch points: @@ -151,15 +135,15 @@ Interactive start at 1 > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=5 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=13 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 13 +buf[0] AE @3000 (!) message_count_ = 9 +buf[1] AE @3000 (+) message_count_ = 10 +buf[2] AE @3000 (+) message_count_ = 11 +buf[3] AE @4000 (+) message_count_ = 12 +buf[4] AE @4000 (+) message_count_ = 13 INTERACTIVE CONSOLE -- Rank:0/2 Thread:0/2 (Triggered) @@ -195,7 +179,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R0,T1: Current watch points: -0: TriggerCount 1 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +0: TriggerCount 1 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace R1,T0: Current watch points: R1,T1: Current watch points: > unwatch 0 @@ -210,7 +194,7 @@ Interactive start at 1 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps INTERACTIVE CONSOLE @@ -248,7 +232,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R1,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R1,T1: Current watch points: > #print my_id_ > unwatch 0 @@ -258,7 +242,7 @@ R1,T1: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -296,7 +280,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R1,T0: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 9 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R1,T1: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -417,3 +401,19 @@ Simulation is complete, simulated time: 0 s StopAction to be delivered at 10000000 StopAction to be delivered at 18446744073709551615 ---- Components: ---- +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 21 +set component8/my_id_ 50 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 + Trigger action shutting down simulation +wp simulation shutdown +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 + Trigger action shutting down simulation +wp simulation shutdown +15 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages +11 received 34 messages +10 received 40 messages +9 received 39 messages +50 received 31 messages diff --git a/tests/refFiles/test_DebugConsole_rankserial0.out b/tests/refFiles/test_DebugConsole_rankserial0.out deleted file mode 100644 index 10e93281a..000000000 --- a/tests/refFiles/test_DebugConsole_rankserial0.out +++ /dev/null @@ -1,428 +0,0 @@ -TriggerCount=5 -LastTriggerRecord:@cycle5000: SamplesLost=0: component5/message_count_=16 -buf[0] AE @4000 (!) component5/message_count_=12 -buf[1] AE @4000 (+) component5/message_count_=13 -buf[2] AE @4000 (+) component5/message_count_=14 -buf[3] AE @5000 (+) component5/message_count_=15 -buf[4] AE @5000 (+) component5/message_count_=16 -7 received 25 messages -6 received 31 messages -5 received 28 messages -4 received 28 messages -LastTriggerRecord:@cycle6000: SamplesLost=0: component8/message_count_=24 -set component8/my_id_ 50 -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 1000 -Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankserial0.cmd - -> # Requires 4 ranks -> confirm false -> run 1ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 2000 -Ran clock for 1 sim cycles -> # 0 watch -> cd component0 -> watch message_count_ changed -Added watchpoint #0 -> run - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 3000 - Last Trigger: WP0: AE : component0/message_count_ ... -> wl -R0,T0: Current watch points: -0: TriggerCount 3 : ALL : component0/message_count_ CHANGED : interactive -R1,T0: Current watch points: -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 0 -> cd .. -> # 1 trace printStatus -> cd component2 -> trace message_count_ changed : 16 0 : message_count_ : printStatus -Added watchpoint #1 -> setHandler 1 ae -WP 1 - component2/message_count_ -> run 1ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 4000 -Ran clock for 1 sim cycles -> wl -R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus -R1,T0: Current watch points: -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 1 -> # 2 trace printTrace -> #cd .. -> rank 1 ----- Rank1:Thread0: Entering interactive mode at time 4000 -Interactive start at 0 -> cd component5 -> trace message_count_ changed : 16 4 : message_count_ : printTrace -Added watchpoint #0 -> setHandler 0 ae -WP 0 - component5/message_count_ -> run 2000ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank1:Thread0: Entering interactive mode at time 6000 -Ran clock for 2000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -0: TriggerCount 5 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 0 -> # 3 trace set -> rank 2 ----- Rank2:Thread0: Entering interactive mode at time 6000 -Interactive start at 0 -> cd component8 -> trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 -Added watchpoint #0 -> setHandler 0 ae -WP 0 - component8/message_count_ -> run 1000ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank2:Thread0: Entering interactive mode at time 7000 -Ran clock for 1000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -R2,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 -R3,T0: Current watch points: -> #print my_id_ -> unwatch 0 -> # 4 trace interactive -> cd .. -> cd component10 -> trace message_count_ changed : 16 2 : message_count_ : interactive -Added watchpoint #1 -> setHandler 1 ae -WP 1 - component10/message_count_ -> run - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Not Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank2:Thread0: Entering interactive mode at time 8000 -Ran clock for 1000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -R2,T0: Current watch points: -1: TriggerCount 7 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive -R3,T0: Current watch points: -> unwatch 1 -> # 5 trace shutdown -> #cd .. -> rank 3 ----- Rank3:Thread0: Entering interactive mode at time 8000 -Interactive start at 0 -> cd component12 -> trace message_count_ changed : 16 2 : message_count_ : shutdown -Added watchpoint #0 -> run -3 received 28 messages -2 received 38 messages -1 received 29 messages -0 received 32 messages -Simulation is complete, simulated time: 0 s - CurrentSimCycle: 3000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 14, queue order: 44 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 50 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 51 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 52 - SST::Action to be delivered at time: 3001, priority: 0, order tag: 0, queue order: 53 - SyncManager to be delivered at 4000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 59 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 60 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 55 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 56 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 57 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 58 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 61 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 3000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 14, queue order: 44 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 50 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 51 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 52 - SST::Action to be delivered at time: 3001, priority: 0, order tag: 0, queue order: 53 - SyncManager to be delivered at 4000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 59 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 60 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 55 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 56 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 57 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 58 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 61 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 3000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 14, queue order: 44 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 50 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 51 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 52 - SST::Action to be delivered at time: 3001, priority: 0, order tag: 0, queue order: 53 - SyncManager to be delivered at 4000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 59 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 60 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 55 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 56 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 57 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 58 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 61 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 62 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 3000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 14, queue order: 44 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 50 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 51 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 16, queue order: 52 - SST::Action to be delivered at time: 3001, priority: 0, order tag: 0, queue order: 53 - SyncManager to be delivered at 4000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 59 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 1, queue order: 60 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 55 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 56 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 57 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 6, queue order: 58 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 61 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 4000, priority: 50, order tag: 14, queue order: 62 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages diff --git a/tests/refFiles/test_DebugConsole_rankserial1.out b/tests/refFiles/test_DebugConsole_rankserial1.out deleted file mode 100644 index c765a34da..000000000 --- a/tests/refFiles/test_DebugConsole_rankserial1.out +++ /dev/null @@ -1,416 +0,0 @@ -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 -set component8/my_id_ 50 -11 received 34 messages -10 received 40 messages -9 received 39 messages -50 received 31 messages -TriggerCount=5 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=13 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 -7 received 25 messages -6 received 31 messages -5 received 28 messages -4 received 28 messages -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 - Trigger action shutting down simulation -wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 - Trigger action shutting down simulation -wp simulation shutdown -15 received 28 messages -14 received 35 messages -13 received 34 messages -12 received 32 messages - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 1000 -Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_rankserial1.cmd - -> # Requires 4 ranks -> confirm false -> #run 1ps -> # 0 watch -> cd component0 -> watch message_count_ changed -Added watchpoint #0 -> run - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... -> wl -R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive -R1,T0: Current watch points: -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 0 -> cd .. -> # 1 trace printStatus -> cd component2 -> trace message_count_ changed : 16 0 : message_count_ : printStatus -Added watchpoint #1 -> setHandler 1 ae -WP 1 - component2/message_count_ -> run 1ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank0:Thread0: Entering interactive mode at time 3000 -Ran clock for 1 sim cycles -> wl -R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus -R1,T0: Current watch points: -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 1 -> # 2 trace printTrace -> #cd .. -> rank 1 ----- Rank1:Thread0: Entering interactive mode at time 3000 -Interactive start at 1 -> cd component5 -> trace message_count_ changed : 16 4 : message_count_ : printTrace -Added watchpoint #0 -> setHandler 0 ae -WP 0 - component5/message_count_ -> run 2000ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank1:Thread0: Entering interactive mode at time 5000 -Ran clock for 2000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -0: TriggerCount 1 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace -R2,T0: Current watch points: -R3,T0: Current watch points: -> unwatch 0 -> # 3 trace set -> rank 2 ----- Rank2:Thread0: Entering interactive mode at time 5000 -Interactive start at 1 -> cd component8 -> trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 -Added watchpoint #0 -> setHandler 0 ae -WP 0 - component8/message_count_ -> run 1000ps - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Not Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank2:Thread0: Entering interactive mode at time 6000 -Ran clock for 1000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -R2,T0: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 -R3,T0: Current watch points: -> #print my_id_ -> unwatch 0 -> # 4 trace interactive -> cd .. -> cd component10 -> trace message_count_ changed : 16 2 : message_count_ : interactive -Added watchpoint #1 -> setHandler 1 ae -WP 1 - component10/message_count_ -> run - -INTERACTIVE CONSOLE --- Rank:0/4 Thread:0/1 (Not Triggered) --- Component Summary -component0/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component1/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component2/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component3/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:1/4 Thread:0/1 (Not Triggered) --- Component Summary -component4/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component5/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component6/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component7/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:2/4 Thread:0/1 (Triggered) --- Component Summary -component10/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component11/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component8/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component9/ (SST::CoreTest::MessageMesh::EnclosingComponent) - --- Rank:3/4 Thread:0/1 (Not Triggered) --- Component Summary -component12/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component13/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) -component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) - ----- Rank2:Thread0: Entering interactive mode at time 8000 -Ran clock for 1000 sim cycles -> wl -R0,T0: Current watch points: -R1,T0: Current watch points: -R2,T0: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive -R3,T0: Current watch points: -> unwatch 1 -> # 5 trace shutdown -> #cd .. -> rank 3 ----- Rank3:Thread0: Entering interactive mode at time 8000 -Interactive start at 1 -> cd component12 -> trace message_count_ changed : 16 2 : message_count_ : shutdown -Added watchpoint #0 -> run -3 received 28 messages -2 received 38 messages -1 received 29 messages -0 received 32 messages -Simulation is complete, simulated time: 0 s - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 9, queue order: 27 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 9, queue order: 28 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 30 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 31 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 12, queue order: 34 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 9, queue order: 28 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 30 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 31 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 12, queue order: 34 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 30 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 31 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 12, queue order: 34 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 11, queue order: 31 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 12, queue order: 34 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 12, queue order: 34 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- - CurrentSimCycle: 2000 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 15, queue order: 32 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 16, queue order: 35 - SST::Action to be delivered at time: 2001, priority: 0, order tag: 0, queue order: 36 - SyncManager to be delivered at 3000 with priority 25 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 5, queue order: 43 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 39 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 40 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 41 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 10, queue order: 42 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 13, queue order: 38 - N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 3000, priority: 50, order tag: 14, queue order: 44 - StopAction to be delivered at 10000000 - StopAction to be delivered at 18446744073709551615 ----- Components: ---- diff --git a/tests/refFiles/test_DebugConsole_serial0.out b/tests/refFiles/test_DebugConsole_serial0.out index ce1b19661..408aa5d7f 100644 --- a/tests/refFiles/test_DebugConsole_serial0.out +++ b/tests/refFiles/test_DebugConsole_serial0.out @@ -1,6 +1,6 @@ ---- Rank0:Thread0: Entering interactive mode at time 0 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_serial0.cmd +> replay cmd_DebugConsole_serial0.cmd > confirm false > run 1ps @@ -12,10 +12,10 @@ Ran clock for 1 sim cycles Added watchpoint #0 > run ---- Rank0:Thread0: Entering interactive mode at time 1000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 1 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 1 : ALL : /component0/message_count_ CHANGED : interactive > unwatch 0 > cd .. > # 1 trace printStatus @@ -23,7 +23,7 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps CurrentSimCycle: 1000 N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 1000, priority: 50, order tag: 10, queue order: 17 @@ -305,7 +305,7 @@ WP 1 - component2/message_count_ Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus > unwatch 1 > # 2 trace printTrace > cd .. @@ -313,13 +313,13 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #2 > setHandler 2 ae -WP 2 - component5/message_count_ +WP 2 - /component5/message_count_ CHANGED > run 1000ps ---- Rank0:Thread0: Entering interactive mode at time 2001 Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: -2: TriggerCount 4 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +2: TriggerCount 4 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace > unwatch 2 > # 3 trace set > cd .. @@ -327,15 +327,15 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #3 > setHandler 3 ae -WP 3 - component6/message_count_ +WP 3 - /component6/message_count_ CHANGED > run 1000ps -LastTriggerRecord:@cycle3000: SamplesLost=0: component6/message_count_=13 +LastTriggerRecord:@cycle3000: SamplesLost=0: message_count_ = 13 set component6/my_id_ 50 ---- Rank0:Thread0: Entering interactive mode at time 3001 Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: -3: TriggerCount 3 : AE : component6/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component6/message_count_ : set component6/my_id_ 50 +3: TriggerCount 3 : AE : /component6/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component6/my_id_ 50 > #print my_id_ > unwatch 3 > # 4 trace interactive @@ -344,13 +344,13 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #4 > setHandler 4 ae -WP 4 - component10/message_count_ +WP 4 - /component10/message_count_ CHANGED > run ---- Rank0:Thread0: Entering interactive mode at time 4000 - Last Trigger: WP4: AE : component10/message_count_ ... + Last Trigger: WP4: AE : /component10/message_count_ CHANGED ... > wl R0,T0: Current watch points: -4: TriggerCount 3 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +4: TriggerCount 3 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive > unwatch 4 > # 5 trace shutdown > cd .. @@ -358,7 +358,7 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : shutdown Added watchpoint #5 > run -LastTriggerRecord:@cycle4000: SamplesLost=0: component12/message_count_=14 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 14 Trigger action shutting down simulation wp simulation shutdown 15 received 16 messages diff --git a/tests/refFiles/test_DebugConsole_serial1.out b/tests/refFiles/test_DebugConsole_serial1.out index 1bd2556d8..75c3de085 100644 --- a/tests/refFiles/test_DebugConsole_serial1.out +++ b/tests/refFiles/test_DebugConsole_serial1.out @@ -1,6 +1,6 @@ ---- Rank0:Thread0: Entering interactive mode at time 1 Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_serial1.cmd +> replay cmd_DebugConsole_serial1.cmd > confirm false > # 0 watch @@ -9,10 +9,10 @@ Interactive start at 1 Added watchpoint #0 > run ---- Rank0:Thread0: Entering interactive mode at time 1000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 1 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 1 : ALL : /component0/message_count_ CHANGED : interactive > unwatch 0 > cd .. > # 1 trace printStatus @@ -20,7 +20,7 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps CurrentSimCycle: 1000 N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 1000, priority: 50, order tag: 10, queue order: 17 @@ -302,7 +302,7 @@ WP 1 - component2/message_count_ Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus > unwatch 1 > # 2 trace printTrace > cd .. @@ -310,13 +310,13 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 4 : message_count_ : printTrace Added watchpoint #2 > setHandler 2 ae -WP 2 - component5/message_count_ +WP 2 - /component5/message_count_ CHANGED > run 1000ps ---- Rank0:Thread0: Entering interactive mode at time 2001 Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: -2: TriggerCount 4 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : component5/message_count_ : printTrace +2: TriggerCount 4 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 4 : message_count_ : printTrace > unwatch 2 > # 3 trace set > cd .. @@ -324,15 +324,15 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #3 > setHandler 3 ae -WP 3 - component6/message_count_ +WP 3 - /component6/message_count_ CHANGED > run 1000ps -LastTriggerRecord:@cycle3000: SamplesLost=0: component6/message_count_=13 +LastTriggerRecord:@cycle3000: SamplesLost=0: message_count_ = 13 set component6/my_id_ 50 ---- Rank0:Thread0: Entering interactive mode at time 3001 Ran clock for 1000 sim cycles > wl R0,T0: Current watch points: -3: TriggerCount 3 : AE : component6/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component6/message_count_ : set component6/my_id_ 50 +3: TriggerCount 3 : AE : /component6/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component6/my_id_ 50 > #print my_id_ > unwatch 3 > # 4 trace interactive @@ -341,13 +341,13 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #4 > setHandler 4 ae -WP 4 - component10/message_count_ +WP 4 - /component10/message_count_ CHANGED > run ---- Rank0:Thread0: Entering interactive mode at time 4000 - Last Trigger: WP4: AE : component10/message_count_ ... + Last Trigger: WP4: AE : /component10/message_count_ CHANGED ... > wl R0,T0: Current watch points: -4: TriggerCount 3 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +4: TriggerCount 3 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive > unwatch 4 > # 5 trace shutdown > cd .. @@ -355,7 +355,7 @@ R0,T0: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : shutdown Added watchpoint #5 > run -LastTriggerRecord:@cycle4000: SamplesLost=0: component12/message_count_=14 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 14 Trigger action shutting down simulation wp simulation shutdown 15 received 16 messages diff --git a/tests/refFiles/test_DebugConsole_thread0.out b/tests/refFiles/test_DebugConsole_thread0.out index ed79fee88..d2fe0fad9 100644 --- a/tests/refFiles/test_DebugConsole_thread0.out +++ b/tests/refFiles/test_DebugConsole_thread0.out @@ -30,7 +30,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 0 Interactive start at 0 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_thread0.cmd +> replay cmd_DebugConsole_thread0.cmd > # Requires 4 threads > confirm false @@ -103,10 +103,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 4 : ALL : /component0/message_count_ CHANGED : interactive R0,T1: Current watch points: R0,T2: Current watch points: R0,T3: Current watch points: @@ -117,7 +117,7 @@ R0,T3: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps CurrentSimCycle: 2000 N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 9, queue order: 27 @@ -253,7 +253,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R0,T1: Current watch points: R0,T2: Current watch points: R0,T3: Current watch points: @@ -267,16 +267,16 @@ Interactive start at 0 > trace message_count_ changed : 16 5 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=6 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=14 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 -buf[5] AE @4000 (+) component5/message_count_=14 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 14 +buf[0] AE @3000 (!) message_count_ = 9 +buf[1] AE @3000 (+) message_count_ = 10 +buf[2] AE @3000 (+) message_count_ = 11 +buf[3] AE @4000 (+) message_count_ = 12 +buf[4] AE @4000 (+) message_count_ = 13 +buf[5] AE @4000 (+) message_count_ = 14 INTERACTIVE CONSOLE -- Rank:0/1 Thread:0/4 (Triggered) @@ -312,7 +312,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R0,T1: Current watch points: -0: TriggerCount 6 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 5 : component5/message_count_ : printTrace +0: TriggerCount 6 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 5 : message_count_ : printTrace R0,T2: Current watch points: R0,T3: Current watch points: > unwatch 0 @@ -324,9 +324,9 @@ Interactive start at 0 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 21 set component8/my_id_ 50 INTERACTIVE CONSOLE @@ -364,7 +364,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R0,T2: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R0,T3: Current watch points: > #print my_id_ > unwatch 0 @@ -374,7 +374,7 @@ R0,T3: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -412,7 +412,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R0,T2: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 9 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R0,T3: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -424,26 +424,26 @@ Interactive start at 0 > trace message_count_ changed : 16 2 : message_count_ : shutdown Added watchpoint #0 > run -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 Trigger action shutting down simulation wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 Trigger action shutting down simulation wp simulation shutdown -7 received 25 messages 11 received 34 messages +15 received 28 messages 10 received 40 messages 9 received 39 messages -15 received 28 messages 50 received 31 messages -14 received 35 messages 3 received 28 messages 2 received 38 messages 1 received 29 messages 0 received 32 messages -13 received 34 messages -12 received 32 messages +7 received 25 messages 6 received 31 messages 5 received 28 messages 4 received 28 messages +14 received 35 messages +13 received 34 messages +12 received 32 messages Simulation is complete, simulated time: 0 s diff --git a/tests/refFiles/test_DebugConsole_thread1.out b/tests/refFiles/test_DebugConsole_thread1.out index 5e2eb5ed7..0f72920b8 100644 --- a/tests/refFiles/test_DebugConsole_thread1.out +++ b/tests/refFiles/test_DebugConsole_thread1.out @@ -30,7 +30,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 1000 Interactive start at 1 -> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_thread1.cmd +> replay cmd_DebugConsole_thread1.cmd > # Requires 4 threads > confirm false @@ -70,10 +70,10 @@ component14/ (SST::CoreTest::MessageMesh::EnclosingComponent) component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) ---- Rank0:Thread0: Entering interactive mode at time 2000 - Last Trigger: WP0: AE : component0/message_count_ ... + Last Trigger: WP0: AE : /component0/message_count_ CHANGED ... > wl R0,T0: Current watch points: -0: TriggerCount 4 : ALL : component0/message_count_ CHANGED : interactive +0: TriggerCount 4 : ALL : /component0/message_count_ CHANGED : interactive R0,T1: Current watch points: R0,T2: Current watch points: R0,T3: Current watch points: @@ -84,7 +84,7 @@ R0,T3: Current watch points: > trace message_count_ changed : 16 0 : message_count_ : printStatus Added watchpoint #1 > setHandler 1 ae -WP 1 - component2/message_count_ +WP 1 - /component2/message_count_ CHANGED > run 1ps CurrentSimCycle: 2000 N3SST8CoreTest11MessageMesh12MessageEventE to be delivered at time: 2000, priority: 50, order tag: 9, queue order: 27 @@ -220,7 +220,7 @@ component15/ (SST::CoreTest::MessageMesh::EnclosingComponent) Ran clock for 1 sim cycles > wl R0,T0: Current watch points: -1: TriggerCount 1 : AE : component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : component2/message_count_ : printStatus +1: TriggerCount 1 : AE : /component2/message_count_ CHANGED : bufsize = 16 postDelay = 0 : message_count_ : printStatus R0,T1: Current watch points: R0,T2: Current watch points: R0,T3: Current watch points: @@ -234,16 +234,16 @@ Interactive start at 1 > trace message_count_ changed : 16 5 : message_count_ : printTrace Added watchpoint #0 > setHandler 0 ae -WP 0 - component5/message_count_ +WP 0 - /component5/message_count_ CHANGED > run 2000ps TriggerCount=6 -LastTriggerRecord:@cycle4000: SamplesLost=0: component5/message_count_=14 -buf[0] AE @3000 (!) component5/message_count_=9 -buf[1] AE @3000 (+) component5/message_count_=10 -buf[2] AE @3000 (+) component5/message_count_=11 -buf[3] AE @4000 (+) component5/message_count_=12 -buf[4] AE @4000 (+) component5/message_count_=13 -buf[5] AE @4000 (+) component5/message_count_=14 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 14 +buf[0] AE @3000 (!) message_count_ = 9 +buf[1] AE @3000 (+) message_count_ = 10 +buf[2] AE @3000 (+) message_count_ = 11 +buf[3] AE @4000 (+) message_count_ = 12 +buf[4] AE @4000 (+) message_count_ = 13 +buf[5] AE @4000 (+) message_count_ = 14 INTERACTIVE CONSOLE -- Rank:0/1 Thread:0/4 (Triggered) @@ -279,7 +279,7 @@ Ran clock for 2000 sim cycles > wl R0,T0: Current watch points: R0,T1: Current watch points: -0: TriggerCount 6 : AE : component5/message_count_ CHANGED : bufsize = 16 postDelay = 5 : component5/message_count_ : printTrace +0: TriggerCount 6 : AE : /component5/message_count_ CHANGED : bufsize = 16 postDelay = 5 : message_count_ : printTrace R0,T2: Current watch points: R0,T3: Current watch points: > unwatch 0 @@ -291,9 +291,9 @@ Interactive start at 1 > trace message_count_ changed : 16 2 : message_count_ : set my_id_ 50 Added watchpoint #0 > setHandler 0 ae -WP 0 - component8/message_count_ +WP 0 - /component8/message_count_ CHANGED > run 1000ps -LastTriggerRecord:@cycle5000: SamplesLost=0: component8/message_count_=21 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 21 set component8/my_id_ 50 INTERACTIVE CONSOLE @@ -331,7 +331,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R0,T2: Current watch points: -0: TriggerCount 3 : AE : component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component8/message_count_ : set component8/my_id_ 50 +0: TriggerCount 3 : AE : /component8/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : set component8/my_id_ 50 R0,T3: Current watch points: > #print my_id_ > unwatch 0 @@ -341,7 +341,7 @@ R0,T3: Current watch points: > trace message_count_ changed : 16 2 : message_count_ : interactive Added watchpoint #1 > setHandler 1 ae -WP 1 - component10/message_count_ +WP 1 - /component10/message_count_ CHANGED > run INTERACTIVE CONSOLE @@ -379,7 +379,7 @@ Ran clock for 1000 sim cycles R0,T0: Current watch points: R0,T1: Current watch points: R0,T2: Current watch points: -1: TriggerCount 9 : AE : component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : component10/message_count_ : interactive +1: TriggerCount 9 : AE : /component10/message_count_ CHANGED : bufsize = 16 postDelay = 2 : message_count_ : interactive R0,T3: Current watch points: > unwatch 1 > # 5 trace shutdown @@ -391,26 +391,26 @@ Interactive start at 1 > trace message_count_ changed : 16 2 : message_count_ : shutdown Added watchpoint #0 > run -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=29 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 29 Trigger action shutting down simulation wp simulation shutdown -LastTriggerRecord:@cycle8000: SamplesLost=0: component12/message_count_=31 +LastTriggerRecord:@cycle8000: SamplesLost=0: message_count_ = 31 Trigger action shutting down simulation wp simulation shutdown -7 received 25 messages 11 received 34 messages +7 received 25 messages 15 received 28 messages 10 received 40 messages -6 received 31 messages +14 received 35 messages 9 received 39 messages +6 received 31 messages 50 received 31 messages +13 received 34 messages 5 received 28 messages 4 received 28 messages 3 received 28 messages -14 received 35 messages +12 received 32 messages 2 received 38 messages 1 received 29 messages 0 received 32 messages -13 received 34 messages -12 received 32 messages Simulation is complete, simulated time: 0 s diff --git a/tests/refFiles/test_DebugConsole_tracebuf.out b/tests/refFiles/test_DebugConsole_tracebuf.out new file mode 100644 index 000000000..cfbe405f1 --- /dev/null +++ b/tests/refFiles/test_DebugConsole_tracebuf.out @@ -0,0 +1,129 @@ +---- Rank0:Thread0: Entering interactive mode at time 0 +Interactive start at 0 +> replay /home/skuntz/sanity/sst-core/tests/cmd_DebugConsole_tracebuf.cmd + +> confirm false +> cd component2 +> ls -l +component_state_ = 3 (SST::BaseComponent::ComponentState) +message_count_ = 0 (int) +my_id_ = 2 (int) +my_info_/ +defaultTimeBase (ro) = 0 s +id (ro) = 2 +type (ro) = "coreTestElement.message_mesh.enclosing_component" +ports_ [4 elements] (std::vector >) +0/ +component_state_ +functor_/ +links_ [0 elements] (std::vector >) +my_info_/ +1/ +component_state_ +functor_/ +links_ [0 elements] (std::vector >) +my_info_/ +2/ +component_state_ +my_info_/ +port/ +port_/ +3/ +component_state_ +my_info_/ +port/ +port_/ +stats_ [0 elements] (std::vector*, std::allocator*> >) +verbose_ = true (bool) +component2:ports[0]/ +component2:ports[1]/ +component2:ports[2]/ +component2:ports[3]/ +component2:route/ +> trace message_count_ changed : 32 4 : message_count_ : printTrace +Added watchpoint #0 +> sethandler 0 ae ac +WP 0 - /component2/message_count_ CHANGED +> printwatchpoint 0 +WP0: TriggerCount 0 : AC AE : /component2/message_count_ CHANGED : bufsize = 32 postDelay = 4 : message_count_ : printTrace +> printtrace 0 +TriggerCount=0 +No trace samples in current buffer +> run 3000ps +TriggerCount=5 +LastTriggerRecord:@cycle2000: SamplesLost=0: message_count_ = 5 +buf[0] AE @1000 (!) message_count_ = 1 +buf[1] AE @1000 (+) message_count_ = 2 +buf[2] AE @1000 (+) message_count_ = 3 +buf[3] AE @1000 (+) message_count_ = 4 +buf[4] AE @2000 (+) message_count_ = 5 +TriggerCount=5 +LastTriggerRecord:@cycle2000: SamplesLost=0: message_count_ = 10 +buf[0] AE @2000 (!) message_count_ = 6 +buf[1] AE @2000 (+) message_count_ = 7 +buf[2] AE @2000 (+) message_count_ = 8 +buf[3] AE @2000 (+) message_count_ = 9 +buf[4] AE @2000 (+) message_count_ = 10 +---- Rank0:Thread0: Entering interactive mode at time 3000 +Ran clock for 3000 sim cycles +> wl +R0,T0: Current watch points: +0: TriggerCount 5 : AC AE : /component2/message_count_ CHANGED : bufsize = 32 postDelay = 4 : message_count_ : printTrace +> print message_count_ +message_count_ = 10 +> printwatchpoint 0 +WP0: TriggerCount 5 : AC AE : /component2/message_count_ CHANGED : bufsize = 32 postDelay = 4 : message_count_ : printTrace +> printtrace 0 +TriggerCount=5 +No trace samples in current buffer +> run 3000ps +TriggerCount=5 +LastTriggerRecord:@cycle4000: SamplesLost=0: message_count_ = 15 +buf[0] AE @3000 (!) message_count_ = 11 +buf[1] AE @3000 (+) message_count_ = 12 +buf[2] AE @3000 (+) message_count_ = 13 +buf[3] AE @3000 (+) message_count_ = 14 +buf[4] AE @4000 (+) message_count_ = 15 +TriggerCount=5 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 20 +buf[0] AE @4000 (!) message_count_ = 16 +buf[1] AE @4000 (+) message_count_ = 17 +buf[2] AE @5000 (+) message_count_ = 18 +buf[3] AE @5000 (+) message_count_ = 19 +buf[4] AE @5000 (+) message_count_ = 20 +---- Rank0:Thread0: Entering interactive mode at time 6000 +Ran clock for 3000 sim cycles +> wl +R0,T0: Current watch points: +0: TriggerCount 4 : AC AE : /component2/message_count_ CHANGED : bufsize = 32 postDelay = 4 : message_count_ : printTrace +> print message_count_ +message_count_ = 24 +> printwatchpoint 0 +WP0: TriggerCount 4 : AC AE : /component2/message_count_ CHANGED : bufsize = 32 postDelay = 4 : message_count_ : printTrace +> printtrace 0 +TriggerCount=4 +LastTriggerRecord:@cycle5000: SamplesLost=0: message_count_ = 24 +buf[0] AE @5000 (!) message_count_ = 21 +buf[1] AE @5000 (+) message_count_ = 22 +buf[2] AE @5000 (+) message_count_ = 23 +buf[3] AE @5000 (+) message_count_ = 24 +> shutd +Simulation shutdown +R0, T0: Exiting ObjectExplorer and shutting down simulation +15 received 23 messages +14 received 26 messages +13 received 19 messages +0 received 19 messages +1 received 18 messages +2 received 24 messages +3 received 17 messages +4 received 20 messages +5 received 16 messages +6 received 20 messages +7 received 12 messages +8 received 21 messages +9 received 19 messages +10 received 26 messages +11 received 23 messages +12 received 17 messages +Simulation is complete, simulated time: 0 s diff --git a/tests/testsuite_default_DebugConsole.py b/tests/testsuite_default_DebugConsole.py index 397e53980..c96aaf8ed 100644 --- a/tests/testsuite_default_DebugConsole.py +++ b/tests/testsuite_default_DebugConsole.py @@ -32,6 +32,7 @@ def tearDown(self): parallelism = testing_check_get_num_ranks() * testing_check_get_num_threads() + # Test interactive start and watch/trace actions # Serial #@unittest.skipIf(parallelism > 16, "Test does not support greater than 16-way parallelism") @unittest.skipIf(testing_check_get_num_ranks() > 1, "Test only supports serial execution") @@ -97,6 +98,13 @@ def test_rankparallel0(self): def test_rankparallel1(self): self.debugconsole_test_template("rankparallel1", "1ps") + # Test trace buffer output + #@unittest.skipIf(parallelism > 16, "Test does not support greater than 16-way parallelism") + @unittest.skipIf(testing_check_get_num_ranks() > 1, "Test only supports serial execution") + @unittest.skipIf(testing_check_get_num_threads() > 1, "Test only supports serial execution") + def test_tracebuf(self): + self.debugconsole_test_template("tracebuf", "0") + ##### def debugconsole_test_template(self, testtype, starttime): @@ -121,10 +129,14 @@ def debugconsole_test_template(self, testtype, starttime): # Filter out printstatus queue order due to differences across architectures filter2 = LineFilter(); filter2 = RemoveRegexFromLineFilter(r"queue order:.*") + # Filter out variable types due to differences across architectures + filter3 = LineFilter(); + filter3 = RemoveRegexFromLineFilter(r"std::.*") + # Perform the test comparison with refFile #cmp_result = testing_compare_sorted_diff(testtype, outfile, reffile) - cmp_result = testing_compare_filtered_diff(testtype, outfile, reffile, sort=True, filters=[filter1, filter2]) + cmp_result = testing_compare_filtered_diff(testtype, outfile, reffile, sort=True, filters=[filter1, filter2, filter3]) if not cmp_result: diffdata = testing_get_diff_data(testtype) log_failure(diffdata)