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
17#include "sparta/log/NotificationSource.hpp"
18#include "sparta/simulation/TreeNodePrivateAttorney.hpp"
22
23namespace sparta
24{
25 class ArchData;
26 class Clock;
27
28 namespace app {
29 class Simulation;
30 }
31
32 namespace python {
33 class PythonInterpreter;
34 }
35
49 class RootTreeNode : public TreeNode
50 {
51 public:
52
58
75 RootTreeNode(const std::string & name,
76 const std::string & desc,
77 app::Simulation* sim,
78 GlobalTreeNode* search_scope) :
80 sim_(sim),
81 new_node_noti_(this,
82 "descendant_attached",
83 "Notification immediately after a node becomes a descendant of this "
84 "root at any distance. This new node may have children already attached "
85 "which will not receive their own descendant_attached notification",
86 "descendant_attached")
87 {
88 if(search_scope != nullptr){
89 search_node_ = search_scope;
90 }else{
91 search_node_ = new GlobalTreeNode();
92 alloc_search_node_.reset(search_node_);
93 }
94 search_node_->addChild(this);
95
96 /* Define the default scope that all tree nodes will be in. This is
97 * to ensure that getScopeRoot() never returns nullptr event when no
98 * scope is explicitly defined. */
100 }
101
105 RootTreeNode(const std::string & name,
106 const std::string & desc,
107 GlobalTreeNode* search_scope) :
108 RootTreeNode(name, desc, nullptr, search_scope)
109 {
110 // Delegated construction
111 }
112
116 RootTreeNode(const std::string & name) :
117 RootTreeNode(name, "Top of device tree", nullptr, nullptr)
118 {
119 // Delegated construction
120 }
121
125 RootTreeNode(const std::string & name,
126 const std::string & desc,
127 app::Simulation* sim) :
128 RootTreeNode(name, desc, sim, nullptr)
129 {
130 // Delegated construction
131 }
132
137 RootTreeNode(const std::string & name,
138 const std::string & desc) :
139 RootTreeNode(name, desc, nullptr, nullptr)
140 {
141 // Delegated construction
142 }
143
148 RootTreeNode("top", "Top of device tree", sim, nullptr)
149 {
150 // Delegated construction
151 }
152
157 RootTreeNode("top", "Top of device tree", nullptr, search_scope)
158 {
159 // Delegated construction
160 }
161
166 RootTreeNode("top", "Top of device tree", sim, search_scope)
167 {
168 // Delegated construction
169 }
170
175 RootTreeNode("top", "Top of device tree", nullptr, nullptr)
176 {
177 // Delegated construction
178 }
179
187 virtual ~RootTreeNode() {
188 // Inform Search Scope node since it will not be notified by
189 // ~TreeNode, which does not recognize the search scope as a parent
190 if(search_node_){
191 removeFromParentForTeardown_(search_node_);
192 }
193
194 // No need to alert children, because ~TreeNode will do this next
195 }
196
197 // Returns true. Tree root is always considered "attached"
198 virtual bool isAttached() const override final {
199 return true;
200 }
201
202 // Returns 0. Tree root will never have a parent
203 virtual TreeNode* getParent() override final { return nullptr; }
204
205 // Returns 0. Tree root will never have a parent
206 virtual const TreeNode* getParent() const override final { return nullptr; }
207
208 // Override TreeNode::setClock() so we can pass that clock to the search scope
209 virtual void setClock(const Clock * clk) override final {
210 if (search_node_) {
211 search_node_->setClock(clk);
212 }
214 }
215
220 return sim_;
221 }
222
230 sparta_assert(search_node_);
231 return search_node_;
232 }
233
243 if(getPhase() != TREE_BUILDING){
244 throw SpartaException("Device tree with root \"")
245 << getLocation()<< "\" not currently in the TREE_BUILDING phase, so it cannot "
246 "enter TREE_CONFIGURING";
247 }
248
249 enterConfig_(); // Enter the next phase (cannot throw)
250 }
251
267 void enterFinalized(sparta::python::PythonInterpreter* pyshell = nullptr);
268
285 if(getPhase() != TREE_FINALIZED){
286 throw SpartaException("Device tree with root \"")
287 << getLocation()
288 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeEarly)";
289 }
290
292 }
293
305 if(getPhase() != TREE_FINALIZED){
306 throw SpartaException("Device tree with root \"")
307 << getLocation()
308 << "\" not in the TREE_FINALIZED phase, so it cannot be bound (bindTreeLate)";
309 }
310
312 }
313
328
336 if(getPhase() != TREE_FINALIZED){
337 throw SpartaException("Device tree with root \"")
338 << getLocation()
339 << "\" not in the TREE_FINALIZED phase, so it cannot be pre-run validated";
340 }
341
342 validateTree_(); // Validate all nodes, which may throw
343 }
344
345
353
364 void dumpDebugContent(std::ostream& out) noexcept {
366 }
367
379 enterTeardown_(); // Enter the next phase
380 }
381
389 virtual std::string stringize(bool pretty=false) const override {
390 (void) pretty;
391 std::stringstream ss;
392 ss << "<" << getLocation() << " (root)>";
393 return ss.str();
394 }
395
399
412 return new_node_noti_;
413 }
414
417
422
434 void getArchDataAssociations(std::vector<const ArchData*>& ad_this_tree,
435 std::vector<const ArchData*>& ad_no_assoc,
436 std::vector<const ArchData*>& ad_not_attached,
437 std::vector<const ArchData*>& ad_other_tree) const noexcept;
438
450
461 void dumpArchDataAssociations(std::ostream& o) const noexcept;
462
466 void dumpTypeMix(std::ostream& o) const;
467
470
471 private:
472
473 // No effect on root
474 virtual void createResource_() override {};
475
485 virtual void onSettingParent_(const TreeNode* parent) const override final {
486 if(parent != search_node_){
487 throw SpartaException("This RootTreeNode \"")
488 << "\" cannot be a child of any other node except its constructed "
489 "GlobalTreeNode";
490 }
491 }
492
501 virtual void setParent_(TreeNode* parent, bool) override final {
502 if(parent != search_node_){
503 throw SpartaCriticalError("This RootTreeNode \"")
504 << "\" cannot be a child of any other node except its constructed "
505 "GlobalTreeNode";
506 }
507
508 // NOTE: Do not store parent because the root should act as if there is no parent
509 }
510
511 virtual void onDescendentSubtreeAdded_(TreeNode* des) noexcept override final {
512 // Broadcast notification for self coming into existence
513 try{
514 new_node_noti_.postNotification(*des);
515
516 // Iterate subtree headed by des and notify observers of these
517 for(TreeNode* child : TreeNodePrivateAttorney::getAllChildren(des)){
518 onDescendentSubtreeAdded_(child);
519 }
520 }catch(SpartaException& ex){
521 std::stringstream msg;
522 msg << ex.what() <<
523 "\nThis exception within onDescendentSubtreeAdded_, which is not exception-"
524 "safe. The integrity of this sparta tree (" << getRoot() << ") is compromised. "
525 "Aborting. ";
526 sparta_abort(false,msg.str());
527 }
528 }
529
534 std::unique_ptr<GlobalTreeNode> alloc_search_node_;
535
540 GlobalTreeNode* search_node_;
541
545 app::Simulation* sim_;
546
551 NewDescendantNotiSrc new_node_noti_;
552 };
553
554} // namespace sparta
TreeNode refinement representing the global namespace (above "top") of a device tree.
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:51
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.
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.
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....
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...
RootTreeNode(const std::string &name, const std::string &desc)
Constructor with name and desc.
NotificationSource< TreeNode > NewDescendantNotiSrc
Type for notification source in this node which is posted when a new descendent is attached.
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.
Node in a composite tree representing a sparta Tree item.
Definition TreeNode.hpp:205
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:303
std::string getLocation() const override final
virtual TreeNode * getRoot()
Gets farthest ancestor of this node.
void validateTree_()
Iterates the finalized tree and validates each node (e.g. ensures statistics can be evaluated)
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
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.
friend class TreeNodePrivateAttorney
Friend an attorney pattern that can expose access to getAllChildren_ or other methods that bypass pri...
Definition TreeNode.hpp:229
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.