mirror of https://github.com/YosysHQ/yosys.git
sv: Add support for memory typedefs
Signed-off-by: David Shah <dave@ds0.me>
This commit is contained in:
parent
e70e4afb60
commit
30d2326030
|
@ -785,8 +785,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
// resolve typedefs
|
// resolve typedefs
|
||||||
if (type == AST_TYPEDEF) {
|
if (type == AST_TYPEDEF) {
|
||||||
log_assert(children.size() == 1);
|
log_assert(children.size() == 1);
|
||||||
log_assert(children[0]->type == AST_WIRE);
|
log_assert(children[0]->type == AST_WIRE || children[0]->type == AST_MEMORY);
|
||||||
while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
while(children[0]->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {
|
||||||
|
did_something = true;
|
||||||
|
};
|
||||||
log_assert(!children[0]->is_custom_type);
|
log_assert(!children[0]->is_custom_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -807,6 +809,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
// Ensure typedef itself is fully simplified
|
// Ensure typedef itself is fully simplified
|
||||||
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
||||||
|
|
||||||
|
type = templ->type;
|
||||||
is_reg = templ->is_reg;
|
is_reg = templ->is_reg;
|
||||||
is_logic = templ->is_logic;
|
is_logic = templ->is_logic;
|
||||||
is_signed = templ->is_signed;
|
is_signed = templ->is_signed;
|
||||||
|
@ -819,6 +822,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
range_right = templ->range_right;
|
range_right = templ->range_right;
|
||||||
for (auto template_child : templ->children)
|
for (auto template_child : templ->children)
|
||||||
children.push_back(template_child->clone());
|
children.push_back(template_child->clone());
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
log_assert(!is_custom_type);
|
log_assert(!is_custom_type);
|
||||||
}
|
}
|
||||||
|
@ -841,6 +845,8 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
// Ensure typedef itself is fully simplified
|
// Ensure typedef itself is fully simplified
|
||||||
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
while(templ->simplify(const_fold, at_zero, in_lvalue, stage, width_hint, sign_hint, in_param)) {};
|
||||||
|
|
||||||
|
if (templ->type == AST_MEMORY)
|
||||||
|
log_file_error(filename, linenum, "unpacked array type `%s' cannot be used for a parameter\n", children[1]->str.c_str());
|
||||||
is_signed = templ->is_signed;
|
is_signed = templ->is_signed;
|
||||||
is_string = templ->is_string;
|
is_string = templ->is_string;
|
||||||
is_custom_type = templ->is_custom_type;
|
is_custom_type = templ->is_custom_type;
|
||||||
|
@ -851,6 +857,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
||||||
range_right = templ->range_right;
|
range_right = templ->range_right;
|
||||||
for (auto template_child : templ->children)
|
for (auto template_child : templ->children)
|
||||||
children.push_back(template_child->clone());
|
children.push_back(template_child->clone());
|
||||||
|
did_something = true;
|
||||||
}
|
}
|
||||||
log_assert(!is_custom_type);
|
log_assert(!is_custom_type);
|
||||||
}
|
}
|
||||||
|
@ -3074,6 +3081,9 @@ void AstNode::mem2reg_as_needed_pass1(dict<AstNode*, pool<std::string>> &mem2reg
|
||||||
uint32_t children_flags = 0;
|
uint32_t children_flags = 0;
|
||||||
int lhs_children_counter = 0;
|
int lhs_children_counter = 0;
|
||||||
|
|
||||||
|
if (type == AST_TYPEDEF)
|
||||||
|
return; // don't touch content of typedefs
|
||||||
|
|
||||||
if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
|
if (type == AST_ASSIGN || type == AST_ASSIGN_LE || type == AST_ASSIGN_EQ)
|
||||||
{
|
{
|
||||||
// mark all memories that are used in a complex expression on the left side of an assignment
|
// mark all memories that are used in a complex expression on the left side of an assignment
|
||||||
|
@ -3231,6 +3241,9 @@ bool AstNode::mem2reg_as_needed_pass2(pool<AstNode*> &mem2reg_set, AstNode *mod,
|
||||||
if (type == AST_FUNCTION || type == AST_TASK)
|
if (type == AST_FUNCTION || type == AST_TASK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (type == AST_TYPEDEF)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
|
if (type == AST_MEMINIT && id2ast && mem2reg_set.count(id2ast))
|
||||||
{
|
{
|
||||||
log_assert(children[0]->type == AST_CONSTANT);
|
log_assert(children[0]->type == AST_CONSTANT);
|
||||||
|
|
|
@ -1400,7 +1400,7 @@ assign_expr:
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef_decl:
|
typedef_decl:
|
||||||
TOK_TYPEDEF wire_type range TOK_ID ';' {
|
TOK_TYPEDEF wire_type range TOK_ID range_or_multirange ';' {
|
||||||
astbuf1 = $2;
|
astbuf1 = $2;
|
||||||
astbuf2 = $3;
|
astbuf2 = $3;
|
||||||
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
if (astbuf1->range_left >= 0 && astbuf1->range_right >= 0) {
|
||||||
|
@ -1416,6 +1416,24 @@ typedef_decl:
|
||||||
frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
|
frontend_verilog_yyerror("wire/reg/logic packed dimension must be of the form: [<expr>:<expr>], [<expr>+:<expr>], or [<expr>-:<expr>]");
|
||||||
if (astbuf2)
|
if (astbuf2)
|
||||||
astbuf1->children.push_back(astbuf2);
|
astbuf1->children.push_back(astbuf2);
|
||||||
|
|
||||||
|
if ($5 != NULL) {
|
||||||
|
if (!astbuf2) {
|
||||||
|
AstNode *rng = new AstNode(AST_RANGE);
|
||||||
|
rng->children.push_back(AstNode::mkconst_int(0, true));
|
||||||
|
rng->children.push_back(AstNode::mkconst_int(0, true));
|
||||||
|
astbuf1->children.push_back(rng);
|
||||||
|
}
|
||||||
|
astbuf1->type = AST_MEMORY;
|
||||||
|
auto *rangeNode = $5;
|
||||||
|
if (rangeNode->type == AST_RANGE && rangeNode->children.size() == 1) {
|
||||||
|
// SV array size [n], rewrite as [n-1:0]
|
||||||
|
rangeNode->children[0] = new AstNode(AST_SUB, rangeNode->children[0], AstNode::mkconst_int(1, true));
|
||||||
|
rangeNode->children.push_back(AstNode::mkconst_int(0, false));
|
||||||
|
}
|
||||||
|
astbuf1->children.push_back(rangeNode);
|
||||||
|
}
|
||||||
|
|
||||||
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
|
ast_stack.back()->children.push_back(new AstNode(AST_TYPEDEF, astbuf1));
|
||||||
ast_stack.back()->children.back()->str = *$4;
|
ast_stack.back()->children.back()->str = *$4;
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
module top(input [3:0] addr, wdata, input clk, wen, output reg [3:0] rdata);
|
||||||
|
typedef logic [3:0] ram16x4_t[0:15];
|
||||||
|
|
||||||
|
ram16x4_t mem;
|
||||||
|
|
||||||
|
always @(posedge clk) begin
|
||||||
|
if (wen) mem[addr] <= wdata;
|
||||||
|
rdata <= mem[addr];
|
||||||
|
end
|
||||||
|
endmodule
|
Loading…
Reference in New Issue