mirror of https://github.com/YosysHQ/yosys.git
Fixed handling of boolean attributes (frontends)
This commit is contained in:
parent
eae43e2db4
commit
23cf23418c
|
@ -145,6 +145,20 @@ std::string AST::type2str(AstNodeType type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// check if attribute exists and has non-zero value
|
||||||
|
bool AstNode::get_bool_attribute(RTLIL::IdString id)
|
||||||
|
{
|
||||||
|
if (attributes.count(id) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AstNode *attr = attributes.at(id);
|
||||||
|
if (attr->type != AST_CONSTANT)
|
||||||
|
log_error("Attribute `%s' with non-constant value at %s:%d!\n",
|
||||||
|
id.c_str(), attr->filename.c_str(), attr->linenum);
|
||||||
|
|
||||||
|
return attr->integer != 0;
|
||||||
|
}
|
||||||
|
|
||||||
// create new node (AstNode constructor)
|
// create new node (AstNode constructor)
|
||||||
// (the optional child arguments make it easier to create AST trees)
|
// (the optional child arguments make it easier to create AST trees)
|
||||||
AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
|
AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2)
|
||||||
|
@ -670,7 +684,7 @@ static AstModule* process_module(AstNode *ast)
|
||||||
delete child;
|
delete child;
|
||||||
}
|
}
|
||||||
ast->children.swap(new_children);
|
ast->children.swap(new_children);
|
||||||
ast->attributes["\\placeholder"] = AstNode::mkconst_int(0, false, 0);
|
ast->attributes["\\placeholder"] = AstNode::mkconst_int(1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
current_module = new AstModule;
|
current_module = new AstModule;
|
||||||
|
|
|
@ -137,6 +137,7 @@ namespace AST
|
||||||
|
|
||||||
// the list of attributes assigned to this node
|
// the list of attributes assigned to this node
|
||||||
std::map<RTLIL::IdString, AstNode*> attributes;
|
std::map<RTLIL::IdString, AstNode*> attributes;
|
||||||
|
bool get_bool_attribute(RTLIL::IdString id);
|
||||||
|
|
||||||
// node content - most of it is unused in most node types
|
// node content - most of it is unused in most node types
|
||||||
std::string str;
|
std::string str;
|
||||||
|
|
|
@ -260,7 +260,7 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
}
|
}
|
||||||
|
|
||||||
// create initial assignments for the temporary signals
|
// create initial assignments for the temporary signals
|
||||||
if ((flag_nolatches || always->attributes.count("\\nolatches") > 0 || current_module->attributes.count("\\nolatches")) && !found_clocked_sync) {
|
if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) {
|
||||||
subst_rvalue_from = subst_lvalue_from;
|
subst_rvalue_from = subst_lvalue_from;
|
||||||
subst_rvalue_to = RTLIL::SigSpec(RTLIL::State::Sx, subst_rvalue_from.width);
|
subst_rvalue_to = RTLIL::SigSpec(RTLIL::State::Sx, subst_rvalue_from.width);
|
||||||
} else {
|
} else {
|
||||||
|
@ -366,7 +366,7 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
for (size_t i = 0; i < lvalue.chunks.size(); i++) {
|
for (size_t i = 0; i < lvalue.chunks.size(); i++) {
|
||||||
RTLIL::SigSpec lhs = lvalue.chunks[i];
|
RTLIL::SigSpec lhs = lvalue.chunks[i];
|
||||||
RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue.chunks[i].width);
|
RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue.chunks[i].width);
|
||||||
if (inSyncRule && lvalue.chunks[i].wire && lvalue.chunks[i].wire->attributes.count("\\nosync"))
|
if (inSyncRule && lvalue.chunks[i].wire && lvalue.chunks[i].wire->get_bool_attribute("\\nosync"))
|
||||||
rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.width);
|
rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.width);
|
||||||
actions.push_back(RTLIL::SigSig(lhs, rhs));
|
actions.push_back(RTLIL::SigSig(lhs, rhs));
|
||||||
offset += lhs.width;
|
offset += lhs.width;
|
||||||
|
@ -468,7 +468,7 @@ struct AST_INTERNAL::ProcessGenerator
|
||||||
current_case = backup_case;
|
current_case = backup_case;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (last_generated_case != NULL && ast->attributes.count("\\full_case") > 0) {
|
if (last_generated_case != NULL && ast->get_bool_attribute("\\full_case")) {
|
||||||
last_generated_case->compare.clear();
|
last_generated_case->compare.clear();
|
||||||
} else if (!generated_default_case) {
|
} else if (!generated_default_case) {
|
||||||
RTLIL::CaseRule *default_case = new RTLIL::CaseRule;
|
RTLIL::CaseRule *default_case = new RTLIL::CaseRule;
|
||||||
|
|
|
@ -54,7 +54,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage)
|
||||||
|
|
||||||
while (simplify(const_fold, at_zero, in_lvalue, 1)) { }
|
while (simplify(const_fold, at_zero, in_lvalue, 1)) { }
|
||||||
|
|
||||||
if (!flag_nomem2reg && attributes.count("\\nomem2reg") == 0)
|
if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg"))
|
||||||
{
|
{
|
||||||
std::set<AstNode*> mem2reg_set, mem2reg_candidates;
|
std::set<AstNode*> mem2reg_set, mem2reg_candidates;
|
||||||
mem2reg_as_needed_pass1(mem2reg_set, mem2reg_candidates, false, false, flag_mem2reg);
|
mem2reg_as_needed_pass1(mem2reg_set, mem2reg_candidates, false, false, flag_mem2reg);
|
||||||
|
@ -999,7 +999,7 @@ void AstNode::mem2reg_as_needed_pass1(std::set<AstNode*> &mem2reg_set, std::set<
|
||||||
{
|
{
|
||||||
if ((type == AST_ASSIGN_LE && async_proc) || (type == AST_ASSIGN_EQ && (sync_proc || async_proc)))
|
if ((type == AST_ASSIGN_LE && async_proc) || (type == AST_ASSIGN_EQ && (sync_proc || async_proc)))
|
||||||
if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY &&
|
if (children[0]->type == AST_IDENTIFIER && children[0]->id2ast && children[0]->id2ast->type == AST_MEMORY &&
|
||||||
children[0]->id2ast->attributes.count("\\nomem2reg") == 0) {
|
!children[0]->id2ast->get_bool_attribute("\\nomem2reg")) {
|
||||||
if (async_proc || mem2reg_candidates.count(children[0]->id2ast) > 0) {
|
if (async_proc || mem2reg_candidates.count(children[0]->id2ast) > 0) {
|
||||||
if (mem2reg_set.count(children[0]->id2ast) == 0)
|
if (mem2reg_set.count(children[0]->id2ast) == 0)
|
||||||
log("Warning: Replacing memory %s with list of registers because of assignment in line %s:%d.\n",
|
log("Warning: Replacing memory %s with list of registers because of assignment in line %s:%d.\n",
|
||||||
|
@ -1009,10 +1009,10 @@ void AstNode::mem2reg_as_needed_pass1(std::set<AstNode*> &mem2reg_set, std::set<
|
||||||
mem2reg_candidates.insert(children[0]->id2ast);
|
mem2reg_candidates.insert(children[0]->id2ast);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == AST_MEMORY && (attributes.count("\\mem2reg") > 0 || force_mem2reg))
|
if (type == AST_MEMORY && (get_bool_attribute("\\mem2reg") || force_mem2reg))
|
||||||
mem2reg_set.insert(this);
|
mem2reg_set.insert(this);
|
||||||
|
|
||||||
if (type == AST_MODULE && attributes.count("\\mem2reg") > 0)
|
if (type == AST_MODULE && get_bool_attribute("\\mem2reg"))
|
||||||
force_mem2reg = true;
|
force_mem2reg = true;
|
||||||
|
|
||||||
if (type == AST_ALWAYS) {
|
if (type == AST_ALWAYS) {
|
||||||
|
@ -1046,13 +1046,13 @@ void AstNode::mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *
|
||||||
AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
|
AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
|
||||||
wire_addr->str = id_addr;
|
wire_addr->str = id_addr;
|
||||||
wire_addr->is_reg = true;
|
wire_addr->is_reg = true;
|
||||||
wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(0, false, 0);
|
wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
mod->children.push_back(wire_addr);
|
mod->children.push_back(wire_addr);
|
||||||
|
|
||||||
AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
||||||
wire_data->str = id_data;
|
wire_data->str = id_data;
|
||||||
wire_data->is_reg = true;
|
wire_data->is_reg = true;
|
||||||
wire_data->attributes["\\nosync"] = AstNode::mkconst_int(0, false, 0);
|
wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
mod->children.push_back(wire_data);
|
mod->children.push_back(wire_data);
|
||||||
|
|
||||||
assert(block != NULL);
|
assert(block != NULL);
|
||||||
|
@ -1097,12 +1097,12 @@ void AstNode::mem2reg_as_needed_pass2(std::set<AstNode*> &mem2reg_set, AstNode *
|
||||||
|
|
||||||
AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
|
AstNode *wire_addr = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(addr_bits-1, true), mkconst_int(0, true)));
|
||||||
wire_addr->str = id_addr;
|
wire_addr->str = id_addr;
|
||||||
wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(0, false, 0);
|
wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
mod->children.push_back(wire_addr);
|
mod->children.push_back(wire_addr);
|
||||||
|
|
||||||
AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(mem_width-1, true), mkconst_int(0, true)));
|
||||||
wire_data->str = id_data;
|
wire_data->str = id_data;
|
||||||
wire_data->attributes["\\nosync"] = AstNode::mkconst_int(0, false, 0);
|
wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false);
|
||||||
mod->children.push_back(wire_data);
|
mod->children.push_back(wire_data);
|
||||||
|
|
||||||
AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
|
AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone());
|
||||||
|
|
|
@ -776,11 +776,11 @@ case_type:
|
||||||
opt_synopsys_attr:
|
opt_synopsys_attr:
|
||||||
opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE {
|
opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE {
|
||||||
if (ast_stack.back()->attributes.count("\\full_case") == 0)
|
if (ast_stack.back()->attributes.count("\\full_case") == 0)
|
||||||
ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(0, false, 0);
|
ast_stack.back()->attributes["\\full_case"] = AstNode::mkconst_int(1, false);
|
||||||
} |
|
} |
|
||||||
opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE {
|
opt_synopsys_attr TOK_SYNOPSYS_PARALLEL_CASE {
|
||||||
if (ast_stack.back()->attributes.count("\\parallel_case") == 0)
|
if (ast_stack.back()->attributes.count("\\parallel_case") == 0)
|
||||||
ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(0, false, 0);
|
ast_stack.back()->attributes["\\parallel_case"] = AstNode::mkconst_int(1, false);
|
||||||
} |
|
} |
|
||||||
/* empty */;
|
/* empty */;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue