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 class TreeNodeExtensionManager;
32
33 namespace app {
34 class Simulation;
35 }
36
37 namespace python {
38 class PythonInterpreter;
39 }
40
54 class RootTreeNode : public TreeNode
55 {
56 public:
57
63
80 RootTreeNode(const std::string & name,
81 const std::string & desc,
82 app::Simulation* sim,
83 GlobalTreeNode* search_scope) :
85 sim_(sim)
86 {
87 if(search_scope != nullptr){
88 search_node_ = search_scope;
89 }else{
90 search_node_ = new GlobalTreeNode();
91 alloc_search_node_.reset(search_node_);
92 }
93 search_node_->addChild(this);
94
95 /* Define the default scope that all tree nodes will be in. This is
96 * to ensure that getScopeRoot() never returns nullptr event when no
97 * scope is explicitly defined. */
99
100 // Create the notification after the RTN is fully realized
101 new_node_noti_.reset(
102 new NewDescendantNotiSrc(this,
103 "descendant_attached",
104 "Notification immediately after a node becomes a descendant of this "
105 "root at any distance. This new node may have children already attached "
106 "which will not receive their own descendant_attached notification",
107 "descendant_attached"));
108 }
109
113 RootTreeNode(const std::string & name,
114 const std::string & desc,
115 GlobalTreeNode* search_scope) :
116 RootTreeNode(name, desc, nullptr, search_scope)
117 {
118 // Delegated construction
119 }
120
124 RootTreeNode(const std::string & name) :
125 RootTreeNode(name, "Top of device tree", nullptr, nullptr)
126 {
127 // Delegated construction
128 }
129
133 RootTreeNode(const std::string & name,
134 const std::string & desc,
135 app::Simulation* sim) :
136 RootTreeNode(name, desc, sim, nullptr)
137 {
138 // Delegated construction
139 }
140
145 RootTreeNode(const std::string & name,
146 const std::string & desc) :
147 RootTreeNode(name, desc, nullptr, nullptr)
148 {
149 // Delegated construction
150 }
151
156 RootTreeNode("top", "Top of device tree", sim, nullptr)
157 {
158 // Delegated construction
159 }
160
165 RootTreeNode("top", "Top of device tree", nullptr, search_scope)
166 {
167 // Delegated construction
168 }
169
174 RootTreeNode("top", "Top of device tree", sim, search_scope)
175 {
176 // Delegated construction
177 }
178
183 RootTreeNode("top", "Top of device tree", nullptr, nullptr)
184 {
185 // Delegated construction
186 }
187
195 virtual ~RootTreeNode() {
196 // Inform Search Scope node since it will not be notified by
197 // ~TreeNode, which does not recognize the search scope as a parent
198 if(search_node_){
199 removeFromParentForTeardown_(search_node_);
200 }
201
202 // No need to alert children, because ~TreeNode will do this next
203 }
204
205 // Returns true. Tree root is always considered "attached"
206 virtual bool isAttached() const override final {
207 return true;
208 }
209
210 // Returns 0. Tree root will never have a parent
211 virtual TreeNode* getParent() override final { return nullptr; }
212
213 // Returns 0. Tree root will never have a parent
214 virtual const TreeNode* getParent() const override final { return nullptr; }
215
216 // Override TreeNode::setClock() so we can pass that clock to the search scope
217 virtual void setClock(const Clock * clk) override final {
218 if (search_node_) {
219 search_node_->setClock(clk);
220 }
222 }
223
228 return sim_;
229 }
230
238 sparta_assert(search_node_);
239 return search_node_;
240 }
241
251 if(getPhase() != TREE_BUILDING){
252 throw SpartaException("Device tree with root \"")
253 << getLocation()<< "\" not currently in the TREE_BUILDING phase, so it cannot "
254 "enter TREE_CONFIGURING";
255 }
256
257 enterConfig_(); // Enter the next phase (cannot throw)
258 }
259
275 void enterFinalized(sparta::python::PythonInterpreter* pyshell = nullptr);
276
293 if(getPhase() != TREE_FINALIZED){
294 throw SpartaException("Device tree with root \"")
295 << getLocation()
296 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeEarly)";
297 }
298
300 }
301
313 if(getPhase() != TREE_FINALIZED){
314 throw SpartaException("Device tree with root \"")
315 << getLocation()
316 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeLate)";
317 }
318
320 }
321
336
344 if(getPhase() != TREE_FINALIZED){
345 throw SpartaException("Device tree with root \"")
346 << getLocation()
347 << "\" not in the TREE_FINALIZED phase, so it cannot be pre-run validated";
348 }
349
350 validateTree_(); // Validate all nodes, which may throw
351 }
352
353
361
372 void dumpDebugContent(std::ostream& out) noexcept {
374 }
375
387 enterTeardown_(); // Enter the next phase
388 }
389
397 virtual std::string stringize(bool pretty=false) const override {
398 (void) pretty;
399 std::stringstream ss;
400 ss << "<" << getLocation() << " (root)>";
401 return ss.str();
402 }
403
407
420 return *new_node_noti_;
421 }
422
425
430
442 void getArchDataAssociations(std::vector<const ArchData*>& ad_this_tree,
443 std::vector<const ArchData*>& ad_no_assoc,
444 std::vector<const ArchData*>& ad_not_attached,
445 std::vector<const ArchData*>& ad_other_tree) const noexcept;
446
458
469 void dumpArchDataAssociations(std::ostream& o) const noexcept;
470
474 void dumpTypeMix(std::ostream& o) const;
475
482 void setExtensionManager(TreeNodeExtensionManager* mgr);
483
487 const TreeNodeExtensionManager * getExtensionManager(bool must_exist = true) const {
488 if (!extension_mgr_ && must_exist) {
489 throw SpartaException("Expecting TreeNodeExtensionsManager to exist but it doesn't");
490 }
491 return extension_mgr_;
492 }
493
497 TreeNodeExtensionManager * getExtensionManager(bool must_exist = true) {
498 if (!extension_mgr_ && must_exist) {
499 throw SpartaException("Expecting TreeNodeExtensionsManager to exist but it doesn't");
500 }
501 return extension_mgr_;
502 }
503
506
507 private:
508
509 // The TreeNodeExtensionManager object owned by CommandLineSimulator,
510 // a simulation subclass, or in the SimulationConfiguration object
511 // on the stack in a unit test.
512 TreeNodeExtensionManager * extension_mgr_ = nullptr;
513
514 // No effect on root
515 virtual void createResource_() override {};
516
526 virtual void onSettingParent_(const TreeNode* parent) const override final {
527 if(parent != search_node_){
528 throw SpartaException("This RootTreeNode \"")
529 << "\" cannot be a child of any other node except its constructed "
530 "GlobalTreeNode";
531 }
532 }
533
542 virtual void setParent_(TreeNode* parent, bool) override final {
543 if(parent != search_node_){
544 throw SpartaCriticalError("This RootTreeNode \"")
545 << "\" cannot be a child of any other node except its constructed "
546 "GlobalTreeNode";
547 }
548
549 // NOTE: Do not store parent because the root should act as if there is no parent
550 }
551
552 virtual void onDescendentSubtreeAdded_(TreeNode* des) noexcept override final {
553 // Broadcast notification for self coming into existence
554 try{
555 // There's an irony here ... how do you create the new
556 // node notification object without it calling itself
557 // to notify that it's adding itself? Easy -- the
558 // unique pointer isn't fully realized until it's
559 // fully added to the tree node hierarchy.
560 if (SPARTA_EXPECT_TRUE(new_node_noti_)) {
561 new_node_noti_->postNotification(*des);
562 }
563
564 // Iterate subtree headed by des and notify observers of these
566 onDescendentSubtreeAdded_(child);
567 }
568 }catch(SpartaException& ex){
569 std::stringstream msg;
570 msg << ex.what() <<
571 "\nThis exception within onDescendentSubtreeAdded_, which is not exception-"
572 "safe. The integrity of this sparta tree (" << getRoot() << ") is compromised. "
573 "Aborting. ";
574 sparta_abort(false,msg.str());
575 }
576 }
577
582 std::unique_ptr<GlobalTreeNode> alloc_search_node_;
583
588 GlobalTreeNode* search_node_;
589
593 app::Simulation* sim_;
594
599 std::unique_ptr<NewDescendantNotiSrc> new_node_noti_;
600 };
601
602} // namespace sparta
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.
#define SPARTA_EXPECT_TRUE(x)
A macro for hinting to the compiler a particular condition should be considered most likely true.
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...
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.
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.
RootTreeNode(const std::string &name, const std::string &desc, app::Simulation *sim)
Consturctor with name, desc, and simulator.
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 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.
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....
TreeNodeExtensionManager * getExtensionManager(bool must_exist=true)
Get the TreeNodeExtensionsManager.
void setExtensionManager(TreeNodeExtensionManager *mgr)
Enable tree node extensions by giving the root node a TreeNodeExtensionsManager.
virtual bool isAttached() const override final
Is this node part of a device tree with a proper RootTreeNode at the root.
const TreeNodeExtensionManager * getExtensionManager(bool must_exist=true) const
Get the TreeNodeExtensionsManager.
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...
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...
Simulator which builds a sparta DeviceTree.
Macros for handling exponential backoff.