The Sparta Modeling Framework
Loading...
Searching...
No Matches
ResourceTreeNode.hpp
1// <ResourceTreeNode> -*- C++ -*-
2
3#pragma once
4
5#include <iostream>
6#include <string>
7
8#include "sparta/functional/ArchData.hpp"
10#include "sparta/log/MessageSource.hpp"
14#include "sparta/simulation/ResourceFactory.hpp"
15
16namespace sparta
17{
18
30 {
31 public:
32
40 static const ArchData::offset_type ARCH_DATA_LINE_SIZE = 256;
41
64 const std::string & name,
65 const std::string & group,
66 group_idx_type group_idx,
67 const std::string & desc,
68 ResourceFactoryBase* res_fact) :
69 TreeNode(name, group, group_idx, desc),
70 created_resource_(false),
71 res_fact_(res_fact),
72 params_(0),
73 adata_(this, ARCH_DATA_LINE_SIZE)
74 {
75 setExpectedParent_(parent);
76
77 if(nullptr == res_fact_){
78 throw SpartaException("Resource factory for node \"")
79 << getLocation() << " cannot be null";
80 }
81
82 if(parent != nullptr){
83 parent->addChild(this); // Do not inherit parent state
84 }
85
86 initConfigurables_();
87 }
88
90 ResourceTreeNode(const std::string & name,
91 const std::string & group,
92 group_idx_type group_idx,
93 const std::string & desc,
94 ResourceFactoryBase* res_fact) :
95 ResourceTreeNode(nullptr, name, group, group_idx, desc, res_fact)
96 {
97 // Initialization delegated to other constructor
98 }
99
102 const std::string & name,
103 const std::string & desc,
104 ResourceFactoryBase* res_fact) :
105 ResourceTreeNode(parent,
106 name,
109 desc,
110 res_fact)
111 {
112 // Initialization delegated to other constructor
113 }
114
116 ResourceTreeNode(const std::string & name,
117 const std::string & desc,
118 ResourceFactoryBase* res_fact) :
119 ResourceTreeNode(name,
122 desc,
123 res_fact)
124 {
125 // Initialization delegated to other constructor
126 }
127
130 if(res_fact_ != nullptr){
131 if(params_ != nullptr){
132 res_fact_->deleteParameters(params_);
133 params_ = 0;
134 }
135
136 if(getResource_() != nullptr){
137 res_fact_->deleteResource(getResource_());
138 }
139
140 res_fact_->deleteSubtree(this);
141 }
142 }
143
149 sparta_assert(params_ != 0);
150 return params_;
151 }
152
157 sparta_assert(params_ != 0);
158 return params_;
159 }
160
166 virtual std::string getResourceType() const override {
167 return res_fact_->getResourceType();
168 }
169
175 virtual std::string getResourceTypeRaw() const override {
176 return res_fact_->getResourceTypeRaw();
177 }
178
186 virtual std::string stringize(bool pretty=false) const override {
187 (void) pretty;
188 std::stringstream ss;
189 ss << "<" << getLocation() << " resource: \""
190 << res_fact_->getResourceType() << "\">";
191 return ss.str();
192 }
193
198 void finalize() {
199 if(getResource_() != nullptr){
200 throw SpartaException("Cannot re-finalize this ResourceTreeNode: ")
201 << getLocation() << " because it already has a resource. ";
202 }
203
205 }
206
207
208 Resource* getResourceNow() noexcept {
209 return getResource_();
210 }
211
212 protected:
213
232 virtual void createResource_() override
233 {
234 if(getPhase() != TREE_FINALIZING){
235 throw SpartaException("Tried to create resource on ")
236 << getLocation() << " but tree was not in TREE_FINALIZING phase";
237 }
238
239 if(getResource_() != nullptr){
240 // Already has a resource. Nothing left to do
241 sparta_assert(created_resource_,
242 "Resource was set in ResourceTreeNode " << getLocation()
243 << " but not by the ResourceTreeNode itself");
246 return;
247 }
248
249 // Ensure that this node has a parent OR children.
250 // Note that this:
251 // A) prohibits 1-node device trees. A 'top' node should exist anyway
252 // B) Cannot check for orphaned trees (yet)
253 if(!isAttached()){
254 throw SpartaException("Cannot create resource for TreeNode \"")
255 << getName() << "\"@" << (void*)this << " because it is not attached to a tree with a RootTreeNode";
256 }
257
258 // Check for valid configured values
259 if(getResource_() != 0){
260 throw SpartaException("Resource already created for TreeNode \"")
261 << getLocation() << "\". Cannot create again";
262 }
263
264 if(getClock() == nullptr){
265 throw SpartaException("No clock associated with TreeNode ")
266 << getLocation() << " and no ancestor has an associated clock. All ResourceTreeNodes "
267 << "must have at least one clock associated with a node in their ancestry";
268 }
269
270 std::string errs;
271 if(!params_->validateIndependently(errs)){
272 throw SpartaException("Parameter limits violated:")
273 << errs;
274 }
275
276 if(!params_->validateDependencies(this, errs)){
277 throw SpartaException("Parameter validation callbacks indicated invalid parameters: ")
278 << errs;
279 }
280
281 // Note, parameters have been reset to 0 read-counts when the
282 // parameter set was constructed
283
284 Resource* r = res_fact_->createResource(this, params_);
285 sparta_assert(r != nullptr); // Resource created must not be NULL
286
287 if(getResource_() == nullptr){
288 throw SpartaException("ResourceTreeNode ") << getLocation()
289 << " created a resource of type " << res_fact_->getResourceType()
290 << " but that resource did not register itself with this node. Ensure that "
291 "this resource class uses the proper sparta::Resource base-class constructor "
292 "which takes a ResourceContainer";
293 }
294 if(getResource_() != r){
295 throw SpartaException("ResourceTreeNode ") << getLocation()
296 << " created a resource of type " << res_fact_->getResourceType()
297 << " but that resource was different than the resource registered with this "
298 "node.";
299 }
300
301 lockResource_(); // No changing resource until teardown
302
303 created_resource_ = true; // Created by this ResourceTreeNode
304
305 // Note, do not check all parameters right here because children may
306 // be reading them. Instead, defer this to a tree-validation stage
307 // Ensure each Parameter was read at least once by the consuming
308 // component
309
310 // Layout the contained ArchData
311 adata_.layout();
312 }
313
314 private:
315
316 // Prevent addition to the tree after the TREE_BUILDING phase
317 void onSettingParent_(const TreeNode* parent) const override {
318 (void) parent;
319 if(isBuilt()){
320 throw SpartaException("Cannot add ResourceTreeNode \"")
321 << getName() << "\" as child of device tree node \""
322 << getLocation() << "\". This tree has exited the TREE_BUILDING "
323 << "phase and ResourceTreeNodes can no longer be added.";
324 }
325 }
326
330 void onConfiguring_() override {
331 // Hook to configure mode, even call create subtree
332 res_fact_->onConfiguring(this);
333 }
334
338 void onBindTreeEarly_() override {
339 // This doesn't work due to a bug in Port's auto
340 // precedence registration in SPARTA. If the resource
341 // factory does the binding early and connects ports
342 // together, then when a sparta::Unit's onBindTreeEarly_
343 // function is called, the ports are already bound and an
344 // assertion will fire. The fix should be a separate
345 // state that allows the Unit to register events on ports
346 // before ANY binding occurs
347 //
348 //res_fact_->bindEarly(this);
349 }
350
354 void onBindTreeLate_() override {
355 res_fact_->bindLate(this);
356 }
357
358 // Validate the tree
359 void validateNode_() const override {
360 params_->verifyAllRead(); // Throws if not all read at least once
361 }
362
371 void initConfigurables_() {
372 // Create parameters first
373 params_ = res_fact_->createParameters(this);
374 sparta_assert(params_ != 0); // Params must not be NULL
375 params_->resetReadCounts(); // Reset read-counts to 0
376
377 //Hook for additional building is needed
378 res_fact_->onBuilding(this);
379
380 std::string res_type = res_fact_->getResourceType();
381 if(res_type == ""){
382 throw SpartaException("resource type for ResourceFactory associated with ")
383 << getLocation() << " must not be empty string";
384 }
385 }
386
387 bool created_resource_;
388 ResourceFactoryBase* const res_fact_;
389 ParameterSet* params_;
390
398 ArchData adata_;
399 };
400
401
402} // 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
Generic container of Parameters.
void verifyAllRead() const
Checks the read-count on all Parameters. If any have no been read at least once since last write (sin...
void resetReadCounts()
Reset the read-count on all Parameters in this set.
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.
Factory which can create Resources as well as the Parameter sets that can be modified before actually...
virtual void deleteSubtree(sparta::ResourceTreeNode *n)=0
Optionally deletes the TreeNodes created by createSubtee (if any).
virtual void deleteResource(Resource *res)=0
Deletes a resource created by the createResource method of this ResourceFactory.
virtual std::string getResourceType() const =0
Returns the resource type-name for this resource, demangled.
virtual void onBuilding(sparta::ResourceTreeNode *n)=0
Hook for additional building on ResourceTreeNode constructing.
virtual void deleteParameters(ParameterSet *params)=0
Deletes a ParameterSet created by the createParameters method of this ResourceFactory.
virtual Resource * createResource(TreeNode *node, const ParameterSet *params)=0
Instanitates a new Resource of the type described by this factory.
virtual void bindLate(TreeNode *node)=0
Allows contents to be bound together if desired.
virtual void onConfiguring(sparta::ResourceTreeNode *n)=0
Hook for additional configuring on resource node configure.
virtual std::string getResourceTypeRaw() const =0
Returns the resource type-name for this resource as in the typeid.
virtual ParameterSet * createParameters(TreeNode *node)=0
Creates a new set of parameters associated with the resource that can be created by this factory.
TreeNode subclass representing a node in the device tree which contains a single ResourceFactory and ...
virtual ~ResourceTreeNode()
Virtual Destructor.
virtual void createResource_() override
After setting parameters, create a resource.
void finalize()
Finalize this node and construct its resource.
ResourceTreeNode(const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc, ResourceFactoryBase *res_fact)
Alternate Constructor.
virtual std::string getResourceTypeRaw() const override
Gets the typename of the resource that this node will contain once finalized.
virtual std::string getResourceType() const override
Gets the typename of the resource that this node will contain once finalized, demangled.
const ParameterSet * getParameterSet() const
Gets the Parameter set assoiciated with this node.
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...
ResourceTreeNode(TreeNode *parent, const std::string &name, const std::string &group, group_idx_type group_idx, const std::string &desc, ResourceFactoryBase *res_fact)
Construct a new TreeNode attached to a parent.
ParameterSet * getParameterSet()
Gets the ParameterSet associated with this ResourceTreeNode.
ResourceTreeNode(TreeNode *parent, const std::string &name, const std::string &desc, ResourceFactoryBase *res_fact)
Alternate Constructor.
virtual std::string stringize(bool pretty=false) const override
Render description of this ResourceTreeNode as a string.
ResourceTreeNode(const std::string &name, const std::string &desc, ResourceFactoryBase *res_fact)
Alternate Constructor.
The is the base class for all types of resources used by the SPARTA framework.
Definition Resource.hpp:44
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
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
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.