The Sparta Modeling Framework
Loading...
Searching...
No Matches
RootTreeNode.hpp
Go to the documentation of this file.
1// <RootTreeNode> -*- C++ -*-
2
8#pragma once
9
10#include <memory>
11#include <ostream>
12#include <string>
13#include <vector>
14
16#include "sparta/simulation/TreeNodeExtensions.hpp"
19#include "sparta/log/NotificationSource.hpp"
20#include "sparta/simulation/TreeNodePrivateAttorney.hpp"
21#include "sparta/simulation/ParameterTree.hpp"
26
27namespace sparta
28{
29 class ArchData;
30 class Clock;
31
32 namespace app {
33 class Simulation;
34 }
35
36 namespace python {
37 class PythonInterpreter;
38 }
39
53 class RootTreeNode : public TreeNode
54 {
55 public:
56
62
79 RootTreeNode(const std::string & name,
80 const std::string & desc,
81 app::Simulation* sim,
82 GlobalTreeNode* search_scope) :
84 sim_(sim),
85 new_node_noti_(this,
86 "descendant_attached",
87 "Notification immediately after a node becomes a descendant of this "
88 "root at any distance. This new node may have children already attached "
89 "which will not receive their own descendant_attached notification",
90 "descendant_attached")
91 {
92 if(search_scope != nullptr){
93 search_node_ = search_scope;
94 }else{
95 search_node_ = new GlobalTreeNode();
96 alloc_search_node_.reset(search_node_);
97 }
98 search_node_->addChild(this);
99
100 /* Define the default scope that all tree nodes will be in. This is
101 * to ensure that getScopeRoot() never returns nullptr event when no
102 * scope is explicitly defined. */
103 setScopeRoot();
104 }
105
109 RootTreeNode(const std::string & name,
110 const std::string & desc,
111 GlobalTreeNode* search_scope) :
112 RootTreeNode(name, desc, nullptr, search_scope)
113 {
114 // Delegated construction
115 }
116
120 RootTreeNode(const std::string & name) :
121 RootTreeNode(name, "Top of device tree", nullptr, nullptr)
122 {
123 // Delegated construction
124 }
125
129 RootTreeNode(const std::string & name,
130 const std::string & desc,
131 app::Simulation* sim) :
132 RootTreeNode(name, desc, sim, nullptr)
133 {
134 // Delegated construction
135 }
136
141 RootTreeNode(const std::string & name,
142 const std::string & desc) :
143 RootTreeNode(name, desc, nullptr, nullptr)
144 {
145 // Delegated construction
146 }
147
152 RootTreeNode("top", "Top of device tree", sim, nullptr)
153 {
154 // Delegated construction
155 }
156
161 RootTreeNode("top", "Top of device tree", nullptr, search_scope)
162 {
163 // Delegated construction
164 }
165
170 RootTreeNode("top", "Top of device tree", sim, search_scope)
171 {
172 // Delegated construction
173 }
174
179 RootTreeNode("top", "Top of device tree", nullptr, nullptr)
180 {
181 // Delegated construction
182 }
183
191 virtual ~RootTreeNode() {
192 // Inform Search Scope node since it will not be notified by
193 // ~TreeNode, which does not recognize the search scope as a parent
194 if(search_node_){
195 removeFromParentForTeardown_(search_node_);
196 }
197
198 // No need to alert children, because ~TreeNode will do this next
199 }
200
201 // Returns true. Tree root is always considered "attached"
202 virtual bool isAttached() const override final {
203 return true;
204 }
205
206 // Returns 0. Tree root will never have a parent
207 virtual TreeNode* getParent() override final { return nullptr; }
208
209 // Returns 0. Tree root will never have a parent
210 virtual const TreeNode* getParent() const override final { return nullptr; }
211
212 // Override TreeNode::setClock() so we can pass that clock to the search scope
213 virtual void setClock(const Clock * clk) override final {
214 if (search_node_) {
215 search_node_->setClock(clk);
216 }
218 }
219
224 return sim_;
225 }
226
234 sparta_assert(search_node_);
235 return search_node_;
236 }
237
247 if(getPhase() != TREE_BUILDING){
248 throw SpartaException("Device tree with root \"")
249 << getLocation()<< "\" not currently in the TREE_BUILDING phase, so it cannot "
250 "enter TREE_CONFIGURING";
251 }
252
253 enterConfig_(); // Enter the next phase (cannot throw)
254 }
255
271 void enterFinalized(sparta::python::PythonInterpreter* pyshell = nullptr);
272
289 if(getPhase() != TREE_FINALIZED){
290 throw SpartaException("Device tree with root \"")
291 << getLocation()
292 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeEarly)";
293 }
294
296 }
297
309 if(getPhase() != TREE_FINALIZED){
310 throw SpartaException("Device tree with root \"")
311 << getLocation()
312 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeLate)";
313 }
314
316 }
317
332
340 if(getPhase() != TREE_FINALIZED){
341 throw SpartaException("Device tree with root \"")
342 << getLocation()
343 << "\" not in the TREE_FINALIZED phase, so it cannot be pre-run validated";
344 }
345
346 validateTree_(); // Validate all nodes, which may throw
347 }
348
349
357
368 void dumpDebugContent(std::ostream& out) noexcept {
370 }
371
383 enterTeardown_(); // Enter the next phase
384 }
385
393 virtual std::string stringize(bool pretty=false) const override {
394 (void) pretty;
395 std::stringstream ss;
396 ss << "<" << getLocation() << " (root)>";
397 return ss.str();
398 }
399
403
416 return new_node_noti_;
417 }
418
421
426
438 void getArchDataAssociations(std::vector<const ArchData*>& ad_this_tree,
439 std::vector<const ArchData*>& ad_no_assoc,
440 std::vector<const ArchData*>& ad_not_attached,
441 std::vector<const ArchData*>& ad_other_tree) const noexcept;
442
454
465 void dumpArchDataAssociations(std::ostream& o) const noexcept;
466
470 void dumpTypeMix(std::ostream& o) const;
471
475 template <typename ExtensionT>
477 static_assert(std::is_base_of<ExtensionsBase, ExtensionT>::value);
478 extensionFactories_()[ExtensionT::NAME] = []() { return new ExtensionT; };
479 }
480
484 static void registerExtensionFactory(const std::string & extension_name,
485 std::function<ExtensionsBase*()> factory)
486 {
487 extensionFactories_()[extension_name] = factory;
488 }
489
494 static std::function<ExtensionsBase*()> & getExtensionFactory(const std::string & extension_name)
495 {
496 auto it = extensionFactories_().find(extension_name);
497 if (it != extensionFactories_().end()) {
498 return it->second;
499 }
500
501 static std::function<ExtensionsBase*()> none;
502 return none;
503 }
504
510 return extensions_ptree_;
511 }
512
519 return extensions_ptree_;
520 }
521
528 void addExtensions(const std::string & yaml_file,
529 const std::vector<std::string> & config_search_paths = {},
530 const bool verbose_cfg = false)
531 {
532 app::NodeConfigFileApplicator applicator("", yaml_file, config_search_paths);
533
534 ParameterTree ptree;
535 applicator.applyUnbound(ptree, verbose_cfg);
536
537 // Store the extensions in the std::any map owned by the ParameterTree::Node's
538 extensions_ptree_.merge(ptree);
539 if (verbose_cfg) {
540 std::cout << "After merging extension file '" << yaml_file << "', parameter tree contains:\n";
541 constexpr bool print_user_data = false; // Already printed from "extension" nodes
542 extensions_ptree_.recursePrint(std::cout, print_user_data);
543 }
544 }
545
548
549 private:
550
555 static std::map<std::string, std::function<ExtensionsBase*()>> & extensionFactories_() {
556 static std::map<std::string, std::function<ExtensionsBase*()>> factories;
557 return factories;
558 }
559
561 ParameterTree extensions_ptree_;
562
563 // No effect on root
564 virtual void createResource_() override {};
565
575 virtual void onSettingParent_(const TreeNode* parent) const override final {
576 if(parent != search_node_){
577 throw SpartaException("This RootTreeNode \"")
578 << "\" cannot be a child of any other node except its constructed "
579 "GlobalTreeNode";
580 }
581 }
582
591 virtual void setParent_(TreeNode* parent, bool) override final {
592 if(parent != search_node_){
593 throw SpartaCriticalError("This RootTreeNode \"")
594 << "\" cannot be a child of any other node except its constructed "
595 "GlobalTreeNode";
596 }
597
598 // NOTE: Do not store parent because the root should act as if there is no parent
599 }
600
601 virtual void onDescendentSubtreeAdded_(TreeNode* des) noexcept override final {
602 // Broadcast notification for self coming into existence
603 try{
604 new_node_noti_.postNotification(*des);
605
606 // Iterate subtree headed by des and notify observers of these
608 onDescendentSubtreeAdded_(child);
609 }
610 }catch(SpartaException& ex){
611 std::stringstream msg;
612 msg << ex.what() <<
613 "\nThis exception within onDescendentSubtreeAdded_, which is not exception-"
614 "safe. The integrity of this sparta tree (" << getRoot() << ") is compromised. "
615 "Aborting. ";
616 sparta_abort(false,msg.str());
617 }
618 }
619
624 std::unique_ptr<GlobalTreeNode> alloc_search_node_;
625
630 GlobalTreeNode* search_node_;
631
635 app::Simulation* sim_;
636
641 NewDescendantNotiSrc new_node_noti_;
642 };
643
644 template <typename ExtensionT>
653
654} // namespace sparta
655
656#define SPARTA_CONCATENATE_DETAIL(x, y) x##y
657#define SPARTA_CONCATENATE(x, y) SPARTA_CONCATENATE_DETAIL(x, y)
658
659#define REGISTER_TREE_NODE_EXTENSION(ExtensionClass) \
660 sparta::ExtensionRegistration<ExtensionClass> SPARTA_CONCATENATE(__extension_registration_, __COUNTER__)
Configuration Applicators.
TreeNode refinement representing the global namespace (above "top") of a device tree.
A set of sparta::Parameters per sparta::ResourceTreeNode.
Basic Node framework in sparta device tree composite pattern.
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_abort(...)
Simple variatic assertion that will print a message to std::cerr and call std::terminate()
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Basic Node framework in sparta device tree composite pattern.
A representation of simulated time.
Definition Clock.hpp:44
TreeNode which represents some "global" namespace of the device tree, containing only RootTreeNodes,...
A TreeNode that generates a specific type of notification which propagates up a tree of TreeNodes (us...
void postNotification(const NotificationDataT &data) const
Post with reference to data with parent as message origin.
Virtual Parameter Tree. This represents a tree of parameters read from some source but does not neces...
void recursePrint(std::ostream &o, bool print_user_data=true) const
Recursively print.
void merge(const ParameterTree &rhp)
Merge this tree with another by applying all of its parameters to this tree. Parameters in the right ...
TreePhase getPhase() const
Gets the trees current phase.
@ TREE_BUILDING
Setting up tree hierarchy only (initial state)
@ TREE_FINALIZED
Tree and all resources have been instantiated. No more configuration/connection allowed.
TreeNode which represents the root ("top") of a device tree.
RootTreeNode(app::Simulation *sim, GlobalTreeNode *search_scope)
Constructor with only a simulator and search scope.
app::Simulation * getSimulator() const
Gets the simulator (if any) associated with this Root node.
void simulationTerminating()
Called after simulation has stopped, but before statistic/report generation.
static std::function< ExtensionsBase *()> & getExtensionFactory(const std::string &extension_name)
Get a tree node extension factory, if available. Check "operator bool()" before using.
RootTreeNode(const std::string &name)
Constructor with name only.
void dumpArchDataAssociations(std::ostream &o) const noexcept
Debugging tool which checks all ArchDatas in existence to see if they are associated with this tree....
RootTreeNode(GlobalTreeNode *search_scope)
Constructor with only a search scope.
static void registerExtensionFactory(const std::string &extension_name, std::function< ExtensionsBase *()> factory)
Register a tree node extension factory.
RootTreeNode(const std::string &name, const std::string &desc, app::Simulation *sim)
Consturctor with name, desc, and simulator.
static void registerExtensionClass()
Register a tree node extension factory.
virtual ~RootTreeNode()
Destructor.
NotificationSource< TreeNode > NewDescendantNotiSrc
Type for notification source in this node which is posted when a new descendent is attached.
RootTreeNode()
Default constuctor.
RootTreeNode(app::Simulation *sim)
Constructor with only a simulator.
void bindTreeEarly()
Public method for recursively giving all resources and nodes a chance to bind ports locally....
virtual std::string stringize(bool pretty=false) const override
Render description of this RootTreeNode as a string.
GlobalTreeNode * getSearchScope()
Gets the search node "parent" of this root node which is suitable for performing searches that includ...
void addExtensions(const std::string &yaml_file, const std::vector< std::string > &config_search_paths={}, const bool verbose_cfg=false)
Add tree node extension(s) from the given YAML file. This method simply adds the extension informatio...
void dumpTypeMix(std::ostream &o) const
Dumps the mix of tree node concrete types to the ostream.
void enterConfiguring()
Public method to crystalize the tree structure and begin configuring.
const ParameterTree & getExtensionsUnboundParameterTree() const
Returns a ParameterTree (const version) containing an unbound set of named tree node extensions and t...
void bindTreeLate()
Public method for recursively giving all resources and nodes a chance to bind ports locally....
void validatePreRun()
Validate the entire tree immediately prior to running. All ports should be bound ,...
void enterTeardown()
Places this tree into TREE_TEARDOWN phase so that nodes may be deleted without errors.
void dumpDebugContent(std::ostream &out) noexcept
Dump all debug content from each resource in the tree to an ostream.
void validatePostRun()
Validate all resources in the simulator, throwing exceptions if invalid state is detected....
virtual bool isAttached() const override final
Is this node part of a device tree with a proper RootTreeNode at the root.
void enterFinalized(sparta::python::PythonInterpreter *pyshell=nullptr)
Public method for recursive tree finalization. Places tree temporarily into TREE_FINALIZING phase bef...
RootTreeNode(const std::string &name, const std::string &desc, GlobalTreeNode *search_scope)
Constructor with name, desc, and search scope.
void validateArchDataAssociations() const
Gets the results.
void getArchDataAssociations(std::vector< const ArchData * > &ad_this_tree, std::vector< const ArchData * > &ad_no_assoc, std::vector< const ArchData * > &ad_not_attached, std::vector< const ArchData * > &ad_other_tree) const noexcept
Gets vectors of all the ArchData instances in existance now categorized into several groups....
RootTreeNode(const std::string &name, const std::string &desc, app::Simulation *sim, GlobalTreeNode *search_scope)
Constructor.
virtual TreeNode * getParent() override final
Gets immediate parent of this node if one exists.
NewDescendantNotiSrc & getNodeAttachedNotification()
Returns the post-write notification-source node for this register which can be used to observe writes...
ParameterTree & getExtensionsUnboundParameterTree()
Returns a ParameterTree containing an unbound set of named tree node extensions and their parameter v...
RootTreeNode(const std::string &name, const std::string &desc)
Constructor with name and desc.
virtual void setClock(const Clock *clk) override final
Assigns a clock to this node. This clock will then be accessed by any descendant which has no assigne...
Used to construct and throw a standard C++ exception. Inherits from std::exception.
static const TreeNode::ChildrenVector & getAllChildren(const TreeNode &node)
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:204
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
Definition TreeNode.hpp:302
std::string getLocation() const override final
void validateTree_()
Iterates the finalized tree and validates each node (e.g. ensures statistics can be evaluated)
virtual TreeNode * getRoot()
Gets farthest ancestor of this node.
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:313
void simulationTerminating_()
Hook to allow simulation resources to clean-up before simulation is ended.
void enterTeardown_() noexcept
Recursively enter TREE_TEARDOWN phase while alerting nodes through onEnteringTeardown_ and alterting ...
TreeNode()=delete
Not default-constructable.
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
virtual void setClock(const Clock *clk)
Assigns a clock to this node. This clock will then be accessed by any descendant which has no assigne...
void dumpDebugContent_(std::ostream &out) const noexcept
Allows resources to write out detailed textual debugging information about the node....
void enterConfig_() noexcept
Recursively enter TREE_CONFIGURING phase.
void bindTreeLate_()
Recursively invoke TreeNode::onBindTreeEarly_ and Resource::onBindTreeLate_ (in that order for each n...
void bindTreeEarly_()
Recursively invoke TreeNode::onBindTreeEarly_ and Resource::onBindTreeEarly_ (in that order for each ...
void removeFromParentForTeardown_(TreeNode *parent)
Protected Wrapper for getParent()->removeChildForTeardown_ which allows subclases of TreeNode to indi...
Applies a configuration file to a node pattern.
Simulator which builds a sparta DeviceTree.
Macros for handling exponential backoff.