The Sparta Modeling Framework
Loading...
Searching...
No Matches
DynamicResourceTreeNode.hpp
1// <DynamicResourceTreeNode> -*- C++ -*-
2
3#pragma once
4
5#include <iostream>
6#include <string>
7
9#include "sparta/log/MessageSource.hpp"
13#include "sparta/simulation/ResourceFactory.hpp"
14#include "sparta/functional/ArchData.hpp"
15
16namespace sparta
17{
47 template <typename ResourceT, typename ParamsT>
49 {
50 public:
51
58 static const ArchData::offset_type ARCH_DATA_LINE_SIZE = 256;
59
77 const std::string & name,
78 const std::string & group,
79 group_idx_type group_idx,
80 const std::string & desc,
81 const ParamsT* params) :
82 TreeNode(name, group, group_idx, desc),
83 adata_(this, ARCH_DATA_LINE_SIZE),
84 params_(params)
85 {
86 setExpectedParent_(parent);
87
88 if(nullptr == parent){
89 throw SpartaException("Cannot create a DynamicResourceTreeNode without a non-null parent. Error at: ")
90 << getLocation();
91 }
92
93 // Ensure that this node has a parent that is attached (because this node isn't actually attached yet)
94 if(false == parent->isAttached()){
95 throw SpartaException("Cannot create resource for TreeNode \"")
96 << getName() << "\"@" << (void*)this << " because it is not attached to a tree with a RootTreeNode";
97 }
98
99 if(nullptr == params){
100 throw SpartaException("Params for DynamicResourceTreeNode \"")
101 << getLocation() << " cannot be null";
102 }
103
104 if(getClock() == nullptr && parent->getClock() == nullptr){
105 throw SpartaException("No clock associated with TreeNode ")
106 << getLocation() << " and no ancestor has an associated clock. A DynamicResourceTreeNode "
107 << "must have at least one clock associated with a node in their ancestry";
108 }
109
110 // Layout the contained ArchData
111 adata_.layout();
112 if(parent != nullptr){
113 parent->addChild(this);
114 }
115 }
116
119 const std::string & name,
120 const std::string & desc,
121 const ParamsT* params) :
123 name,
126 desc,
127 params)
128 { }
129
132 }
133
138 void finalize() {
139 if(getResource_() != nullptr){
140 throw SpartaException("Cannot re-finalize this DynamicResourceTreeNode: ")
141 << getLocation() << " because it already has a resource";
142 }
143
144 createResource_();
145 }
146
154 virtual std::string stringize(bool pretty=false) const override {
155 (void) pretty;
156 std::stringstream ss;
157 ss << "<" << getLocation() << " dynamic resource: \"" << demangle(typeid(ResourceT).name()) << "\">";
158 return ss.str();
159 }
160
161 private:
162
186 virtual void createResource_() override {
187 sparta_assert(params_ != nullptr); // Constructor should prevent this
188 sparta_assert(getParent() != nullptr); // Constructor should prevent this
189
190 if(getResource_() != nullptr){
191 // Already has a resource. Nothing left to do
192 return;
193 }
194
195 if(getPhase() != TREE_FINALIZING){
196 throw SpartaException("Tried to create resource through DynamicResourceTreeNode ")
197 << getLocation() << " but tree was not in TREE_FINALIZING phase";
198 }
199
200 if(getClock() == nullptr){
201 throw SpartaException("No clock associated with DynamicResourceTreeNode ")
202 << getLocation() << " and no ancestor has an associated clock. All DynamicResourceTreeNodes "
203 << "must have at least one clock associated with a node in their ancestry";
204 }
205
206 std::string errs;
207 if(!params_->validateIndependently(errs)){
208 throw SpartaException("Parameter limits violated:")
209 << errs;
210 }
211
212 if(!params_->validateDependencies(this, errs)){
213 throw SpartaException("Parameter validation callbacks indicated invalid parameters: ")
214 << errs;
215 }
216
217 res_.reset(new ResourceT(this, params_));
218 sparta_assert(res_ != nullptr); // Resource created must not be null
219 if(getResource_() == nullptr){
220 throw SpartaException("DynamicResourceTreeNode ") << getLocation()
221 << " created a resource of type " << demangle(typeid(ResourceT).name())
222 << " but that resource did not register itself with this node. Ensure that "
223 "this resource class uses the proper sparta::Resource base-class constructor "
224 "which takes a ResourceContainer";
225 }
226 if(getResource_() != res_.get()){
227 throw SpartaException("DynamicResourceTreeNode ") << getLocation()
228 << " created a resource of type " << demangle(typeid(ResourceT).name())
229 << " but that resource was different than the resource registered with this "
230 "node.";
231 }
233 }
234
235 // Prevent addition to the tree after the TREE_BUILDING phase
236 virtual void onSettingParent_(const TreeNode* parent) const override {
237 (void) parent;
238 if(isBuilt()){
239 throw SpartaException("Cannot add DynamicResourceTreeNode \"")
240 << getName() << "\" as child of device tree node \""
241 << getLocation() << "\". This tree has exited the TREE_BUILDING "
242 << "phase and ResourceTreeNodes can no longer be added.";
243 }
244 }
245
246 std::unique_ptr<ResourceT> res_;
247
255 ArchData adata_;
256
260 const ParamsT* params_;
261 };
262
263
264} // namespace sparta
A set of sparta::Parameters per sparta::ResourceTreeNode.
Set of macros for Sparta assertions. Caught by the framework.
#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.
friend class ArchData
ArchData must be able to invoke associateArchData_ and disassociateArchData_ methods during construct...
void layout()
Organizes the Segments into overlapping regions as needed, eventually calling ArchDataSegment::place ...
Definition ArchData.hpp:586
TreeNode subclass representing a node in the device tree which creates and owns a resource....
DynamicResourceTreeNode(TreeNode *parent, const std::string &name, const std::string &desc, const ParamsT *params)
Alternate constructor.
virtual ~DynamicResourceTreeNode()
Virtual Destructor.
static const ArchData::offset_type ARCH_DATA_LINE_SIZE
Size of an ArchData line for ResourceTreeNode (bytes) ArchData for ResourceTreeNode is a catch-all sp...
void finalize()
Finalize this node and construct its resource.
DynamicResourceTreeNode(TreeNode *parent, const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc, const ParamsT *params)
Dynamic, Non-factory constructor. Useful when no predefined factory object is necessary....
virtual std::string stringize(bool pretty=false) const override
Render description of this ResourceTreeNode as a string.
virtual bool isBuilt() const
Is this node (and thus the entire tree above it) "built". Checks that getPhase has passed TREE_BUILDI...
TreePhase getPhase() const
Gets the trees current phase.
@ TREE_FINALIZING
Tree is being finalized, but has not completed (maybe errors?)
void lockResource_()
Allows subclasses to assign the resource associated with this node.
Resource * getResource_() noexcept
Returns the currently held resource of this node (if any). This method can be called at any time.
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
static constexpr char GROUP_NAME_NONE[]
Group name indicating that a node belongs to no group.
Definition TreeNode.hpp:314
virtual bool isAttached() const
Is this node part of a device tree with a proper RootTreeNode at the root.
Definition TreeNode.hpp:957
TreeNode()=delete
Not default-constructable.
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
uint32_t group_idx_type
Index within a group.
Definition TreeNode.hpp:261
virtual TreeNode * getParent()
Gets immediate parent of this node if one exists.
Definition TreeNode.hpp:965
const std::string & getName() const override
Gets the name of this node.
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
Macros for handling exponential backoff.
std::string demangle(const std::string &name) noexcept
Demangles a C++ symbol.
Definition Utils.hpp:203