Renamed extend() to extend_xx(), changed most users to extend_u0()
[yosys.git] / kernel / rtlil.cc
index 1a9eb4d14c0486b8a6d04343577c2d808f84cc79..0e8078df6db12298bc9fc31b98415429f03e41d0 100644 (file)
@@ -27,6 +27,7 @@
 
 YOSYS_NAMESPACE_BEGIN
 
+RTLIL::IdString::destruct_guard_t RTLIL::IdString::destruct_guard;
 std::vector<int> RTLIL::IdString::global_refcount_storage_;
 std::vector<char*> RTLIL::IdString::global_id_storage_;
 std::map<char*, int, RTLIL::IdString::char_ptr_cmp> RTLIL::IdString::global_id_index_;
@@ -440,7 +441,7 @@ std::vector<RTLIL::Module*> RTLIL::Design::selected_whole_modules_warn() const
                if (selected_whole_module(it.first))
                        result.push_back(it.second);
                else if (selected_module(it.first))
-                       log("Warning: Ignoring partially selected module %s.\n", log_id(it.first));
+                       log_warning("Ignoring partially selected module %s.\n", log_id(it.first));
        return result;
 }
 
@@ -752,6 +753,17 @@ namespace {
                                return;
                        }
 
+                       if (cell->type == "$dffe") {
+                               param_bool("\\CLK_POLARITY");
+                               param_bool("\\EN_POLARITY");
+                               port("\\CLK", 1);
+                               port("\\EN", 1);
+                               port("\\D", param("\\WIDTH"));
+                               port("\\Q", param("\\WIDTH"));
+                               check_expected();
+                               return;
+                       }
+
                        if (cell->type == "$dffsr") {
                                param_bool("\\CLK_POLARITY");
                                param_bool("\\SET_POLARITY");
@@ -892,6 +904,11 @@ namespace {
                        if (cell->type == "$_DFF_N_") { check_gate("DQC"); return; }
                        if (cell->type == "$_DFF_P_") { check_gate("DQC"); return; }
 
+                       if (cell->type == "$_DFFE_NN_") { check_gate("DQCE"); return; }
+                       if (cell->type == "$_DFFE_NP_") { check_gate("DQCE"); return; }
+                       if (cell->type == "$_DFFE_PN_") { check_gate("DQCE"); return; }
+                       if (cell->type == "$_DFFE_PP_") { check_gate("DQCE"); return; }
+
                        if (cell->type == "$_DFF_NN0_") { check_gate("DQCR"); return; }
                        if (cell->type == "$_DFF_NN1_") { check_gate("DQCR"); return; }
                        if (cell->type == "$_DFF_NP0_") { check_gate("DQCR"); return; }
@@ -1062,14 +1079,14 @@ bool RTLIL::Module::has_processes() const
 bool RTLIL::Module::has_memories_warn() const
 {
        if (!memories.empty())
-               log("Warning: Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this));
+               log_warning("Ignoring module %s because it contains memories (run 'memory' command first).\n", log_id(this));
        return !memories.empty();
 }
 
 bool RTLIL::Module::has_processes_warn() const
 {
        if (!processes.empty())
-               log("Warning: Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this));
+               log_warning("Ignoring module %s because it contains processes (run 'proc' command first).\n", log_id(this));
        return !processes.empty();
 }
 
@@ -1579,7 +1596,7 @@ RTLIL::Cell* RTLIL::Module::addSr(RTLIL::IdString name, RTLIL::SigSpec sig_set,
        return cell;
 }
 
-RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d,   RTLIL::SigSpec sig_q, bool clk_polarity)
+RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity)
 {
        RTLIL::Cell *cell = addCell(name, "$dff");
        cell->parameters["\\CLK_POLARITY"] = clk_polarity;
@@ -1590,6 +1607,19 @@ RTLIL::Cell* RTLIL::Module::addDff(RTLIL::IdString name, RTLIL::SigSpec sig_clk,
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addDffe(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity)
+{
+       RTLIL::Cell *cell = addCell(name, "$dffe");
+       cell->parameters["\\CLK_POLARITY"] = clk_polarity;
+       cell->parameters["\\EN_POLARITY"] = en_polarity;
+       cell->parameters["\\WIDTH"] = sig_q.size();
+       cell->setPort("\\CLK", sig_clk);
+       cell->setPort("\\EN", sig_en);
+       cell->setPort("\\D", sig_d);
+       cell->setPort("\\Q", sig_q);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDffsr(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr,
                RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity)
 {
@@ -1657,6 +1687,16 @@ RTLIL::Cell* RTLIL::Module::addDffGate(RTLIL::IdString name, RTLIL::SigSpec sig_
        return cell;
 }
 
+RTLIL::Cell* RTLIL::Module::addDffeGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_en, RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool en_polarity)
+{
+       RTLIL::Cell *cell = addCell(name, stringf("$_DFFE_%c%c_", clk_polarity ? 'P' : 'N', en_polarity ? 'P' : 'N'));
+       cell->setPort("\\C", sig_clk);
+       cell->setPort("\\E", sig_en);
+       cell->setPort("\\D", sig_d);
+       cell->setPort("\\Q", sig_q);
+       return cell;
+}
+
 RTLIL::Cell* RTLIL::Module::addDffsrGate(RTLIL::IdString name, RTLIL::SigSpec sig_clk, RTLIL::SigSpec sig_set, RTLIL::SigSpec sig_clr,
                RTLIL::SigSpec sig_d, RTLIL::SigSpec sig_q, bool clk_polarity, bool set_polarity, bool clr_polarity)
 {
@@ -2149,6 +2189,16 @@ RTLIL::SigSpec::SigSpec(std::set<RTLIL::SigBit> bits)
        check();
 }
 
+RTLIL::SigSpec::SigSpec(bool bit)
+{
+       cover("kernel.rtlil.sigspec.init.bool");
+
+       width_ = 0;
+       hash_ = 0;
+       append_bit(bit);
+       check();
+}
+
 void RTLIL::SigSpec::pack() const
 {
        RTLIL::SigSpec *that = (RTLIL::SigSpec*)this;
@@ -2540,9 +2590,9 @@ void RTLIL::SigSpec::append_bit(const RTLIL::SigBit &bit)
        check();
 }
 
-void RTLIL::SigSpec::extend(int width, bool is_signed)
+void RTLIL::SigSpec::extend_xx(int width, bool is_signed)
 {
-       cover("kernel.rtlil.sigspec.extend");
+       cover("kernel.rtlil.sigspec.extend_xx");
 
        pack();
 
@@ -2550,10 +2600,9 @@ void RTLIL::SigSpec::extend(int width, bool is_signed)
                remove(width, width_ - width);
        
        if (width_ < width) {
-               RTLIL::SigSpec padding = width_ > 0 ? extract(width_ - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0);
-               if (!is_signed && padding != RTLIL::SigSpec(RTLIL::State::Sx) && padding != RTLIL::SigSpec(RTLIL::State::Sz) &&
-                               padding != RTLIL::SigSpec(RTLIL::State::Sa) && padding != RTLIL::SigSpec(RTLIL::State::Sm))
-                       padding = RTLIL::SigSpec(RTLIL::State::S0);
+               RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0;
+               if (!is_signed && (padding == RTLIL::State::S1 || padding.wire))
+                       padding = RTLIL::State::S0;
                while (width_ < width)
                        append(padding);
        }
@@ -2569,9 +2618,9 @@ void RTLIL::SigSpec::extend_u0(int width, bool is_signed)
                remove(width, width_ - width);
        
        if (width_ < width) {
-               RTLIL::SigSpec padding = width_ > 0 ? extract(width_ - 1, 1) : RTLIL::SigSpec(RTLIL::State::S0);
+               RTLIL::SigBit padding = width_ > 0 ? (*this)[width_ - 1] : RTLIL::State::S0;
                if (!is_signed)
-                       padding = RTLIL::SigSpec(RTLIL::State::S0);
+                       padding = RTLIL::State::S0;
                while (width_ < width)
                        append(padding);
        }
@@ -2935,7 +2984,7 @@ bool RTLIL::SigSpec::parse(RTLIL::SigSpec &sig, RTLIL::Module *module, std::stri
                if (netname.size() == 0)
                        continue;
 
-               if ('0' <= netname[0] && netname[0] <= '9') {
+               if (('0' <= netname[0] && netname[0] <= '9') || netname[0] == '\'') {
                        cover("kernel.rtlil.sigspec.parse.const");
                        AST::get_line_num = sigspec_parse_get_dummy_line_num;
                        AST::AstNode *ast = VERILOG_FRONTEND::const2ast(netname);