summaryrefslogtreecommitdiff
path: root/frontends/ast
diff options
context:
space:
mode:
authorClifford Wolf <clifford@clifford.at>2014-08-06 15:43:46 +0200
committerClifford Wolf <clifford@clifford.at>2014-08-06 15:52:54 +0200
commitd259abbda2b9d568228dc8d0bed2d0b0d88d7b4f (patch)
tree86c90432e4453f030be99a5e30a4c9d10ef53d62 /frontends/ast
parentb4f10e342cf400bd2f392a588f28de069ba0f9d8 (diff)
Added AST_MULTIRANGE (arrays with more than 1 dimension)
Diffstat (limited to 'frontends/ast')
-rw-r--r--frontends/ast/ast.cc7
-rw-r--r--frontends/ast/ast.h4
-rw-r--r--frontends/ast/simplify.cc52
3 files changed, 62 insertions, 1 deletions
diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc
index 5815fb0d..f18124e2 100644
--- a/frontends/ast/ast.cc
+++ b/frontends/ast/ast.cc
@@ -78,6 +78,7 @@ std::string AST::type2str(AstNodeType type)
X(AST_PARASET)
X(AST_ARGUMENT)
X(AST_RANGE)
+ X(AST_MULTIRANGE)
X(AST_CONSTANT)
X(AST_REALVALUE)
X(AST_CELLTYPE)
@@ -284,6 +285,12 @@ void AstNode::dumpAst(FILE *f, std::string indent)
fprintf(f, " int=%u", (int)integer);
if (realvalue != 0)
fprintf(f, " real=%e", realvalue);
+ if (!multirange_dimensions.empty()) {
+ fprintf(f, " multirange=[");
+ for (int v : multirange_dimensions)
+ fprintf(f, " %d", v);
+ fprintf(f, " ]");
+ }
fprintf(f, "\n");
for (auto &it : attributes) {
diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h
index 00b044bc..5fb1f0a7 100644
--- a/frontends/ast/ast.h
+++ b/frontends/ast/ast.h
@@ -56,6 +56,7 @@ namespace AST
AST_PARASET,
AST_ARGUMENT,
AST_RANGE,
+ AST_MULTIRANGE,
AST_CONSTANT,
AST_REALVALUE,
AST_CELLTYPE,
@@ -158,6 +159,9 @@ namespace AST
uint32_t integer;
double realvalue;
+ // if this is a multirange memory then this vector contains offset and length of each dimension
+ std::vector<int> multirange_dimensions;
+
// this is set by simplify and used during RTLIL generation
AstNode *id2ast;
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc
index 29d00be9..39c47262 100644
--- a/frontends/ast/simplify.cc
+++ b/frontends/ast/simplify.cc
@@ -553,6 +553,56 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
}
}
+ // resolve multiranges on memory decl
+ if (type == AST_MEMORY && children.size() > 1 && children[1]->type == AST_MULTIRANGE)
+ {
+ int total_size = 1;
+ multirange_dimensions.clear();
+ for (auto range : children[1]->children) {
+ if (!range->range_valid)
+ log_error("Non-constant range on memory decl at %s:%d.\n", filename.c_str(), linenum);
+ multirange_dimensions.push_back(std::min(range->range_left, range->range_right));
+ multirange_dimensions.push_back(std::max(range->range_left, range->range_right) - std::min(range->range_left, range->range_right) + 1);
+ total_size *= multirange_dimensions.back();
+ }
+ delete children[1];
+ children[1] = new AstNode(AST_RANGE, AstNode::mkconst_int(0, true), AstNode::mkconst_int(total_size-1, true));
+ did_something = true;
+ }
+
+ // resolve multiranges on memory access
+ if (type == AST_IDENTIFIER && id2ast && id2ast->type == AST_MEMORY && children.size() > 0 && children[0]->type == AST_MULTIRANGE)
+ {
+ AstNode *index_expr = nullptr;
+
+ for (int i = 0; 2*i < SIZE(id2ast->multirange_dimensions); i++)
+ {
+ if (SIZE(children[0]->children) < i)
+ log_error("Insufficient number of array indices for %s at %s:%d.\n", log_id(str), filename.c_str(), linenum);
+
+ AstNode *new_index_expr = children[0]->children[i]->children.at(0)->clone();
+
+ if (id2ast->multirange_dimensions[2*i])
+ new_index_expr = new AstNode(AST_SUB, new_index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i], true));
+
+ if (i == 0)
+ index_expr = new_index_expr;
+ else
+ index_expr = new AstNode(AST_ADD, new AstNode(AST_MUL, index_expr, AstNode::mkconst_int(id2ast->multirange_dimensions[2*i-1], true)), new_index_expr);
+ }
+
+ for (int i = SIZE(id2ast->multirange_dimensions)/1; i < SIZE(children[0]->children); i++)
+ children.push_back(children[0]->children[i]->clone());
+
+ delete children[0];
+ if (index_expr == nullptr)
+ children.erase(children.begin());
+ else
+ children[0] = new AstNode(AST_RANGE, index_expr);
+
+ did_something = true;
+ }
+
// trim/extend parameters
if (type == AST_PARAMETER || type == AST_LOCALPARAM) {
if (children.size() > 1 && children[1]->type == AST_RANGE) {
@@ -1166,7 +1216,7 @@ skip_dynamic_range_lvalue_expansion:;
if (stage > 1 && (type == AST_ASSIGN_EQ || type == AST_ASSIGN_LE) && children[0]->type == AST_IDENTIFIER &&
children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY && children[0]->id2ast->children.size() >= 2 &&
children[0]->id2ast->children[0]->range_valid && children[0]->id2ast->children[1]->range_valid &&
- (children[0]->children.size() == 1 || children[0]->children.size() == 2))
+ (children[0]->children.size() == 1 || children[0]->children.size() == 2) && children[0]->children[0]->type == AST_RANGE)
{
std::stringstream sstr;
sstr << "$memwr$" << children[0]->str << "$" << filename << ":" << linenum << "$" << (autoidx++);