Renamed extend() to extend_xx(), changed most users to extend_u0()
[yosys.git] / frontends / ast / genrtlil.cc
index 506c2bb259c4ef1aa425ffb1eb4858082b2c6382..238da2634a9d4b793b3324757cad6e214fe80aa9 100644 (file)
@@ -70,17 +70,17 @@ static RTLIL::SigSpec uniop2rtlil(AstNode *that, std::string type, int result_wi
 }
 
 // helper function for extending bit width (preferred over SigSpec::extend() because of correct undef propagation in ConstEval)
-static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed, std::string celltype)
+static void widthExtend(AstNode *that, RTLIL::SigSpec &sig, int width, bool is_signed)
 {
        if (width <= sig.size()) {
-               sig.extend(width, is_signed);
+               sig.extend_u0(width, is_signed);
                return;
        }
 
        std::stringstream sstr;
        sstr << "$extend" << "$" << that->filename << ":" << that->linenum << "$" << (autoidx++);
 
-       RTLIL::Cell *cell = current_module->addCell(sstr.str(), celltype);
+       RTLIL::Cell *cell = current_module->addCell(sstr.str(), "$pos");
        cell->attributes["\\src"] = stringf("%s:%d", that->filename.c_str(), that->linenum);
 
        RTLIL::Wire *wire = current_module->addWire(cell->name.str() + "_Y", width);
@@ -254,7 +254,7 @@ struct AST_INTERNAL::ProcessGenerator
 
                // create initial assignments for the temporary signals
                if ((flag_nolatches || always->get_bool_attribute("\\nolatches") || current_module->get_bool_attribute("\\nolatches")) && !found_clocked_sync) {
-                       subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, SIZE(subst_lvalue_from)));
+                       subst_rvalue_map = subst_lvalue_from.to_sigbit_map(RTLIL::SigSpec(RTLIL::State::Sx, GetSize(subst_lvalue_from)));
                } else {
                        addChunkActions(current_case->actions, subst_lvalue_to, subst_lvalue_from);
                }
@@ -276,6 +276,7 @@ struct AST_INTERNAL::ProcessGenerator
                        for (auto &init_lvalue_c : init_lvalue.chunks()) {
                                RTLIL::SigSpec lhs = init_lvalue_c;
                                RTLIL::SigSpec rhs = init_rvalue.extract(offset, init_lvalue_c.width);
+                               remove_unwanted_lvalue_bits(lhs, rhs);
                                sync->actions.push_back(RTLIL::SigSig(lhs, rhs));
                                offset += lhs.size();
                        }
@@ -284,12 +285,28 @@ struct AST_INTERNAL::ProcessGenerator
                outputSignals = RTLIL::SigSpec(subst_lvalue_from);
        }
 
+       void remove_unwanted_lvalue_bits(RTLIL::SigSpec &lhs, RTLIL::SigSpec &rhs)
+       {
+               RTLIL::SigSpec new_lhs, new_rhs;
+
+               log_assert(GetSize(lhs) == GetSize(rhs));
+               for (int i = 0; i < GetSize(lhs); i++) {
+                       if (lhs[i].wire == nullptr)
+                               continue;
+                       new_lhs.append(lhs[i]);
+                       new_rhs.append(rhs[i]);
+               }
+
+               lhs = new_lhs;
+               rhs = new_rhs;
+       }
+
        // create new temporary signals
        RTLIL::SigSpec new_temp_signal(RTLIL::SigSpec sig)
        {
                std::vector<RTLIL::SigChunk> chunks = sig.chunks();
 
-               for (int i = 0; i < SIZE(chunks); i++)
+               for (int i = 0; i < GetSize(chunks); i++)
                {
                        RTLIL::SigChunk &chunk = chunks[i];
                        if (chunk.wire == NULL)
@@ -349,8 +366,13 @@ struct AST_INTERNAL::ProcessGenerator
                        log_abort();
                }
 
-               if (run_sort_and_unify)
-                       reg.sort_and_unify();
+               if (run_sort_and_unify) {
+                       std::set<RTLIL::SigBit> sorted_reg;
+                       for (auto bit : reg)
+                               if (bit.wire)
+                                       sorted_reg.insert(bit);
+                       reg = RTLIL::SigSpec(sorted_reg);
+               }
        }
 
        // remove all assignments to the given signal pattern in a case and all its children.
@@ -384,6 +406,7 @@ struct AST_INTERNAL::ProcessGenerator
                        RTLIL::SigSpec rhs = rvalue.extract(offset, lvalue_c.width);
                        if (inSyncRule && lvalue_c.wire && lvalue_c.wire->get_bool_attribute("\\nosync"))
                                rhs = RTLIL::SigSpec(RTLIL::State::Sx, rhs.size());
+                       remove_unwanted_lvalue_bits(lhs, rhs);
                        actions.push_back(RTLIL::SigSig(lhs, rhs));
                        offset += lhs.size();
                }
@@ -407,11 +430,12 @@ struct AST_INTERNAL::ProcessGenerator
                                lvalue.replace(subst_lvalue_map.stdmap());
 
                                if (ast->type == AST_ASSIGN_EQ) {
-                                       for (int i = 0; i < SIZE(unmapped_lvalue); i++)
+                                       for (int i = 0; i < GetSize(unmapped_lvalue); i++)
                                                subst_rvalue_map.set(unmapped_lvalue[i], rvalue[i]);
                                }
 
                                removeSignalFromCaseTree(lvalue.to_sigbit_set(), current_case);
+                               remove_unwanted_lvalue_bits(lvalue, rvalue);
                                current_case->actions.push_back(RTLIL::SigSig(lvalue, rvalue));
                        }
                        break;
@@ -448,7 +472,7 @@ struct AST_INTERNAL::ProcessGenerator
                                        subst_lvalue_map.save();
                                        subst_rvalue_map.save();
 
-                                       for (int i = 0; i < SIZE(this_case_eq_lvalue); i++)
+                                       for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
                                                subst_lvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
 
                                        RTLIL::CaseRule *backup_case = current_case;
@@ -483,7 +507,7 @@ struct AST_INTERNAL::ProcessGenerator
                                        sw->cases.push_back(default_case);
                                }
 
-                               for (int i = 0; i < SIZE(this_case_eq_lvalue); i++)
+                               for (int i = 0; i < GetSize(this_case_eq_lvalue); i++)
                                        subst_rvalue_map.set(this_case_eq_lvalue[i], this_case_eq_ltemp[i]);
 
                                this_case_eq_lvalue.replace(subst_lvalue_map.stdmap());
@@ -845,7 +869,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
        case AST_REALVALUE:
                {
                        RTLIL::SigSpec sig = realAsConst(width_hint);
-                       log("Warning: converting real value %e to binary %s at %s:%d.\n",
+                       log_warning("converting real value %e to binary %s at %s:%d.\n",
                                        realvalue, log_signal(sig), filename.c_str(), linenum);
                        return sig;
                }
@@ -866,7 +890,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                wire->attributes["\\src"] = stringf("%s:%d", filename.c_str(), linenum);
                                wire->name = str;
                                if (flag_autowire)
-                                       log("Warning: Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
+                                       log_warning("Identifier `%s' is implicitly declared at %s:%d.\n", str.c_str(), filename.c_str(), linenum);
                                else
                                        log_error("Identifier `%s' is implicitly declared at %s:%d and `default_nettype is set to none.\n", str.c_str(), filename.c_str(), linenum);
                        }
@@ -917,7 +941,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                                shift_val = current_module->Sub(NEW_ID, RTLIL::SigSpec(source_width - width), shift_val, fake_ast->children[1]->is_signed);
                                                fake_ast->children[1]->is_signed = true;
                                        }
-                                       if (SIZE(shift_val) >= 32)
+                                       if (GetSize(shift_val) >= 32)
                                                fake_ast->children[1]->is_signed = true;
                                        RTLIL::SigSpec sig = binop2rtlil(fake_ast, "$shiftx", width, fake_ast->children[0]->genRTLIL(), shift_val);
                                        delete left_at_zero_ast;
@@ -931,10 +955,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                                chunk.offset = (id2ast->range_left - id2ast->range_right + 1) - (chunk.offset + chunk.width);
                                        if (chunk.offset >= source_width || chunk.offset + chunk.width < 0) {
                                                if (chunk.width == 1)
-                                                       log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
+                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting result bit to undef.\n",
                                                                        str.c_str(), filename.c_str(), linenum);
                                                else
-                                                       log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
+                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting all %d result bits to undef.\n",
                                                                        str.c_str(), filename.c_str(), linenum, chunk.width);
                                                chunk = RTLIL::SigChunk(RTLIL::State::Sx, chunk.width);
                                        } else {
@@ -948,10 +972,10 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                                                        chunk.offset += add_undef_bits_lsb;
                                                }
                                                if (add_undef_bits_lsb)
-                                                       log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
+                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d LSB bits to undef.\n",
                                                                        str.c_str(), filename.c_str(), linenum, add_undef_bits_lsb);
                                                if (add_undef_bits_msb)
-                                                       log("Warning: Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
+                                                       log_warning("Range select out of bounds on signal `%s' at %s:%d: Setting %d MSB bits to undef.\n",
                                                                        str.c_str(), filename.c_str(), linenum, add_undef_bits_msb);
                                        }
                                }
@@ -1012,7 +1036,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
                        int width = arg.size();
                        if (width_hint > 0) {
                                width = width_hint;
-                               widthExtend(this, arg, width, is_signed, "$pos");
+                               widthExtend(this, arg, width, is_signed);
                        }
                        return uniop2rtlil(this, type_name, width, arg);
                }
@@ -1167,8 +1191,8 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint)
 
                        int width = std::max(val1.size(), val2.size());
                        is_signed = children[1]->is_signed && children[2]->is_signed;
-                       widthExtend(this, val1, width, is_signed, "$bu0");
-                       widthExtend(this, val2, width, is_signed, "$bu0");
+                       widthExtend(this, val1, width, is_signed);
+                       widthExtend(this, val2, width, is_signed);
 
                        RTLIL::SigSpec sig = mux2rtlil(this, cond, val1, val2);