Merge pull request #3080 from YosysHQ/micko/init_wire
[yosys.git] / backends / verilog / verilog_backend.cc
index 27a032586ad2e3ddd8b1f689fdddcd8a77bec667..47ef1c479d97d01bcdceb8609ade8e006395adb7 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  yosys -- Yosys Open SYnthesis Suite
  *
- *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
+ *  Copyright (C) 2012  Claire Xenia Wolf <claire@yosyshq.com>
  *
  *  Permission to use, copy, modify, and/or distribute this software for any
  *  purpose with or without fee is hereby granted, provided that the above
@@ -44,6 +44,7 @@ std::string auto_prefix, extmem_prefix;
 RTLIL::Module *active_module;
 dict<RTLIL::SigBit, RTLIL::State> active_initdata;
 SigMap active_sigmap;
+IdString initial_id;
 
 void reset_auto_counter_id(RTLIL::IdString id, bool may_rename)
 {
@@ -504,9 +505,24 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                                int start = init.addr.as_int();
                                for (int i=0; i<words; i++)
                                {
-                                       f << stringf("%s" "  %s[%d] = ", indent.c_str(), mem_id.c_str(), i + start);
-                                       dump_const(f, init.data.extract(i*mem.width, mem.width));
-                                       f << stringf(";\n");
+                                       for (int j = 0; j < mem.width; j++)
+                                       {
+                                               if (init.en[j] != State::S1)
+                                                       continue;
+
+                                               int start_j = j, width = 1;
+
+                                               while (j+1 < mem.width && init.en[j+1] == State::S1)
+                                                       j++, width++;
+
+                                               if (width == mem.width) {
+                                                       f << stringf("%s" "  %s[%d] = ", indent.c_str(), mem_id.c_str(), i + start);
+                                               } else {
+                                                       f << stringf("%s" "  %s[%d][%d:%d] = ", indent.c_str(), mem_id.c_str(), i + start, j, start_j);
+                                               }
+                                               dump_const(f, init.data.extract(i*mem.width+start_j, width));
+                                               f << stringf(";\n");
+                                       }
                                }
                        }
                        f << stringf("%s" "end\n", indent.c_str());
@@ -515,6 +531,8 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
 
        // create a map : "edge clk" -> expressions within that clock domain
        dict<std::string, std::vector<std::string>> clk_to_lof_body;
+       dict<std::string, std::string> clk_to_arst_cond;
+       dict<std::string, std::vector<std::string>> clk_to_arst_body;
        clk_to_lof_body[""] = std::vector<std::string>();
        std::string clk_domain_str;
        // create a list of reg declarations
@@ -529,10 +547,27 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                                std::ostringstream os;
                                dump_sigspec(os, port.clk);
                                clk_domain_str = stringf("%sedge %s", port.clk_polarity ? "pos" : "neg", os.str().c_str());
-                               if( clk_to_lof_body.count(clk_domain_str) == 0 )
-                                       clk_to_lof_body[clk_domain_str] = std::vector<std::string>();
+                               if (port.arst != State::S0) {
+                                       std::ostringstream os2;
+                                       dump_sigspec(os2, port.arst);
+                                       clk_domain_str += stringf(", posedge %s", os2.str().c_str());
+                                       clk_to_arst_cond[clk_domain_str] = os2.str();
+                               }
                        }
-                       if (!port.transparent)
+
+                       // Decide how to represent the transparency; same idea as Mem::extract_rdff.
+                       bool trans_use_addr = true;
+                       for (auto bit : port.transparency_mask)
+                               if (!bit)
+                                       trans_use_addr = false;
+
+                       if (GetSize(mem.wr_ports) == 0)
+                               trans_use_addr = false;
+
+                       if (port.en != State::S1 || port.srst != State::S0 || port.arst != State::S0 || !port.init_value.is_fully_undef())
+                               trans_use_addr = false;
+
+                       if (!trans_use_addr)
                        {
                                // for clocked read ports make something like:
                                //   reg [..] temp_id;
@@ -541,19 +576,148 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                                //   assign r_data = temp_id;
                                std::string temp_id = next_auto_id();
                                lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.data.size() - 1, temp_id.c_str()) );
-                               {
+
+                               bool has_indent = false;
+
+                               if (port.arst != State::S0) {
                                        std::ostringstream os;
-                                       if (port.en != RTLIL::SigBit(true))
-                                       {
-                                               os << stringf("if (");
-                                               dump_sigspec(os, port.en);
-                                               os << stringf(") ");
+                                       os << stringf("%s <= ", temp_id.c_str());
+                                       dump_sigspec(os, port.arst_value);
+                                       os << ";\n";
+                                       clk_to_arst_body[clk_domain_str].push_back(os.str());
+                               }
+
+                               if (port.srst != State::S0 && !port.ce_over_srst) {
+                                       std::ostringstream os;
+                                       os << stringf("if (");
+                                       dump_sigspec(os, port.srst);
+                                       os << stringf(")\n");
+                                       clk_to_lof_body[clk_domain_str].push_back(os.str());
+                                       std::ostringstream os2;
+                                       os2 << stringf("%s" "%s <= ", indent.c_str(), temp_id.c_str());
+                                       dump_sigspec(os2, port.srst_value);
+                                       os2 << ";\n";
+                                       clk_to_lof_body[clk_domain_str].push_back(os2.str());
+                                       std::ostringstream os3;
+                                       if (port.en == State::S1) {
+                                               os3 << "else begin\n";
+                                       } else {
+                                               os3 << "else if (";
+                                               dump_sigspec(os3, port.en);
+                                               os3 << ") begin\n";
                                        }
-                                       os << stringf("%s <= %s[", temp_id.c_str(), mem_id.c_str());
-                                       dump_sigspec(os, port.addr);
+                                       clk_to_lof_body[clk_domain_str].push_back(os3.str());
+                                       has_indent = true;
+                               } else if (port.en != State::S1) {
+                                       std::ostringstream os;
+                                       os << stringf("if (");
+                                       dump_sigspec(os, port.en);
+                                       os << stringf(") begin\n");
+                                       clk_to_lof_body[clk_domain_str].push_back(os.str());
+                                       has_indent = true;
+                               }
+
+                               for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+                               {
+                                       SigSpec addr = port.sub_addr(sub);
+                                       std::ostringstream os;
+                                       if (has_indent)
+                                               os << indent;
+                                       os << temp_id;
+                                       if (port.wide_log2)
+                                               os << stringf("[%d:%d]", (sub + 1) * mem.width - 1, sub * mem.width);
+                                       os << stringf(" <= %s[", mem_id.c_str());
+                                       dump_sigspec(os, addr);
                                        os << stringf("];\n");
                                        clk_to_lof_body[clk_domain_str].push_back(os.str());
                                }
+
+                               for (int i = 0; i < GetSize(mem.wr_ports); i++) {
+                                       auto &wport = mem.wr_ports[i];
+                                       if (!port.transparency_mask[i] && !port.collision_x_mask[i])
+                                               continue;
+                                       int min_wide_log2 = std::min(port.wide_log2, wport.wide_log2);
+                                       int max_wide_log2 = std::max(port.wide_log2, wport.wide_log2);
+                                       bool wide_write = wport.wide_log2 > port.wide_log2;
+                                       for (int sub = 0; sub < (1 << max_wide_log2); sub += (1 << min_wide_log2)) {
+                                               SigSpec raddr = port.addr;
+                                               SigSpec waddr = wport.addr;
+                                               if (wide_write)
+                                                       waddr = wport.sub_addr(sub);
+                                               else
+                                                       raddr = port.sub_addr(sub);
+                                               int pos = 0;
+                                               int ewidth = mem.width << min_wide_log2;
+                                               int wsub = wide_write ? sub : 0;
+                                               int rsub = wide_write ? 0 : sub;
+                                               while (pos < ewidth) {
+                                                       int epos = pos;
+                                                       while (epos < ewidth && wport.en[epos + wsub * mem.width] == wport.en[pos + wsub * mem.width])
+                                                               epos++;
+
+                                                       std::ostringstream os;
+                                                       if (has_indent)
+                                                               os << indent;
+                                                       os << "if (";
+                                                       dump_sigspec(os, wport.en[pos + wsub * mem.width]);
+                                                       if (raddr != waddr) {
+                                                               os << " && ";
+                                                               dump_sigspec(os, raddr);
+                                                               os << " == ";
+                                                               dump_sigspec(os, waddr);
+                                                       }
+                                                       os << ")\n";
+                                                       clk_to_lof_body[clk_domain_str].push_back(os.str());
+
+                                                       std::ostringstream os2;
+                                                       if (has_indent)
+                                                               os2 << indent;
+                                                       os2 << indent;
+                                                       os2 << temp_id;
+                                                       if (epos-pos != GetSize(port.data))
+                                                               os2 << stringf("[%d:%d]", rsub * mem.width + epos-1, rsub * mem.width + pos);
+                                                       os2 << " <= ";
+                                                       if (port.transparency_mask[i])
+                                                               dump_sigspec(os2, wport.data.extract(wsub * mem.width + pos, epos-pos));
+                                                       else
+                                                               dump_sigspec(os2, Const(State::Sx, epos - pos));
+                                                       os2 << ";\n";
+                                                       clk_to_lof_body[clk_domain_str].push_back(os2.str());
+
+                                                       pos = epos;
+                                               }
+                                       }
+                               }
+
+                               if (port.srst != State::S0 && port.ce_over_srst)
+                               {
+                                       std::ostringstream os;
+                                       if (has_indent)
+                                               os << indent;
+                                       os << stringf("if (");
+                                       dump_sigspec(os, port.srst);
+                                       os << stringf(")\n");
+                                       clk_to_lof_body[clk_domain_str].push_back(os.str());
+                                       std::ostringstream os2;
+                                       if (has_indent)
+                                               os2 << indent;
+                                       os2 << stringf("%s" "%s <= ", indent.c_str(), temp_id.c_str());
+                                       dump_sigspec(os2, port.srst_value);
+                                       os2 << ";\n";
+                                       clk_to_lof_body[clk_domain_str].push_back(os2.str());
+                               }
+
+                               if (has_indent)
+                                       clk_to_lof_body[clk_domain_str].push_back("end\n");
+
+                               if (!port.init_value.is_fully_undef())
+                               {
+                                       std::ostringstream os;
+                                       dump_sigspec(os, port.init_value);
+                                       std::string line = stringf("initial %s = %s;\n", temp_id.c_str(), os.str().c_str());
+                                       clk_to_lof_body[""].push_back(line);
+                               }
+
                                {
                                        std::ostringstream os;
                                        dump_sigspec(os, port.data);
@@ -569,28 +733,48 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                                //     temp_id <= r_addr;
                                //   assign r_data = array_reg[temp_id];
                                std::string temp_id = next_auto_id();
-                               lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.addr.size() - 1, temp_id.c_str()) );
+                               lof_reg_declarations.push_back( stringf("reg [%d:0] %s;\n", port.addr.size() - 1 - port.wide_log2, temp_id.c_str()) );
                                {
                                        std::ostringstream os;
-                                       dump_sigspec(os, port.addr);
+                                       dump_sigspec(os, port.addr.extract_end(port.wide_log2));
                                        std::string line = stringf("%s <= %s;\n", temp_id.c_str(), os.str().c_str());
                                        clk_to_lof_body[clk_domain_str].push_back(line);
                                }
+                               for (int sub = 0; sub < (1 << port.wide_log2); sub++)
                                {
                                        std::ostringstream os;
-                                       dump_sigspec(os, port.data);
-                                       std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), temp_id.c_str());
-                                       clk_to_lof_body[""].push_back(line);
+                                       os << "assign ";
+                                       dump_sigspec(os, port.data.extract(sub * mem.width, mem.width));
+                                       os << stringf(" = %s[", mem_id.c_str());;
+                                       if (port.wide_log2) {
+                                               Const addr_lo;
+                                               for (int i = 0; i < port.wide_log2; i++)
+                                                       addr_lo.bits.push_back(State(sub >> i & 1));
+                                               os << "{";
+                                               os << temp_id;
+                                               os << ", ";
+                                               dump_const(os, addr_lo);
+                                               os << "}";
+                                       } else {
+                                               os << temp_id;
+                                       }
+                                       os << "];\n";
+                                       clk_to_lof_body[""].push_back(os.str());
                                }
                        }
                } else {
                        // for non-clocked read-ports make something like:
                        //   assign r_data = array_reg[r_addr];
-                       std::ostringstream os, os2;
-                       dump_sigspec(os, port.data);
-                       dump_sigspec(os2, port.addr);
-                       std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
-                       clk_to_lof_body[""].push_back(line);
+                       for (int sub = 0; sub < (1 << port.wide_log2); sub++)
+                       {
+                               SigSpec addr = port.sub_addr(sub);
+
+                               std::ostringstream os, os2;
+                               dump_sigspec(os, port.data.extract(sub * mem.width, mem.width));
+                               dump_sigspec(os2, addr);
+                               std::string line = stringf("assign %s = %s[%s];\n", os.str().c_str(), mem_id.c_str(), os2.str().c_str());
+                               clk_to_lof_body[""].push_back(line);
+                       }
                }
        }
 
@@ -636,9 +820,13 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                                break;
                }
 
-               f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", root.clk_polarity ? "pos" : "neg");
-               dump_sigspec(f, root.clk);
-               f << ") begin\n";
+               if (root.clk_enable) {
+                       f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", root.clk_polarity ? "pos" : "neg");
+                       dump_sigspec(f, root.clk);
+                       f << ") begin\n";
+               } else {
+                       f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_latch" : " @*");
+               }
 
                for (int pidx = 0; pidx < GetSize(mem.wr_ports); pidx++)
                {
@@ -657,33 +845,37 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                        //   always @(posedge clk)
                        //      if (wr_en_bit) memid[w_addr][??] <= w_data[??];
                        //   ...
-                       for (int i = 0; i < GetSize(port.en); i++)
+                       for (int sub = 0; sub < (1 << port.wide_log2); sub++)
                        {
-                               int start_i = i, width = 1;
-                               SigBit wen_bit = port.en[i];
+                               SigSpec addr = port.sub_addr(sub);
+                               for (int i = 0; i < mem.width; i++)
+                               {
+                                       int start_i = i, width = 1;
+                                       SigBit wen_bit = port.en[sub * mem.width + i];
 
-                               while (i+1 < GetSize(port.en) && active_sigmap(port.en[i+1]) == active_sigmap(wen_bit))
-                                       i++, width++;
+                                       while (i+1 < mem.width && active_sigmap(port.en[sub * mem.width + i+1]) == active_sigmap(wen_bit))
+                                               i++, width++;
 
-                               if (wen_bit == State::S0)
-                                       continue;
+                                       if (wen_bit == State::S0)
+                                               continue;
 
-                               f << stringf("%s%s", indent.c_str(), indent.c_str());
-                               if (wen_bit != State::S1)
-                               {
-                                       f << stringf("if (");
-                                       dump_sigspec(f, wen_bit);
-                                       f << stringf(")\n");
-                                       f << stringf("%s%s%s", indent.c_str(), indent.c_str(), indent.c_str());
+                                       f << stringf("%s%s", indent.c_str(), indent.c_str());
+                                       if (wen_bit != State::S1)
+                                       {
+                                               f << stringf("if (");
+                                               dump_sigspec(f, wen_bit);
+                                               f << stringf(")\n");
+                                               f << stringf("%s%s%s", indent.c_str(), indent.c_str(), indent.c_str());
+                                       }
+                                       f << stringf("%s[", mem_id.c_str());
+                                       dump_sigspec(f, addr);
+                                       if (width == GetSize(port.en))
+                                               f << stringf("] <= ");
+                                       else
+                                               f << stringf("][%d:%d] <= ", i, start_i);
+                                       dump_sigspec(f, port.data.extract(sub * mem.width + start_i, width));
+                                       f << stringf(";\n");
                                }
-                               f << stringf("%s[", mem_id.c_str());
-                               dump_sigspec(f, port.addr);
-                               if (width == GetSize(port.en))
-                                       f << stringf("] <= ");
-                               else
-                                       f << stringf("][%d:%d] <= ", i, start_i);
-                               dump_sigspec(f, port.data.extract(start_i, width));
-                               f << stringf(";\n");
                        }
                }
 
@@ -720,8 +912,19 @@ void dump_memory(std::ostream &f, std::string indent, Mem &mem)
                if( clk_domain != "")
                {
                        f << stringf("%s" "always%s @(%s) begin\n", indent.c_str(), systemverilog ? "_ff" : "", clk_domain.c_str());
-                       for(auto &line : lof_lines)
-                               f << stringf("%s%s" "%s", indent.c_str(), indent.c_str(), line.c_str());
+                       bool has_arst = clk_to_arst_cond.count(clk_domain) != 0;
+                       if (has_arst) {
+                               f << stringf("%s%s" "if (%s) begin\n", indent.c_str(), indent.c_str(), clk_to_arst_cond[clk_domain].c_str());
+                               for(auto &line : clk_to_arst_body[clk_domain])
+                                       f << stringf("%s%s%s" "%s", indent.c_str(), indent.c_str(), indent.c_str(), line.c_str());
+                               f << stringf("%s%s" "end else begin\n", indent.c_str(), indent.c_str());
+                               for(auto &line : lof_lines)
+                                       f << stringf("%s%s%s" "%s", indent.c_str(), indent.c_str(), indent.c_str(), line.c_str());
+                               f << stringf("%s%s" "end\n", indent.c_str(), indent.c_str());
+                       } else {
+                               for(auto &line : lof_lines)
+                                       f << stringf("%s%s" "%s", indent.c_str(), indent.c_str(), line.c_str());
+                       }
                        f << stringf("%s" "end\n", indent.c_str());
                }
                else
@@ -1196,7 +1399,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                FfData ff(nullptr, cell);
 
                // $ff / $_FF_ cell: not supported.
-               if (ff.has_d && !ff.has_clk && !ff.has_en)
+               if (ff.has_gclk)
                        return false;
 
                std::string reg_name = cellname(cell);
@@ -1217,17 +1420,19 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 
                for (int i = 0; i < chunks; i++)
                {
-                       SigSpec sig_d;
+                       SigSpec sig_d, sig_ad;
                        Const val_arst, val_srst;
-                       std::string reg_bit_name, sig_set_name, sig_clr_name, sig_arst_name;
+                       std::string reg_bit_name, sig_set_name, sig_clr_name, sig_arst_name, sig_aload_name;
                        if (chunky) {
                                reg_bit_name = stringf("%s[%d]", reg_name.c_str(), i);
-                               if (ff.has_d)
+                               if (ff.has_gclk || ff.has_clk)
                                        sig_d = ff.sig_d[i];
+                               if (ff.has_aload)
+                                       sig_ad = ff.sig_ad[i];
                        } else {
                                reg_bit_name = reg_name;
-                               if (ff.has_d)
-                                       sig_d = ff.sig_d;
+                               sig_d = ff.sig_d;
+                               sig_ad = ff.sig_ad;
                        }
                        if (ff.has_arst)
                                val_arst = chunky ? ff.val_arst[i] : ff.val_arst;
@@ -1235,28 +1440,38 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                val_srst = chunky ? ff.val_srst[i] : ff.val_srst;
 
                        // If there are constants in the sensitivity list, replace them with an intermediate wire
-                       if (ff.has_sr) {
-                               if (ff.sig_set[i].wire == NULL)
-                               {
-                                       sig_set_name = next_auto_id();
-                                       f << stringf("%s" "wire %s = ", indent.c_str(), sig_set_name.c_str());
-                                       dump_const(f, ff.sig_set[i].data);
-                                       f << stringf(";\n");
-                               }
-                               if (ff.sig_clr[i].wire == NULL)
-                               {
-                                       sig_clr_name = next_auto_id();
-                                       f << stringf("%s" "wire %s = ", indent.c_str(), sig_clr_name.c_str());
-                                       dump_const(f, ff.sig_clr[i].data);
-                                       f << stringf(";\n");
-                               }
-                       } else if (ff.has_arst) {
-                               if (ff.sig_arst[i].wire == NULL)
-                               {
-                                       sig_arst_name = next_auto_id();
-                                       f << stringf("%s" "wire %s = ", indent.c_str(), sig_arst_name.c_str());
-                                       dump_const(f, ff.sig_arst[i].data);
-                                       f << stringf(";\n");
+                       if (ff.has_clk) {
+                               if (ff.has_sr) {
+                                       if (ff.sig_set[i].wire == NULL)
+                                       {
+                                               sig_set_name = next_auto_id();
+                                               f << stringf("%s" "wire %s = ", indent.c_str(), sig_set_name.c_str());
+                                               dump_const(f, ff.sig_set[i].data);
+                                               f << stringf(";\n");
+                                       }
+                                       if (ff.sig_clr[i].wire == NULL)
+                                       {
+                                               sig_clr_name = next_auto_id();
+                                               f << stringf("%s" "wire %s = ", indent.c_str(), sig_clr_name.c_str());
+                                               dump_const(f, ff.sig_clr[i].data);
+                                               f << stringf(";\n");
+                                       }
+                               } else if (ff.has_arst) {
+                                       if (ff.sig_arst[0].wire == NULL)
+                                       {
+                                               sig_arst_name = next_auto_id();
+                                               f << stringf("%s" "wire %s = ", indent.c_str(), sig_arst_name.c_str());
+                                               dump_const(f, ff.sig_arst[0].data);
+                                               f << stringf(";\n");
+                                       }
+                               } else if (ff.has_aload) {
+                                       if (ff.sig_aload[0].wire == NULL)
+                                       {
+                                               sig_aload_name = next_auto_id();
+                                               f << stringf("%s" "wire %s = ", indent.c_str(), sig_aload_name.c_str());
+                                               dump_const(f, ff.sig_aload[0].data);
+                                               f << stringf(";\n");
+                                       }
                                }
                        }
 
@@ -1278,13 +1493,18 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                                f << stringf("%s", sig_clr_name.c_str());
                                        else
                                                dump_sigspec(f, ff.sig_clr[i]);
-
                                } else if (ff.has_arst) {
                                        f << stringf(", %sedge ", ff.pol_arst ? "pos" : "neg");
-                                       if (ff.sig_arst[i].wire == NULL)
+                                       if (ff.sig_arst[0].wire == NULL)
                                                f << stringf("%s", sig_arst_name.c_str());
                                        else
                                                dump_sigspec(f, ff.sig_arst);
+                               } else if (ff.has_aload) {
+                                       f << stringf(", %sedge ", ff.pol_aload ? "pos" : "neg");
+                                       if (ff.sig_aload[0].wire == NULL)
+                                               f << stringf("%s", sig_aload_name.c_str());
+                                       else
+                                               dump_sigspec(f, ff.sig_aload);
                                }
                                f << stringf(")\n");
 
@@ -1305,7 +1525,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                        f << stringf("%s" "  else ", indent.c_str());
                                } else if (ff.has_arst) {
                                        f << stringf("if (%s", ff.pol_arst ? "" : "!");
-                                       if (ff.sig_arst[i].wire == NULL)
+                                       if (ff.sig_arst[0].wire == NULL)
                                                f << stringf("%s", sig_arst_name.c_str());
                                        else
                                                dump_sigspec(f, ff.sig_arst);
@@ -1313,11 +1533,21 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                        dump_sigspec(f, val_arst);
                                        f << stringf(";\n");
                                        f << stringf("%s" "  else ", indent.c_str());
+                               } else if (ff.has_aload) {
+                                       f << stringf("if (%s", ff.pol_aload ? "" : "!");
+                                       if (ff.sig_aload[0].wire == NULL)
+                                               f << stringf("%s", sig_aload_name.c_str());
+                                       else
+                                               dump_sigspec(f, ff.sig_aload);
+                                       f << stringf(") %s <= ", reg_bit_name.c_str());
+                                       dump_sigspec(f, sig_ad);
+                                       f << stringf(";\n");
+                                       f << stringf("%s" "  else ", indent.c_str());
                                }
 
-                               if (ff.has_srst && ff.has_en && ff.ce_over_srst) {
-                                       f << stringf("if (%s", ff.pol_en ? "" : "!");
-                                       dump_sigspec(f, ff.sig_en);
+                               if (ff.has_srst && ff.has_ce && ff.ce_over_srst) {
+                                       f << stringf("if (%s", ff.pol_ce ? "" : "!");
+                                       dump_sigspec(f, ff.sig_ce);
                                        f << stringf(")\n");
                                        f << stringf("%s" "    if (%s", indent.c_str(), ff.pol_srst ? "" : "!");
                                        dump_sigspec(f, ff.sig_srst);
@@ -1334,9 +1564,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                                f << stringf(";\n");
                                                f << stringf("%s" "  else ", indent.c_str());
                                        }
-                                       if (ff.has_en) {
-                                               f << stringf("if (%s", ff.pol_en ? "" : "!");
-                                               dump_sigspec(f, ff.sig_en);
+                                       if (ff.has_ce) {
+                                               f << stringf("if (%s", ff.pol_ce ? "" : "!");
+                                               dump_sigspec(f, ff.sig_ce);
                                                f << stringf(") ");
                                        }
                                }
@@ -1358,7 +1588,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                        f << stringf("%s" "  else if (%s", indent.c_str(), ff.pol_set ? "" : "!");
                                        dump_sigspec(f, ff.sig_set[i]);
                                        f << stringf(") %s = 1'b1;\n", reg_bit_name.c_str());
-                                       if (ff.has_d)
+                                       if (ff.has_aload)
                                                f << stringf("%s" "  else ", indent.c_str());
                                } else if (ff.has_arst) {
                                        f << stringf("if (%s", ff.pol_arst ? "" : "!");
@@ -1366,14 +1596,14 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
                                        f << stringf(") %s = ", reg_bit_name.c_str());
                                        dump_sigspec(f, val_arst);
                                        f << stringf(";\n");
-                                       if (ff.has_d)
+                                       if (ff.has_aload)
                                                f << stringf("%s" "  else ", indent.c_str());
                                }
-                               if (ff.has_d) {
-                                       f << stringf("if (%s", ff.pol_en ? "" : "!");
-                                       dump_sigspec(f, ff.sig_en);
+                               if (ff.has_aload) {
+                                       f << stringf("if (%s", ff.pol_aload ? "" : "!");
+                                       dump_sigspec(f, ff.sig_aload);
                                        f << stringf(") %s = ", reg_bit_name.c_str());
-                                       dump_sigspec(f, sig_d);
+                                       dump_sigspec(f, sig_ad);
                                        f << stringf(";\n");
                                }
                        }
@@ -1714,7 +1944,7 @@ void dump_process(std::ostream &f, std::string indent, RTLIL::Process *proc, boo
 
        f << stringf("%s" "always%s begin\n", indent.c_str(), systemverilog ? "_comb" : " @*");
        if (!systemverilog)
-               f << indent + "  " << "if (" << id("\\initial") << ") begin end\n";
+               f << indent + "  " << "if (" << id(initial_id) << ") begin end\n";
        dump_case_body(f, indent, &proc->root_case, true);
 
        std::string backup_indent = indent;
@@ -1833,6 +2063,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
        dump_attributes(f, indent, module->attributes, '\n', /*modattr=*/true);
        f << stringf("%s" "module %s(", indent.c_str(), id(module->name, false).c_str());
        bool keep_running = true;
+       int cnt = 0;
        for (int port_id = 1; keep_running; port_id++) {
                keep_running = false;
                for (auto wire : module->wires()) {
@@ -1841,14 +2072,16 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
                                        f << stringf(", ");
                                f << stringf("%s", id(wire->name).c_str());
                                keep_running = true;
+                               if (cnt==20) { f << stringf("\n"); cnt = 0; } else cnt++;
                                continue;
                        }
                }
        }
        f << stringf(");\n");
-
-       if (!systemverilog && !module->processes.empty())
-               f << indent + "  " << "reg " << id("\\initial") << " = 0;\n";
+       if (!systemverilog && !module->processes.empty()) {
+               initial_id = NEW_ID;
+               f << indent + "  " << "reg " << id(initial_id) << " = 0;\n";
+       }
 
        for (auto w : module->wires())
                dump_wire(f, indent + "  ", w);