diff options
Diffstat (limited to 'frontends/ast/simplify.cc')
-rw-r--r-- | frontends/ast/simplify.cc | 92 |
1 files changed, 68 insertions, 24 deletions
diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index cdb7e91e0..f629df387 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -91,7 +91,7 @@ std::string AstNode::process_format_str(const std::string &sformat, int next_arg case 'D': if (got_len) goto unsupported_format; - /* fall through */ + YS_FALLTHROUGH case 'x': case 'X': if (next_arg >= GetSize(children)) @@ -608,6 +608,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, case AST_TO_BITS: case AST_TO_SIGNED: case AST_TO_UNSIGNED: + case AST_SELFSZ: case AST_CONCAT: case AST_REPLICATE: case AST_REDUCE_AND: @@ -920,11 +921,11 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_swapped = templ->range_swapped; range_left = templ->range_left; range_right = templ->range_right; - attributes["\\wiretype"] = mkconst_str(resolved_type->str); + attributes[ID::wiretype] = mkconst_str(resolved_type->str); //check if enum - if (templ->attributes.count("\\enum_type")){ + if (templ->attributes.count(ID::enum_type)){ //get reference to enum node: - std::string enum_type = templ->attributes["\\enum_type"]->str.c_str(); + const std::string &enum_type = templ->attributes[ID::enum_type]->str; // log("enum_type=%s (count=%lu)\n", enum_type.c_str(), current_scope.count(enum_type)); // log("current scope:\n"); // for (auto &it : current_scope) @@ -972,7 +973,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, RTLIL::Const val = enum_item->children[0]->bitsAsConst(width, is_signed); enum_item_str.append(val.as_string()); //set attribute for available val to enum item name mappings - attributes[enum_item_str.c_str()] = mkconst_str(enum_item->str); + attributes[enum_item_str] = mkconst_str(enum_item->str); } } @@ -1021,7 +1022,7 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, range_swapped = templ->range_swapped; range_left = templ->range_left; range_right = templ->range_right; - attributes["\\wiretype"] = mkconst_str(resolved_type->str); + attributes[ID::wiretype] = mkconst_str(resolved_type->str); for (auto template_child : templ->children) children.push_back(template_child->clone()); did_something = true; @@ -1739,8 +1740,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *node = children_list[1]; if (op_type != AST_POS) - for (size_t i = 2; i < children_list.size(); i++) + for (size_t i = 2; i < children_list.size(); i++) { node = new AstNode(op_type, node, children_list[i]); + node->location = location; + } if (invert_results) node = new AstNode(AST_BIT_NOT, node); @@ -1786,7 +1789,18 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, result_width = abs(int(left_at_zero_ast->integer - right_at_zero_ast->integer)) + 1; } - if (0) + bool use_case_method = false; + + if (children[0]->id2ast->attributes.count(ID::nowrshmsk)) { + AstNode *node = children[0]->id2ast->attributes.at(ID::nowrshmsk); + while (node->simplify(true, false, false, stage, -1, false, false)) { } + if (node->type != AST_CONSTANT) + log_file_error(filename, location.first_line, "Non-constant value for `nowrshmsk' attribute on `%s'!\n", children[0]->id2ast->str.c_str()); + if (node->asAttrConst().as_bool()) + use_case_method = true; + } + + if (use_case_method) { // big case block @@ -1794,10 +1808,10 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, newNode = new AstNode(AST_CASE, shift_expr); for (int i = 0; i < source_width; i++) { int start_bit = children[0]->id2ast->range_right + i; + int end_bit = std::min(start_bit+result_width,source_width) - 1; AstNode *cond = new AstNode(AST_COND, mkconst_int(start_bit, true)); AstNode *lvalue = children[0]->clone(); lvalue->delete_children(); - int end_bit = std::min(start_bit+result_width,source_width) - 1; lvalue->children.push_back(new AstNode(AST_RANGE, mkconst_int(end_bit, true), mkconst_int(start_bit, true))); cond->children.push_back(new AstNode(AST_BLOCK, new AstNode(type, lvalue, children[1]->clone()))); @@ -1810,14 +1824,14 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *wire_mask = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); wire_mask->str = stringf("$bitselwrite$mask$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); - wire_mask->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_mask->attributes[ID::nosync] = AstNode::mkconst_int(1, false); wire_mask->is_logic = true; while (wire_mask->simplify(true, false, false, 1, -1, false, false)) { } current_ast_mod->children.push_back(wire_mask); AstNode *wire_data = new AstNode(AST_WIRE, new AstNode(AST_RANGE, mkconst_int(source_width-1, true), mkconst_int(0, true))); wire_data->str = stringf("$bitselwrite$data$%s:%d$%d", filename.c_str(), location.first_line, autoidx++); - wire_data->attributes["\\nosync"] = AstNode::mkconst_int(1, false); + wire_data->attributes[ID::nosync] = AstNode::mkconst_int(1, false); wire_data->is_logic = true; while (wire_data->simplify(true, false, false, 1, -1, false, false)) { } current_ast_mod->children.push_back(wire_data); @@ -1844,11 +1858,40 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, AstNode *shamt = shift_expr; - newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), - new AstNode(AST_SHIFT_LEFT, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), shamt->clone()))); - newNode->children.push_back(new AstNode(AST_ASSIGN_EQ, ref_data->clone(), - new AstNode(AST_SHIFT_LEFT, new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()), shamt))); - newNode->children.push_back(new AstNode(type, lvalue, new AstNode(AST_BIT_OR, new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)), ref_data))); + int shamt_width_hint = 0; + bool shamt_sign_hint = true; + shamt->detectSignWidth(shamt_width_hint, shamt_sign_hint); + + int start_bit = children[0]->id2ast->range_right; + bool use_shift = shamt_sign_hint; + + if (start_bit != 0) { + shamt = new AstNode(AST_SUB, shamt, mkconst_int(start_bit, true)); + use_shift = true; + } + + AstNode *t; + + t = mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false); + if (use_shift) + t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt->clone())); + else + t = new AstNode(AST_SHIFT_LEFT, t, shamt->clone()); + t = new AstNode(AST_ASSIGN_EQ, ref_mask->clone(), t); + newNode->children.push_back(t); + + t = new AstNode(AST_BIT_AND, mkconst_bits(std::vector<RTLIL::State>(result_width, State::S1), false), children[1]->clone()); + if (use_shift) + t = new AstNode(AST_SHIFT, t, new AstNode(AST_NEG, shamt)); + else + t = new AstNode(AST_SHIFT_LEFT, t, shamt); + t = new AstNode(AST_ASSIGN_EQ, ref_data->clone(), t); + newNode->children.push_back(t); + + t = new AstNode(AST_BIT_AND, old_data, new AstNode(AST_BIT_NOT, ref_mask)); + t = new AstNode(AST_BIT_OR, t, ref_data); + t = new AstNode(type, lvalue, t); + newNode->children.push_back(t); } goto apply_newNode; @@ -2637,7 +2680,7 @@ skip_dynamic_range_lvalue_expansion:; 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) && !decl->attributes.count("\\via_celltype")) + if ((in_param || recommend_const_eval || require_const_eval) && !decl->attributes.count(ID::via_celltype)) { bool all_args_const = true; for (auto child : children) { @@ -2696,9 +2739,9 @@ skip_dynamic_range_lvalue_expansion:; goto replace_fcall_with_id; } - if (decl->attributes.count("\\via_celltype")) + if (decl->attributes.count(ID::via_celltype)) { - std::string celltype = decl->attributes.at("\\via_celltype")->asAttrConst().decode_string(); + std::string celltype = decl->attributes.at(ID::via_celltype)->asAttrConst().decode_string(); std::string outport = str; if (celltype.find(' ') != std::string::npos) { @@ -2792,7 +2835,7 @@ skip_dynamic_range_lvalue_expansion:; wire->is_reg = true; wire->attributes[ID::nosync] = AstNode::mkconst_int(1, false); if (child->type == AST_ENUM_ITEM) - wire->attributes["\\enum_base_type"] = child->attributes["\\enum_base_type"]; + wire->attributes[ID::enum_base_type] = child->attributes[ID::enum_base_type]; wire_cache[child->str] = wire; @@ -3024,6 +3067,7 @@ replace_fcall_later:; } } break; + if (0) { case AST_SELFSZ: const_func = RTLIL::const_pos; } if (0) { case AST_POS: const_func = RTLIL::const_pos; } if (0) { case AST_NEG: const_func = RTLIL::const_neg; } if (children[0]->type == AST_CONSTANT) { @@ -3032,10 +3076,10 @@ replace_fcall_later:; } else if (children[0]->isConst()) { newNode = new AstNode(AST_REALVALUE); - if (type == AST_POS) - newNode->realvalue = +children[0]->asReal(sign_hint); - else + if (type == AST_NEG) newNode->realvalue = -children[0]->asReal(sign_hint); + else + newNode->realvalue = +children[0]->asReal(sign_hint); } break; case AST_TERNARY: @@ -4092,7 +4136,7 @@ void AstNode::allocateDefaultEnumValues() int last_enum_int = -1; for (auto node : children) { log_assert(node->type==AST_ENUM_ITEM); - node->attributes["\\enum_base_type"] = mkconst_str(str); + node->attributes[ID::enum_base_type] = mkconst_str(str); for (size_t i = 0; i < node->children.size(); i++) { switch (node->children[i]->type) { case AST_NONE: |