From d259abbda2b9d568228dc8d0bed2d0b0d88d7b4f Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Wed, 6 Aug 2014 15:43:46 +0200 Subject: Added AST_MULTIRANGE (arrays with more than 1 dimension) --- frontends/ast/ast.cc | 7 +++++++ frontends/ast/ast.h | 4 ++++ frontends/ast/simplify.cc | 52 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 62 insertions(+), 1 deletion(-) (limited to 'frontends/ast') 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 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++); -- cgit v1.2.3