mirror of https://github.com/YosysHQ/yosys.git
Added AST_MULTIRANGE (arrays with more than 1 dimension)
This commit is contained in:
parent
b4f10e342c
commit
d259abbda2
1
README
1
README
|
@ -326,7 +326,6 @@ Other Unsorted TODOs
|
|||
|
||||
- Implement missing Verilog 2005 features:
|
||||
|
||||
- Multi-dimensional arrays
|
||||
- Support for real (float) const. expressions and parameters
|
||||
- ROM modeling using $readmemh/$readmemb in "initial" blocks
|
||||
- Ignore what needs to be ignored (e.g. drive and charge strengths)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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++);
|
||||
|
|
|
@ -112,7 +112,8 @@ static void free_attr(std::map<std::string, AstNode*> *al)
|
|||
%token TOK_SUPPLY0 TOK_SUPPLY1 TOK_TO_SIGNED TOK_TO_UNSIGNED
|
||||
%token TOK_POS_INDEXED TOK_NEG_INDEXED TOK_ASSERT TOK_PROPERTY
|
||||
|
||||
%type <ast> wire_type range non_opt_range range_or_signed_int expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
||||
%type <ast> range range_or_multirange non_opt_range non_opt_multirange range_or_signed_int
|
||||
%type <ast> wire_type expr basic_expr concat_list rvalue lvalue lvalue_concat_list
|
||||
%type <string> opt_label tok_prim_wrapper hierarchical_id
|
||||
%type <boolean> opt_signed
|
||||
%type <al> attr
|
||||
|
@ -361,6 +362,15 @@ non_opt_range:
|
|||
$$->children.push_back($2);
|
||||
};
|
||||
|
||||
non_opt_multirange:
|
||||
non_opt_range non_opt_range {
|
||||
$$ = new AstNode(AST_MULTIRANGE, $1, $2);
|
||||
} |
|
||||
non_opt_multirange non_opt_range {
|
||||
$$ = $1;
|
||||
$$->children.push_back($2);
|
||||
};
|
||||
|
||||
range:
|
||||
non_opt_range {
|
||||
$$ = $1;
|
||||
|
@ -369,6 +379,10 @@ range:
|
|||
$$ = NULL;
|
||||
};
|
||||
|
||||
range_or_multirange:
|
||||
range { $$ = $1; } |
|
||||
non_opt_multirange { $$ = $1; };
|
||||
|
||||
range_or_signed_int:
|
||||
range {
|
||||
$$ = $1;
|
||||
|
@ -566,7 +580,7 @@ wire_name_and_opt_assign:
|
|||
};
|
||||
|
||||
wire_name:
|
||||
TOK_ID range {
|
||||
TOK_ID range_or_multirange {
|
||||
AstNode *node = astbuf1->clone();
|
||||
node->str = *$1;
|
||||
append_attr_clone(node, albuf);
|
||||
|
@ -1007,8 +1021,8 @@ rvalue:
|
|||
$$->str = *$1;
|
||||
delete $1;
|
||||
} |
|
||||
hierarchical_id non_opt_range non_opt_range {
|
||||
$$ = new AstNode(AST_IDENTIFIER, $2, $3);
|
||||
hierarchical_id non_opt_multirange {
|
||||
$$ = new AstNode(AST_IDENTIFIER, $2);
|
||||
$$->str = *$1;
|
||||
delete $1;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue