From 23cf23418cd28b98c11a1ed3fb45dbb927f48e65 Mon Sep 17 00:00:00 2001 From: Clifford Wolf Date: Thu, 24 Oct 2013 11:20:13 +0200 Subject: [PATCH] Fixed handling of boolean attributes (frontends) --- frontends/ast/ast.cc | 16 +++++++++++++++- frontends/ast/ast.h | 1 + frontends/ast/genrtlil.cc | 6 +++--- frontends/ast/simplify.cc | 16 ++++++++-------- frontends/verilog/parser.y | 4 ++-- 5 files changed, 29 insertions(+), 14 deletions(-) diff --git a/frontends/ast/ast.cc b/frontends/ast/ast.cc index f589f0c17..df30c6d95 100644 --- a/frontends/ast/ast.cc +++ b/frontends/ast/ast.cc @@ -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) // (the optional child arguments make it easier to create AST trees) AstNode::AstNode(AstNodeType type, AstNode *child1, AstNode *child2) @@ -670,7 +684,7 @@ static AstModule* process_module(AstNode *ast) delete child; } 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; diff --git a/frontends/ast/ast.h b/frontends/ast/ast.h index 039b929f7..504ec5f2d 100644 --- a/frontends/ast/ast.h +++ b/frontends/ast/ast.h @@ -137,6 +137,7 @@ namespace AST // the list of attributes assigned to this node std::map attributes; + bool get_bool_attribute(RTLIL::IdString id); // node content - most of it is unused in most node types std::string str; diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index 6ea07652b..8b122a7a5 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -260,7 +260,7 @@ struct AST_INTERNAL::ProcessGenerator } // 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_to = RTLIL::SigSpec(RTLIL::State::Sx, subst_rvalue_from.width); } else { @@ -366,7 +366,7 @@ struct AST_INTERNAL::ProcessGenerator for (size_t i = 0; i < lvalue.chunks.size(); i++) { RTLIL::SigSpec lhs = lvalue.chunks[i]; 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); actions.push_back(RTLIL::SigSig(lhs, rhs)); offset += lhs.width; @@ -468,7 +468,7 @@ struct AST_INTERNAL::ProcessGenerator 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(); } else if (!generated_default_case) { RTLIL::CaseRule *default_case = new RTLIL::CaseRule; diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 5f0e68677..a8c4d01ce 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -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)) { } - if (!flag_nomem2reg && attributes.count("\\nomem2reg") == 0) + if (!flag_nomem2reg && !get_bool_attribute("\\nomem2reg")) { std::set mem2reg_set, mem2reg_candidates; mem2reg_as_needed_pass1(mem2reg_set, mem2reg_candidates, false, false, flag_mem2reg); @@ -999,7 +999,7 @@ void AstNode::mem2reg_as_needed_pass1(std::set &mem2reg_set, std::set< { 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 && - 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 (mem2reg_set.count(children[0]->id2ast) == 0) 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 &mem2reg_set, std::set< 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); - if (type == AST_MODULE && attributes.count("\\mem2reg") > 0) + if (type == AST_MODULE && get_bool_attribute("\\mem2reg")) force_mem2reg = true; if (type == AST_ALWAYS) { @@ -1046,13 +1046,13 @@ void AstNode::mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode * 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->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); 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->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); assert(block != NULL); @@ -1097,12 +1097,12 @@ void AstNode::mem2reg_as_needed_pass2(std::set &mem2reg_set, AstNode * 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->attributes["\\nosync"] = AstNode::mkconst_int(0, false, 0); + wire_addr->attributes["\\nosync"] = AstNode::mkconst_int(1, false); 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))); 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); AstNode *assign_addr = new AstNode(AST_ASSIGN_EQ, new AstNode(AST_IDENTIFIER), children[0]->children[0]->clone()); diff --git a/frontends/verilog/parser.y b/frontends/verilog/parser.y index 59d0a5700..35e225179 100644 --- a/frontends/verilog/parser.y +++ b/frontends/verilog/parser.y @@ -776,11 +776,11 @@ case_type: opt_synopsys_attr: opt_synopsys_attr TOK_SYNOPSYS_FULL_CASE { 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 { 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 */; -- 2.30.2