 |
Cerata
A library to generate structural hardware designs
|
15 #include "cerata/array.h"
23 #include "cerata/edge.h"
24 #include "cerata/node.h"
25 #include "cerata/expression.h"
26 #include "cerata/parameter.h"
27 #include "cerata/pool.h"
28 #include "cerata/graph.h"
32 static std::shared_ptr<Node> IncrementNode(Node *node) {
33 if (node->IsLiteral() || node->IsExpression()) {
34 return node->shared_from_this() + 1;
35 }
else if (node->IsParameter()) {
38 auto param =
dynamic_cast<Parameter *
>(node);
40 std::vector<Node *> value_trace;
41 param->TraceValue(&value_trace);
43 if (!value_trace.back()->IsLiteral()) {
44 CERATA_LOG(FATAL,
"Parameter node " + param->ToString() +
" not (indirectly) sourced by literal.");
47 auto second_last = value_trace[value_trace.size() - 2];
48 auto incremented = value_trace.back()->shared_from_this() + 1;
50 Connect(second_last, incremented);
51 return node->shared_from_this();
53 CERATA_LOG(FATAL,
"Can only increment literal, expression or parameter size node " + node->ToString());
58 if (!(
size->IsLiteral() ||
size->IsParameter() ||
size->IsExpression())) {
59 CERATA_LOG(FATAL,
"NodeArray size node must be literal, parameter or expression.");
61 if (
size->IsParameter()) {
62 auto param =
size->AsParameter();
63 if (param->node_array_parent) {
64 auto na =
size->AsParameter()->node_array_parent.value();
66 CERATA_LOG(FATAL,
"NodeArray size can only be used by a single NodeArray.");
69 param->node_array_parent =
this;
80 auto new_node = std::dynamic_pointer_cast<Node>(
base_->Copy());
82 new_node->SetParent(*
parent());
84 new_node->SetArray(
this);
85 nodes_.push_back(new_node);
100 CERATA_LOG(FATAL,
"Index " + std::to_string(i) +
" out of bounds for node " +
ToString());
107 for (
const auto &e :
nodes_) {
113 for (
size_t i = 0; i <
nodes_.size(); i++) {
114 if (
nodes_[i].get() == &n) {
118 CERATA_LOG(FATAL,
"Node " + n.
ToString() +
" is not element of " + this->ToString());
129 :
Object(std::move(name),
Object::ARRAY), node_id_(id), base_(std::move(base)) {
130 base_->SetArray(
this);
141 auto result = std::dynamic_pointer_cast<NodeArray>(this->
Copy());
142 result->SetName(
name);
145 std::shared_ptr<Node> new_size = result->size_;
146 if (
size_->IsParameter()) {
147 if (rebinding->count(
size_.get()) == 0) {
148 CERATA_LOG(FATAL,
"Size node parameters of NodeArray " +
size_->name()
149 +
" must be in rebind map before NodeArray can be copied.");
151 result->SetSize(rebinding->at(
size_.get())->shared_from_this());
156 auto base_generics =
base_->type()->GetGenerics();
157 if (!base_generics.empty()) {
160 auto rebound_base_type = result->type()->Copy(*rebinding);
162 result->base_->SetType(rebound_base_type);
172 const std::shared_ptr<Node> &size) :
175 std::shared_ptr<PortArray>
port_array(
const std::string &name,
176 const std::shared_ptr<Type> &type,
177 const std::shared_ptr<Node> &size,
179 const std::shared_ptr<ClockDomain> &domain) {
180 auto base_node =
port(name, type, dir, domain);
182 return std::shared_ptr<PortArray>(
port_array);
185 std::shared_ptr<PortArray>
port_array(
const std::shared_ptr<Port> &base_node,
186 const std::shared_ptr<Node> &size) {
188 return std::shared_ptr<PortArray>(
port_array);
199 const std::shared_ptr<Type> &type,
200 const std::shared_ptr<Node>& size,
201 const std::shared_ptr<ClockDomain> &domain) {
202 auto base_node =
signal(name, type, domain);
203 auto *sig_array =
new SignalArray(base_node, size);
204 return std::shared_ptr<SignalArray>(sig_array);
Node::NodeID node_id_
The type ID of the nodes in this NodeArray.
Type * type() const
Return the type of the nodes in the NodeArray.
virtual Graph & Add(const std::shared_ptr< Object > &object)
Add an object to the component.
void SetParent(Graph *new_parent) override
Set the parent of this NodeArray base node and array nodes.
An array of signal nodes.
NodeArray * CopyOnto(Graph *dst, const std::string &name, NodeMap *rebinding)
Copy the NodeArray onto a graph, but not the array nodes. Creates a new size node set to zero.
std::optional< std::shared_ptr< ClockDomain > > GetDomain(const Node &node)
Return the clock domain of a node, if it is a synchronous node.
std::shared_ptr< Node > base_
A node representing the template for each of the element nodes.
std::shared_ptr< Node > Append(bool increment_size=true)
Append a node to this array, optionally incrementing the size node. Returns a pointer to that node.
A terminator structure to enable terminator sanity checks.
A graph representing a hardware structure.
virtual void SetParent(Graph *parent)
Set the parent graph of this object.
Contains every Cerata class, function, etc...
std::vector< std::shared_ptr< Node > > nodes_
The nodes contained by this array.
std::shared_ptr< Object > Copy() const override
Deep-copy the NodeArray, but not the array nodes. Resets the size node to an integer literal of 0.
std::unordered_map< const Node *, Node * > NodeMap
A mapping from one object to another object, used in e.g. type generic rebinding.
std::string ToString() const
Return a human-readable representation of this NodeArray.
std::string name() const
Return the name of the object.
NodeID
Node type IDs with different properties.
PortArray(const std::shared_ptr< Port > &base, const std::shared_ptr< Node > &size)
Construct a new port array.
std::shared_ptr< Literal > intl(int64_t i)
Obtain a shared pointer to an integer literal from the default node pool.
A Cerata Object on a graph.
size_t IndexOf(const Node &n) const
Return the index of a specific node.
std::shared_ptr< Object > Copy() const override
Make a copy of this port array.
void SetSize(const std::shared_ptr< Node > &size)
Set the size node.
void IncrementSize()
Increment the size of the ArrayNode.
virtual std::string ToString() const
Return a human-readable string of this node.
std::shared_ptr< SignalArray > signal_array(const std::string &name, const std::shared_ptr< Type > &type, const std::shared_ptr< Node > &size, const std::shared_ptr< ClockDomain > &domain)
Construct a new node array and return a shared pointer to it.
void SetType(const std::shared_ptr< Type > &type)
Set the type of the base node and array nodes.
std::shared_ptr< Signal > signal(const std::string &name, const std::shared_ptr< Type > &type, const std::shared_ptr< ClockDomain > &domain)
Create a new Signal and return a smart pointer to it.
Dir dir_
The direction of this terminator.
std::shared_ptr< Node > size_
A node representing the number of concatenated edges.
Node * size() const
Return the size node.
NodeArray(std::string name, Node::NodeID id, std::shared_ptr< Node > base, const std::shared_ptr< Node > &size)
ArrayNode constructor.
Node * node(size_t i) const
Return element node i.
std::shared_ptr< PortArray > port_array(const std::string &name, const std::shared_ptr< Type > &type, const std::shared_ptr< Node > &size, Port::Dir dir, const std::shared_ptr< ClockDomain > &domain)
Get a smart pointer to a new ArrayPort.
virtual std::optional< Graph * > parent() const
Return the parent graph of this object, if any. Returns empty option otherwise.
std::shared_ptr< Port > port(const std::string &name, const std::shared_ptr< Type > &type, Term::Dir dir, const std::shared_ptr< ClockDomain > &domain)
Make a new port with some name, type and direction.
void ImplicitlyRebindNodes(Graph *dst, const std::vector< Node * > &nodes, NodeMap *rebinding)
Make sure that the NodeMap contains all nodes to be rebound onto the destination graph.
std::shared_ptr< Edge > Connect(Node *dst, Node *src)
Connect two nodes, returns the corresponding edge.