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.
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.
virtual TreeNode * getParent()
Gets immediate parent of this node if one exists.
Definition TreeNode.hpp:965
uint32_t group_idx_type
Index within a group.
Definition TreeNode.hpp:261
const Clock * getClock() override
Walks up parents (starting with self) until a parent with an associated local clock is found,...
const std::string & getName() const override
Gets the name of this node.
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