mirror of https://github.com/YosysHQ/yosys.git
Various improvements in support for generate statements
This commit is contained in:
parent
f4b46ed31e
commit
4a4a3fc337
|
@ -135,6 +135,7 @@ std::string AST::type2str(AstNodeType type)
|
|||
X(AST_GENVAR)
|
||||
X(AST_GENFOR)
|
||||
X(AST_GENIF)
|
||||
X(AST_GENCASE)
|
||||
X(AST_GENBLOCK)
|
||||
X(AST_POSEDGE)
|
||||
X(AST_NEGEDGE)
|
||||
|
@ -700,6 +701,15 @@ RTLIL::Const AstNode::asParaConst()
|
|||
return val;
|
||||
}
|
||||
|
||||
bool AstNode::asBool()
|
||||
{
|
||||
log_assert(type == AST_CONSTANT);
|
||||
for (auto &bit : bits)
|
||||
if (bit == RTLIL::State::S1)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
// create a new AstModule from an AST_MODULE AST node
|
||||
static AstModule* process_module(AstNode *ast)
|
||||
{
|
||||
|
|
|
@ -116,6 +116,7 @@ namespace AST
|
|||
AST_GENVAR,
|
||||
AST_GENFOR,
|
||||
AST_GENIF,
|
||||
AST_GENCASE,
|
||||
AST_GENBLOCK,
|
||||
|
||||
AST_POSEDGE,
|
||||
|
@ -218,6 +219,7 @@ namespace AST
|
|||
RTLIL::Const bitsAsConst(int width = -1);
|
||||
RTLIL::Const asAttrConst();
|
||||
RTLIL::Const asParaConst();
|
||||
bool asBool();
|
||||
};
|
||||
|
||||
// process an AST tree (ast must point to an AST_DESIGN node) and generate RTLIL code
|
||||
|
|
|
@ -812,6 +812,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
|
|||
case AST_GENFOR:
|
||||
case AST_GENBLOCK:
|
||||
case AST_GENIF:
|
||||
case AST_GENCASE:
|
||||
break;
|
||||
|
||||
// remember the parameter, needed for example in techmap
|
||||
|
|
|
@ -346,7 +346,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
bool did_something_here = true;
|
||||
if ((type == AST_GENFOR || type == AST_FOR) && i >= 3)
|
||||
break;
|
||||
if (type == AST_GENIF && i >= 1)
|
||||
if ((type == AST_GENIF || type == AST_GENCASE) && i >= 1)
|
||||
break;
|
||||
if (type == AST_GENBLOCK)
|
||||
break;
|
||||
|
@ -726,7 +726,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
// dumpAst(f, "verilog-ast> ");
|
||||
log_error("Condition for generate if at %s:%d is not constant!\n", filename.c_str(), linenum);
|
||||
}
|
||||
if (buf->integer != 0) {
|
||||
if (buf->asBool() != 0) {
|
||||
delete buf;
|
||||
buf = children[1]->clone();
|
||||
} else {
|
||||
|
@ -757,6 +757,82 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage,
|
|||
did_something = true;
|
||||
}
|
||||
|
||||
// simplify generate-case blocks
|
||||
if (type == AST_GENCASE && children.size() != 0)
|
||||
{
|
||||
AstNode *buf = children[0]->clone();
|
||||
while (buf->simplify(true, false, false, stage, width_hint, sign_hint)) { }
|
||||
if (buf->type != AST_CONSTANT) {
|
||||
// for (auto f : log_files)
|
||||
// dumpAst(f, "verilog-ast> ");
|
||||
log_error("Condition for generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
|
||||
}
|
||||
|
||||
bool ref_signed = buf->is_signed;
|
||||
RTLIL::Const ref_value = buf->bitsAsConst();
|
||||
delete buf;
|
||||
|
||||
AstNode *selected_case = NULL;
|
||||
for (size_t i = 1; i < children.size(); i++)
|
||||
{
|
||||
log_assert(children.at(i)->type == AST_COND);
|
||||
|
||||
AstNode *this_genblock = NULL;
|
||||
for (auto child : children.at(i)->children) {
|
||||
log_assert(this_genblock == NULL);
|
||||
if (child->type == AST_GENBLOCK)
|
||||
this_genblock = child;
|
||||
}
|
||||
|
||||
for (auto child : children.at(i)->children)
|
||||
{
|
||||
if (child->type == AST_DEFAULT) {
|
||||
if (selected_case == NULL)
|
||||
selected_case = this_genblock;
|
||||
continue;
|
||||
}
|
||||
if (child->type == AST_GENBLOCK)
|
||||
continue;
|
||||
|
||||
buf = child->clone();
|
||||
while (buf->simplify(true, false, false, stage, width_hint, sign_hint)) { }
|
||||
if (buf->type != AST_CONSTANT) {
|
||||
// for (auto f : log_files)
|
||||
// dumpAst(f, "verilog-ast> ");
|
||||
log_error("Expression in generate case at %s:%d is not constant!\n", filename.c_str(), linenum);
|
||||
}
|
||||
|
||||
if (RTLIL::const_eq(ref_value, buf->bitsAsConst(), ref_signed && buf->is_signed, ref_signed && buf->is_signed, 1).as_bool()) {
|
||||
selected_case = this_genblock;
|
||||
i = children.size();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (selected_case != NULL)
|
||||
{
|
||||
log_assert(selected_case->type == AST_GENBLOCK);
|
||||
buf = selected_case->clone();
|
||||
|
||||
if (!buf->str.empty()) {
|
||||
std::map<std::string, std::string> name_map;
|
||||
buf->expand_genblock(std::string(), buf->str + ".", name_map);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < buf->children.size(); i++) {
|
||||
buf->children[i]->simplify(false, false, false, stage, -1, false);
|
||||
current_ast_mod->children.push_back(buf->children[i]);
|
||||
}
|
||||
|
||||
buf->children.clear();
|
||||
delete buf;
|
||||
}
|
||||
|
||||
delete_children();
|
||||
did_something = true;
|
||||
}
|
||||
|
||||
// replace primitives with assignmens
|
||||
if (type == AST_PRIMITIVE)
|
||||
{
|
||||
|
|
|
@ -4,10 +4,12 @@ GENFILES += frontends/verilog/parser.tab.h
|
|||
GENFILES += frontends/verilog/parser.output
|
||||
GENFILES += frontends/verilog/lexer.cc
|
||||
|
||||
frontends/verilog/parser.tab.cc frontends/verilog/parser.tab.h: frontends/verilog/parser.y
|
||||
frontends/verilog/parser.tab.cc: frontends/verilog/parser.y
|
||||
bison -d -r all -b frontends/verilog/parser frontends/verilog/parser.y
|
||||
mv frontends/verilog/parser.tab.c frontends/verilog/parser.tab.cc
|
||||
|
||||
frontends/verilog/parser.tab.h: frontends/verilog/parser.tab.cc
|
||||
|
||||
frontends/verilog/lexer.cc: frontends/verilog/lexer.l
|
||||
flex -o frontends/verilog/lexer.cc frontends/verilog/lexer.l
|
||||
|
||||
|
|
|
@ -887,6 +887,22 @@ case_item:
|
|||
ast_stack.pop_back();
|
||||
};
|
||||
|
||||
gen_case_body:
|
||||
gen_case_body gen_case_item |
|
||||
/* empty */;
|
||||
|
||||
gen_case_item:
|
||||
{
|
||||
AstNode *node = new AstNode(AST_COND);
|
||||
ast_stack.back()->children.push_back(node);
|
||||
ast_stack.push_back(node);
|
||||
} case_select {
|
||||
case_type_stack.push_back(0);
|
||||
} gen_stmt_or_null {
|
||||
case_type_stack.pop_back();
|
||||
ast_stack.pop_back();
|
||||
};
|
||||
|
||||
case_select:
|
||||
case_expr_list ':' |
|
||||
TOK_DEFAULT;
|
||||
|
@ -956,7 +972,6 @@ single_arg:
|
|||
|
||||
module_gen_body:
|
||||
module_gen_body gen_stmt |
|
||||
module_gen_body module_body_stmt |
|
||||
/* empty */;
|
||||
|
||||
// this production creates the obligatory if-else shift/reduce conflict
|
||||
|
@ -967,7 +982,7 @@ gen_stmt:
|
|||
ast_stack.push_back(node);
|
||||
} simple_behavioral_stmt ';' expr {
|
||||
ast_stack.back()->children.push_back($6);
|
||||
} ';' simple_behavioral_stmt ')' gen_stmt {
|
||||
} ';' simple_behavioral_stmt ')' gen_stmt_block {
|
||||
ast_stack.pop_back();
|
||||
} |
|
||||
TOK_IF '(' expr ')' {
|
||||
|
@ -975,7 +990,15 @@ gen_stmt:
|
|||
ast_stack.back()->children.push_back(node);
|
||||
ast_stack.push_back(node);
|
||||
ast_stack.back()->children.push_back($3);
|
||||
} gen_stmt opt_gen_else {
|
||||
} gen_stmt_block opt_gen_else {
|
||||
ast_stack.pop_back();
|
||||
} |
|
||||
case_type '(' expr ')' {
|
||||
AstNode *node = new AstNode(AST_GENCASE, $3);
|
||||
ast_stack.back()->children.push_back(node);
|
||||
ast_stack.push_back(node);
|
||||
} gen_case_body TOK_ENDCASE {
|
||||
case_type_stack.pop_back();
|
||||
ast_stack.pop_back();
|
||||
} |
|
||||
TOK_BEGIN opt_label {
|
||||
|
@ -989,10 +1012,23 @@ gen_stmt:
|
|||
if ($6 != NULL)
|
||||
delete $6;
|
||||
ast_stack.pop_back();
|
||||
} |
|
||||
module_body_stmt;
|
||||
|
||||
gen_stmt_block:
|
||||
{
|
||||
AstNode *node = new AstNode(AST_GENBLOCK);
|
||||
ast_stack.back()->children.push_back(node);
|
||||
ast_stack.push_back(node);
|
||||
} gen_stmt {
|
||||
ast_stack.pop_back();
|
||||
};
|
||||
|
||||
gen_stmt_or_null:
|
||||
gen_stmt_block | ';';
|
||||
|
||||
opt_gen_else:
|
||||
TOK_ELSE gen_stmt | /* empty */;
|
||||
TOK_ELSE gen_stmt_or_null | /* empty */;
|
||||
|
||||
expr:
|
||||
basic_expr {
|
||||
|
|
|
@ -65,3 +65,30 @@ end
|
|||
|
||||
endmodule
|
||||
|
||||
// ------------------------------------------
|
||||
|
||||
module test3(a, b, sel, y, z);
|
||||
|
||||
input [3:0] a, b;
|
||||
input sel;
|
||||
output [3:0] y, z;
|
||||
|
||||
genvar i;
|
||||
generate
|
||||
for (i=0; i < 2; i=i+1)
|
||||
assign y[i] = sel ? a[i] : b[i], z[i] = sel ? b[i] : a[i];
|
||||
for (i=0; i < 2; i=i+1) begin
|
||||
if (i == 0)
|
||||
assign y[2] = sel ? a[2] : b[2];
|
||||
else
|
||||
assign z[2] = sel ? a[2] : b[2];
|
||||
case (i)
|
||||
default:
|
||||
assign z[3] = sel ? a[3] : b[3];
|
||||
0:
|
||||
assign y[3] = sel ? a[3] : b[3];
|
||||
endcase
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
|
Loading…
Reference in New Issue