 |
Cerata
A library to generate structural hardware designs
|
18 #include "cerata/expression.h"
19 #include "cerata/graph.h"
23 static std::string ToString(Node *n) {
29 static std::string ToString(
const std::shared_ptr<Node>& n) {
35 std::shared_ptr<Expression>
Expression::Make(
Op op, std::shared_ptr<Node> lhs, std::shared_ptr<Node> rhs) {
37 auto result = std::shared_ptr<Expression>(e);
39 e->parent().value()->Add(result);
45 static std::string GenerateName(
Expression *expr, std::shared_ptr<Node> lhs, std::shared_ptr<Node> rhs) {
46 auto l = ::cerata::ToString(std::move(lhs));
47 auto e = ::cerata::ToString(expr);
48 auto r = ::cerata::ToString(std::move(rhs));
49 std::string result =
"Expr_" + l + e + r;
57 rhs_(std::move(rhs)) {
58 if (
lhs_->parent() &&
rhs_->parent()) {
59 auto lp = *
lhs_->parent();
60 auto rp = *
rhs_->parent();
62 CERATA_LOG(ERROR,
"Can only generate expressions between nodes on same parent.");
66 auto lp = *
lhs_->parent();
68 }
else if (
rhs_->parent()) {
69 auto rp = *
rhs_->parent();
75 if (exp->
lhs_->IsLiteral() && exp->
rhs_->IsLiteral()) {
76 auto l = std::dynamic_pointer_cast<const Literal>(exp->
lhs_);
77 auto r = std::dynamic_pointer_cast<const Literal>(exp->
rhs_);
78 if ((l->storage_type() == Literal::StorageType::INT)
79 && (r->storage_type() == Literal::StorageType::INT)
80 && (l->type() == r->type())) {
81 std::shared_ptr<Node> new_node;
83 case Op::ADD:
return intl(l->IntValue() + r->IntValue());
84 case Op::SUB:
return intl(l->IntValue() - r->IntValue());
85 case Op::MUL:
return intl(l->IntValue() * r->IntValue());
86 case Op::DIV:
return intl(l->IntValue() / r->IntValue());
90 return exp->shared_from_this();
113 if (exp->
rhs_ ==
intl(0)) { CERATA_LOG(FATAL,
"Division by 0."); }
118 return exp->shared_from_this();
122 std::shared_ptr<Node> result = node->shared_from_this();
125 if (node->IsExpression()) {
126 auto expr = std::dynamic_pointer_cast<Expression>(result);
132 if ((min_lhs != expr->
lhs_) || (min_rhs != expr->
rhs_)) {
140 if (result->IsExpression()) {
141 expr = std::dynamic_pointer_cast<Expression>(result);
151 case Expression::Op::ADD:
return "+";
152 case Expression::Op::SUB:
return "-";
153 case Expression::Op::MUL:
return "*";
154 case Expression::Op::DIV:
return "/";
161 if (min->IsExpression()) {
162 auto mine = std::dynamic_pointer_cast<Expression>(min);
163 auto ls = mine->lhs_->ToString();
165 auto rs = mine->rhs_->ToString();
168 return min->ToString();
174 std::dynamic_pointer_cast<Node>(
lhs_->Copy()),
175 std::dynamic_pointer_cast<Node>(
rhs_->Copy()));
179 auto new_lhs = this->
lhs_;
180 auto new_rhs = this->
rhs_;
184 if (rebinding->count(
lhs_.get()) > 0) {
185 new_lhs = rebinding->at(
lhs_.get())->shared_from_this();
187 new_lhs =
lhs_->CopyOnto(dst,
lhs_->name(), rebinding)->shared_from_this();
189 if (rebinding->count(
rhs_.get()) > 0) {
190 new_rhs = rebinding->at(
rhs_.get())->shared_from_this();
192 new_rhs =
rhs_->CopyOnto(dst,
rhs_->name(), rebinding)->shared_from_this();
195 (*rebinding)[
this] = result.get();
201 out->push_back(
lhs_.get());
202 lhs_->AppendReferences(out);
203 out->push_back(
rhs_.get());
204 rhs_->AppendReferences(out);
static std::shared_ptr< Node > Minimize(Node *node)
Minimize a node, if it is an expression, otherwise just returns a copy of the input.
virtual Graph & Add(const std::shared_ptr< Object > &object)
Add an object to the component.
std::string ToString() const override
Minimize the expression and convert it to a human-readable string.
static std::shared_ptr< Node > EliminateZeroOne(Expression *exp)
Eliminate nodes that have zero or one on either side for specific expressions.
A node representing a binary tree of other nodes.
A graph representing a hardware structure.
static std::shared_ptr< Expression > Make(Op op, std::shared_ptr< Node > lhs, std::shared_ptr< Node > rhs)
Short-hand to create a smart pointer to an expression.
Op
Binary expression operator enum class.
virtual void SetParent(Graph *parent)
Set the parent graph of this object.
std::shared_ptr< Node > lhs_
The left hand side node.
Contains every Cerata class, function, etc...
Node * lhs() const
Return the left-hand side node of the expression.
std::unordered_map< const Node *, Node * > NodeMap
A mapping from one object to another object, used in e.g. type generic rebinding.
NodeID
Node type IDs with different properties.
std::shared_ptr< Node > rhs_
The right hand side node.
std::shared_ptr< Type > string()
Return a static string type.
Node * rhs() const
Return the right-hand side node of the expression.
std::shared_ptr< Literal > intl(int64_t i)
Obtain a shared pointer to an integer literal from the default node pool.
std::string ToString()
Return a human-readable string from a type.
Expression(Op op, std::shared_ptr< Node > lhs, std::shared_ptr< Node > rhs)
Construct a new expression.
void AppendReferences(std::vector< Object * > *out) const override
Depth-first traverse the expression tree and add any nodes owned.
static std::shared_ptr< Node > MergeIntLiterals(Expression *exp)
Merge expressions of integer literals into their resulting integer literal.
Op operation_
The binary operator of this expression.
std::shared_ptr< Object > Copy() const override
Copy this expression.
Node * CopyOnto(Graph *dst, const std::string &name, NodeMap *rebinding) const override
Copy this expression onto a graph and rebind anything in the expression tree.
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.
A no-input, multiple-outputs node.