3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2025-04-27 02:45:52 +00:00

Added "via_celltype" attribute on task/func

This commit is contained in:
Clifford Wolf 2014-08-18 14:29:30 +02:00
parent 6f33fc3e87
commit 640d9fc551
3 changed files with 110 additions and 18 deletions

View file

@ -1450,9 +1450,15 @@ skip_dynamic_range_lvalue_expansion:;
log_error("Can't resolve task name `%s' at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
}
AstNode *decl = current_scope[str];
std::stringstream sstr;
sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
std::string prefix = sstr.str();
bool recommend_const_eval = false;
bool require_const_eval = in_param ? false : has_const_only_constructs(recommend_const_eval);
if (in_param || recommend_const_eval || require_const_eval)
if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count("\\via_celltype"))
{
bool all_args_const = true;
for (auto child : children) {
@ -1474,11 +1480,6 @@ skip_dynamic_range_lvalue_expansion:;
log_error("Function %s can only be called with constant arguments at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
}
AstNode *decl = current_scope[str];
std::stringstream sstr;
sstr << "$func$" << str << "$" << filename << ":" << linenum << "$" << (autoidx++) << "$";
std::string prefix = sstr.str();
size_t arg_count = 0;
std::map<std::string, std::string> replace_rules;
@ -1510,6 +1511,68 @@ skip_dynamic_range_lvalue_expansion:;
goto replace_fcall_with_id;
}
if (decl->attributes.count("\\via_celltype"))
{
std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string();
std::string outport = str;
if (celltype.find(' ') != std::string::npos) {
int pos = celltype.find(' ');
outport = RTLIL::escape_id(celltype.substr(pos+1));
celltype = RTLIL::escape_id(celltype.substr(0, pos));
} else
celltype = RTLIL::escape_id(celltype);
AstNode *cell = new AstNode(AST_CELL, new AstNode(AST_CELLTYPE));
cell->str = prefix.substr(0, SIZE(prefix)-1);
cell->children[0]->str = celltype;
for (auto attr : decl->attributes)
if (attr.first.str().rfind("\\via_celltype_defparam_", 0) == 0)
{
AstNode *cell_arg = new AstNode(AST_PARASET, attr.second->clone());
cell_arg->str = RTLIL::escape_id(attr.first.str().substr(strlen("\\via_celltype_defparam_")));
cell->children.push_back(cell_arg);
}
for (auto child : decl->children)
if (child->type == AST_WIRE && (child->is_input || child->is_output || (type == AST_FCALL && child->str == str)))
{
AstNode *wire = child->clone();
wire->str = prefix + wire->str;
wire->port_id = 0;
wire->is_input = false;
wire->is_output = false;
current_ast_mod->children.push_back(wire);
while (wire->simplify(true, false, false, 1, -1, false, false)) { }
AstNode *wire_id = new AstNode(AST_IDENTIFIER);
wire_id->str = wire->str;
if ((child->is_input || child->is_output) && arg_count < children.size())
{
AstNode *arg = children[arg_count++]->clone();
AstNode *assign = child->is_input ?
new AstNode(AST_ASSIGN_EQ, wire_id, arg) :
new AstNode(AST_ASSIGN_EQ, arg, wire_id);
for (auto it = current_block->children.begin(); it != current_block->children.end(); it++) {
if (*it != current_block_child)
continue;
current_block->children.insert(it, assign);
break;
}
}
AstNode *cell_arg = new AstNode(AST_ARGUMENT, wire_id->clone());
cell_arg->str = child->str == str ? outport : child->str;
cell->children.push_back(cell_arg);
}
current_ast_mod->children.push_back(cell);
goto replace_fcall_with_id;
}
for (auto child : decl->children)
if (child->type == AST_WIRE)
{

View file

@ -407,33 +407,35 @@ module_body_stmt:
always_stmt | TOK_GENERATE module_gen_body TOK_ENDGENERATE | defattr | assert_property;
task_func_decl:
TOK_TASK TOK_ID ';' {
attr TOK_TASK TOK_ID ';' {
current_function_or_task = new AstNode(AST_TASK);
current_function_or_task->str = *$2;
current_function_or_task->str = *$3;
append_attr(current_function_or_task, $1);
ast_stack.back()->children.push_back(current_function_or_task);
ast_stack.push_back(current_function_or_task);
current_function_or_task_port_id = 1;
delete $2;
delete $3;
} task_func_body TOK_ENDTASK {
current_function_or_task = NULL;
ast_stack.pop_back();
} |
TOK_FUNCTION opt_signed range_or_signed_int TOK_ID ';' {
attr TOK_FUNCTION opt_signed range_or_signed_int TOK_ID ';' {
current_function_or_task = new AstNode(AST_FUNCTION);
current_function_or_task->str = *$4;
current_function_or_task->str = *$5;
append_attr(current_function_or_task, $1);
ast_stack.back()->children.push_back(current_function_or_task);
ast_stack.push_back(current_function_or_task);
AstNode *outreg = new AstNode(AST_WIRE);
outreg->str = *$4;
outreg->is_signed = $2;
if ($3 != NULL) {
outreg->children.push_back($3);
outreg->is_signed = $2 || $3->is_signed;
$3->is_signed = false;
outreg->str = *$5;
outreg->is_signed = $3;
if ($4 != NULL) {
outreg->children.push_back($4);
outreg->is_signed = $3 || $4->is_signed;
$4->is_signed = false;
}
current_function_or_task->children.push_back(outreg);
current_function_or_task_port_id = 1;
delete $4;
delete $5;
} task_func_body TOK_ENDFUNCTION {
current_function_or_task = NULL;
ast_stack.pop_back();