mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	verilog_backend: Add handling for all FF types.
This commit is contained in:
		
							parent
							
								
									2f50c5af48
								
							
						
					
					
						commit
						8fd43515c5
					
				
					 1 changed files with 135 additions and 253 deletions
				
			
		| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/log.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/ff.h"
 | 
			
		||||
#include <string>
 | 
			
		||||
#include <sstream>
 | 
			
		||||
#include <set>
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,7 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
bool verbose, norename, noattr, attr2comment, noexpr, nodec, nohex, nostr, extmem, defparam, decimal, siminit, systemverilog;
 | 
			
		||||
int auto_name_counter, auto_name_offset, auto_name_digits, extmem_counter;
 | 
			
		||||
std::map<RTLIL::IdString, int> auto_name_map;
 | 
			
		||||
std::set<RTLIL::IdString> reg_wires, reg_ct;
 | 
			
		||||
std::set<RTLIL::IdString> reg_wires;
 | 
			
		||||
std::string auto_prefix, extmem_prefix;
 | 
			
		||||
 | 
			
		||||
RTLIL::Module *active_module;
 | 
			
		||||
| 
						 | 
				
			
			@ -451,7 +452,7 @@ void dump_cell_expr_port(std::ostream &f, RTLIL::Cell *cell, std::string port, b
 | 
			
		|||
 | 
			
		||||
std::string cellname(RTLIL::Cell *cell)
 | 
			
		||||
{
 | 
			
		||||
	if (!norename && cell->name[0] == '$' && reg_ct.count(cell->type) && cell->hasPort(ID::Q))
 | 
			
		||||
	if (!norename && cell->name[0] == '$' && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig = cell->getPort(ID::Q);
 | 
			
		||||
		if (GetSize(sig) != 1 || sig.is_fully_const())
 | 
			
		||||
| 
						 | 
				
			
			@ -605,93 +606,6 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.begins_with("$_DFF_"))
 | 
			
		||||
	{
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << ";\n";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dump_attributes(f, indent, cell->attributes);
 | 
			
		||||
		f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", cell->type[6] == 'P' ? "pos" : "neg");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::C));
 | 
			
		||||
		if (cell->type[7] != '_') {
 | 
			
		||||
			f << stringf(" or %sedge ", cell->type[7] == 'P' ? "pos" : "neg");
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::R));
 | 
			
		||||
		}
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
 | 
			
		||||
		if (cell->type[7] != '_') {
 | 
			
		||||
			f << stringf("%s" "  if (%s", indent.c_str(), cell->type[7] == 'P' ? "" : "!");
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::R));
 | 
			
		||||
			f << stringf(")\n");
 | 
			
		||||
			f << stringf("%s" "    %s <= %c;\n", indent.c_str(), reg_name.c_str(), cell->type[8]);
 | 
			
		||||
			f << stringf("%s" "  else\n", indent.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "    %s <= ", indent.c_str(), reg_name.c_str());
 | 
			
		||||
		dump_cell_expr_port(f, cell, "D", false);
 | 
			
		||||
		f << stringf(";\n");
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "assign ", indent.c_str());
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << stringf(" = %s;\n", reg_name.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.begins_with("$_DFFSR_"))
 | 
			
		||||
	{
 | 
			
		||||
		char pol_c = cell->type[8], pol_s = cell->type[9], pol_r = cell->type[10];
 | 
			
		||||
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << ";\n";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dump_attributes(f, indent, cell->attributes);
 | 
			
		||||
		f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", pol_c == 'P' ? "pos" : "neg");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::C));
 | 
			
		||||
		f << stringf(" or %sedge ", pol_s == 'P' ? "pos" : "neg");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::S));
 | 
			
		||||
		f << stringf(" or %sedge ", pol_r == 'P' ? "pos" : "neg");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::R));
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "  if (%s", indent.c_str(), pol_r == 'P' ? "" : "!");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::R));
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
		f << stringf("%s" "    %s <= 0;\n", indent.c_str(), reg_name.c_str());
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "  else if (%s", indent.c_str(), pol_s == 'P' ? "" : "!");
 | 
			
		||||
		dump_sigspec(f, cell->getPort(ID::S));
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
		f << stringf("%s" "    %s <= 1;\n", indent.c_str(), reg_name.c_str());
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "  else\n", indent.c_str());
 | 
			
		||||
		f << stringf("%s" "    %s <= ", indent.c_str(), reg_name.c_str());
 | 
			
		||||
		dump_cell_expr_port(f, cell, "D", false);
 | 
			
		||||
		f << stringf(";\n");
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "assign ", indent.c_str());
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << stringf(" = %s;\n", reg_name.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
#define HANDLE_UNIOP(_type, _operator) \
 | 
			
		||||
	if (cell->type ==_type) { dump_cell_expr_uniop(f, indent, cell, _operator); return true; }
 | 
			
		||||
#define HANDLE_BINOP(_type, _operator) \
 | 
			
		||||
| 
						 | 
				
			
			@ -986,154 +900,151 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == ID($dffsr))
 | 
			
		||||
	if (RTLIL::builtin_ff_cell_types().count(cell->type))
 | 
			
		||||
	{
 | 
			
		||||
		SigSpec sig_clk = cell->getPort(ID::CLK);
 | 
			
		||||
		SigSpec sig_set = cell->getPort(ID::SET);
 | 
			
		||||
		SigSpec sig_clr = cell->getPort(ID::CLR);
 | 
			
		||||
		SigSpec sig_d = cell->getPort(ID::D);
 | 
			
		||||
		SigSpec sig_q = cell->getPort(ID::Q);
 | 
			
		||||
		FfData ff(nullptr, cell);
 | 
			
		||||
 | 
			
		||||
		int width = cell->parameters[ID::WIDTH].as_int();
 | 
			
		||||
		bool pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool();
 | 
			
		||||
		bool pol_set = cell->parameters[ID::SET_POLARITY].as_bool();
 | 
			
		||||
		bool pol_clr = cell->parameters[ID::CLR_POLARITY].as_bool();
 | 
			
		||||
		// $ff / $_FF_ cell: not supported.
 | 
			
		||||
		if (ff.has_d && !ff.has_clk && !ff.has_en)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(sig_q, reg_name);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(ff.sig_q, reg_name);
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "reg [%d:0] %s", indent.c_str(), width-1, reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, sig_q);
 | 
			
		||||
			if (ff.width == 1)
 | 
			
		||||
				f << stringf("%s" "reg %s", indent.c_str(), reg_name.c_str());
 | 
			
		||||
			else
 | 
			
		||||
				f << stringf("%s" "reg [%d:0] %s", indent.c_str(), ff.width-1, reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, ff.sig_q);
 | 
			
		||||
			f << ";\n";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < width; i++) {
 | 
			
		||||
			f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", pol_clk ? "pos" : "neg");
 | 
			
		||||
			dump_sigspec(f, sig_clk);
 | 
			
		||||
			f << stringf(", %sedge ", pol_set ? "pos" : "neg");
 | 
			
		||||
			dump_sigspec(f, sig_set);
 | 
			
		||||
			f << stringf(", %sedge ", pol_clr ? "pos" : "neg");
 | 
			
		||||
			dump_sigspec(f, sig_clr);
 | 
			
		||||
			f << stringf(")\n");
 | 
			
		||||
		// If the FF has CLR/SET inputs, emit every bit slice separately.
 | 
			
		||||
		int chunks = ff.has_sr ? ff.width : 1;
 | 
			
		||||
		bool chunky = ff.has_sr && ff.width != 1;
 | 
			
		||||
 | 
			
		||||
			f << stringf("%s" "  if (%s", indent.c_str(), pol_clr ? "" : "!");
 | 
			
		||||
			dump_sigspec(f, sig_clr);
 | 
			
		||||
			f << stringf(") %s[%d] <= 1'b0;\n", reg_name.c_str(), i);
 | 
			
		||||
		for (int i = 0; i < chunks; i++)
 | 
			
		||||
		{
 | 
			
		||||
			SigSpec sig_d;
 | 
			
		||||
			Const val_arst, val_srst;
 | 
			
		||||
			std::string reg_bit_name;
 | 
			
		||||
			if (chunky) {
 | 
			
		||||
				reg_bit_name = stringf("%s[%d]", reg_name.c_str(), i);
 | 
			
		||||
				if (ff.has_d)
 | 
			
		||||
					sig_d = ff.sig_d[i];
 | 
			
		||||
			} else {
 | 
			
		||||
				reg_bit_name = reg_name;
 | 
			
		||||
				if (ff.has_d)
 | 
			
		||||
					sig_d = ff.sig_d;
 | 
			
		||||
			}
 | 
			
		||||
			if (ff.has_arst)
 | 
			
		||||
				val_arst = chunky ? ff.val_arst[i] : ff.val_arst;
 | 
			
		||||
			if (ff.has_srst)
 | 
			
		||||
				val_srst = chunky ? ff.val_srst[i] : ff.val_srst;
 | 
			
		||||
 | 
			
		||||
			f << stringf("%s" "  else if (%s", indent.c_str(), pol_set ? "" : "!");
 | 
			
		||||
			dump_sigspec(f, sig_set);
 | 
			
		||||
			f << stringf(") %s[%d] <= 1'b1;\n", reg_name.c_str(), i);
 | 
			
		||||
			dump_attributes(f, indent, cell->attributes);
 | 
			
		||||
			if (ff.has_clk)
 | 
			
		||||
			{
 | 
			
		||||
				// FFs.
 | 
			
		||||
				f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", ff.pol_clk ? "pos" : "neg");
 | 
			
		||||
				dump_sigspec(f, ff.sig_clk);
 | 
			
		||||
				if (ff.has_sr) {
 | 
			
		||||
					f << stringf(", %sedge ", ff.pol_set ? "pos" : "neg");
 | 
			
		||||
					dump_sigspec(f, ff.sig_set[i]);
 | 
			
		||||
					f << stringf(", %sedge ", ff.pol_clr ? "pos" : "neg");
 | 
			
		||||
					dump_sigspec(f, ff.sig_clr[i]);
 | 
			
		||||
				} else if (ff.has_arst) {
 | 
			
		||||
					f << stringf(", %sedge ", ff.pol_arst ? "pos" : "neg");
 | 
			
		||||
					dump_sigspec(f, ff.sig_arst);
 | 
			
		||||
				}
 | 
			
		||||
				f << stringf(")\n");
 | 
			
		||||
 | 
			
		||||
			f << stringf("%s" "  else  %s[%d] <= ", indent.c_str(), reg_name.c_str(), i);
 | 
			
		||||
			dump_sigspec(f, sig_d[i]);
 | 
			
		||||
			f << stringf(";\n");
 | 
			
		||||
				f << stringf("%s" "  ", indent.c_str());
 | 
			
		||||
				if (ff.has_sr) {
 | 
			
		||||
					f << stringf("if (%s", ff.pol_clr ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_clr[i]);
 | 
			
		||||
					f << stringf(") %s <= 1'b0;\n", reg_bit_name.c_str());
 | 
			
		||||
					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());
 | 
			
		||||
					f << stringf("%s" "  else ", indent.c_str());
 | 
			
		||||
				} else if (ff.has_arst) {
 | 
			
		||||
					f << stringf("if (%s", ff.pol_arst ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_arst);
 | 
			
		||||
					f << stringf(") %s <= ", reg_bit_name.c_str());
 | 
			
		||||
					dump_sigspec(f, val_arst);
 | 
			
		||||
					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);
 | 
			
		||||
					f << stringf(")\n");
 | 
			
		||||
					f << stringf("%s" "    if (%s", indent.c_str(), ff.pol_srst ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_srst);
 | 
			
		||||
					f << stringf(") %s <= ", reg_bit_name.c_str());
 | 
			
		||||
					dump_sigspec(f, val_srst);
 | 
			
		||||
					f << stringf(";\n");
 | 
			
		||||
					f << stringf("%s" "    else ", indent.c_str());
 | 
			
		||||
				} else {
 | 
			
		||||
					if (ff.has_srst) {
 | 
			
		||||
						f << stringf("if (%s", ff.pol_srst ? "" : "!");
 | 
			
		||||
						dump_sigspec(f, ff.sig_srst);
 | 
			
		||||
						f << stringf(") %s <= ", reg_bit_name.c_str());
 | 
			
		||||
						dump_sigspec(f, val_srst);
 | 
			
		||||
						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);
 | 
			
		||||
						f << stringf(") ");
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				f << stringf("%s <= ", reg_bit_name.c_str());
 | 
			
		||||
				dump_sigspec(f, sig_d);
 | 
			
		||||
				f << stringf(";\n");
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				// Latches.
 | 
			
		||||
				f << stringf("%s" "always%s\n", indent.c_str(), systemverilog ? "_latch" : " @*");
 | 
			
		||||
 | 
			
		||||
				f << stringf("%s" "  ", indent.c_str());
 | 
			
		||||
				if (ff.has_sr) {
 | 
			
		||||
					f << stringf("if (%s", ff.pol_clr ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_clr[i]);
 | 
			
		||||
					f << stringf(") %s = 1'b0;\n", reg_bit_name.c_str());
 | 
			
		||||
					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)
 | 
			
		||||
						f << stringf("%s" "  else ", indent.c_str());
 | 
			
		||||
				} else if (ff.has_arst) {
 | 
			
		||||
					f << stringf("if (%s", ff.pol_arst ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_arst);
 | 
			
		||||
					f << stringf(") %s = ", reg_bit_name.c_str());
 | 
			
		||||
					dump_sigspec(f, val_arst);
 | 
			
		||||
					f << stringf(";\n");
 | 
			
		||||
					if (ff.has_d)
 | 
			
		||||
						f << stringf("%s" "  else ", indent.c_str());
 | 
			
		||||
				}
 | 
			
		||||
				if (ff.has_d) {
 | 
			
		||||
					f << stringf("if (%s", ff.pol_en ? "" : "!");
 | 
			
		||||
					dump_sigspec(f, ff.sig_en);
 | 
			
		||||
					f << stringf(") %s = ", reg_bit_name.c_str());
 | 
			
		||||
					dump_sigspec(f, sig_d);
 | 
			
		||||
					f << stringf(";\n");
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "assign ", indent.c_str());
 | 
			
		||||
			dump_sigspec(f, sig_q);
 | 
			
		||||
			f << stringf(" = %s;\n", reg_name.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type.in(ID($dff), ID($adff), ID($dffe)))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_clk, sig_arst, sig_en, val_arst;
 | 
			
		||||
		bool pol_clk, pol_arst = false, pol_en = false;
 | 
			
		||||
 | 
			
		||||
		sig_clk = cell->getPort(ID::CLK);
 | 
			
		||||
		pol_clk = cell->parameters[ID::CLK_POLARITY].as_bool();
 | 
			
		||||
 | 
			
		||||
		if (cell->type == ID($adff)) {
 | 
			
		||||
			sig_arst = cell->getPort(ID::ARST);
 | 
			
		||||
			pol_arst = cell->parameters[ID::ARST_POLARITY].as_bool();
 | 
			
		||||
			val_arst = RTLIL::SigSpec(cell->parameters[ID::ARST_VALUE]);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type == ID($dffe)) {
 | 
			
		||||
			sig_en = cell->getPort(ID::EN);
 | 
			
		||||
			pol_en = cell->parameters[ID::EN_POLARITY].as_bool();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << ";\n";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "always%s @(%sedge ", indent.c_str(), systemverilog ? "_ff" : "", pol_clk ? "pos" : "neg");
 | 
			
		||||
		dump_sigspec(f, sig_clk);
 | 
			
		||||
		if (cell->type == ID($adff)) {
 | 
			
		||||
			f << stringf(" or %sedge ", pol_arst ? "pos" : "neg");
 | 
			
		||||
			dump_sigspec(f, sig_arst);
 | 
			
		||||
		}
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
 | 
			
		||||
		if (cell->type == ID($adff)) {
 | 
			
		||||
			f << stringf("%s" "  if (%s", indent.c_str(), pol_arst ? "" : "!");
 | 
			
		||||
			dump_sigspec(f, sig_arst);
 | 
			
		||||
			f << stringf(")\n");
 | 
			
		||||
			f << stringf("%s" "    %s <= ", indent.c_str(), reg_name.c_str());
 | 
			
		||||
			dump_sigspec(f, val_arst);
 | 
			
		||||
			f << stringf(";\n");
 | 
			
		||||
			f << stringf("%s" "  else\n", indent.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type == ID($dffe)) {
 | 
			
		||||
			f << stringf("%s" "  if (%s", indent.c_str(), pol_en ? "" : "!");
 | 
			
		||||
			dump_sigspec(f, sig_en);
 | 
			
		||||
			f << stringf(")\n");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "    %s <= ", indent.c_str(), reg_name.c_str());
 | 
			
		||||
		dump_cell_expr_port(f, cell, "D", false);
 | 
			
		||||
		f << stringf(";\n");
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "assign ", indent.c_str());
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << stringf(" = %s;\n", reg_name.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == ID($dlatch))
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigSpec sig_en;
 | 
			
		||||
		bool pol_en = false;
 | 
			
		||||
 | 
			
		||||
		sig_en = cell->getPort(ID::EN);
 | 
			
		||||
		pol_en = cell->parameters[ID::EN_POLARITY].as_bool();
 | 
			
		||||
 | 
			
		||||
		std::string reg_name = cellname(cell);
 | 
			
		||||
		bool out_is_reg_wire = is_reg_wire(cell->getPort(ID::Q), reg_name);
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "reg [%d:0] %s", indent.c_str(), cell->parameters[ID::WIDTH].as_int()-1, reg_name.c_str());
 | 
			
		||||
			dump_reg_init(f, cell->getPort(ID::Q));
 | 
			
		||||
			f << ";\n";
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "always%s\n", indent.c_str(), systemverilog ? "_latch" : " @*");
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "  if (%s", indent.c_str(), pol_en ? "" : "!");
 | 
			
		||||
		dump_sigspec(f, sig_en);
 | 
			
		||||
		f << stringf(")\n");
 | 
			
		||||
 | 
			
		||||
		f << stringf("%s" "    %s = ", indent.c_str(), reg_name.c_str());
 | 
			
		||||
		dump_cell_expr_port(f, cell, "D", false);
 | 
			
		||||
		f << stringf(";\n");
 | 
			
		||||
 | 
			
		||||
		if (!out_is_reg_wire) {
 | 
			
		||||
			f << stringf("%s" "assign ", indent.c_str());
 | 
			
		||||
			dump_sigspec(f, cell->getPort(ID::Q));
 | 
			
		||||
			dump_sigspec(f, ff.sig_q);
 | 
			
		||||
			f << stringf(" = %s;\n", reg_name.c_str());
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1528,8 +1439,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// FIXME: $_SR_[PN][PN]_, $_DLATCH_[PN]_, $_DLATCHSR_[PN][PN][PN]_
 | 
			
		||||
	// FIXME: $sr, $dlatch, $memrd, $memwr, $fsm
 | 
			
		||||
	// FIXME: $memrd, $memwr, $fsm
 | 
			
		||||
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1602,7 +1512,7 @@ void dump_cell(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (siminit && reg_ct.count(cell->type) && cell->hasPort(ID::Q)) {
 | 
			
		||||
	if (siminit && RTLIL::builtin_ff_cell_types().count(cell->type) && cell->hasPort(ID::Q) && !cell->type.in(ID($ff), ID($_FF_))) {
 | 
			
		||||
		std::stringstream ss;
 | 
			
		||||
		dump_reg_init(ss, cell->getPort(ID::Q));
 | 
			
		||||
		if (!ss.str().empty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1812,7 +1722,7 @@ void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module)
 | 
			
		|||
		std::set<std::pair<RTLIL::Wire*,int>> reg_bits;
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (!reg_ct.count(cell->type) || !cell->hasPort(ID::Q))
 | 
			
		||||
			if (!RTLIL::builtin_ff_cell_types().count(cell->type) || !cell->hasPort(ID::Q) || cell->type.in(ID($ff), ID($_FF_)))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec sig = cell->getPort(ID::Q);
 | 
			
		||||
| 
						 | 
				
			
			@ -1984,33 +1894,6 @@ struct VerilogBackend : public Backend {
 | 
			
		|||
 | 
			
		||||
		auto_name_map.clear();
 | 
			
		||||
		reg_wires.clear();
 | 
			
		||||
		reg_ct.clear();
 | 
			
		||||
 | 
			
		||||
		reg_ct.insert(ID($dff));
 | 
			
		||||
		reg_ct.insert(ID($adff));
 | 
			
		||||
		reg_ct.insert(ID($dffe));
 | 
			
		||||
		reg_ct.insert(ID($dlatch));
 | 
			
		||||
 | 
			
		||||
		reg_ct.insert(ID($_DFF_N_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_P_));
 | 
			
		||||
 | 
			
		||||
		reg_ct.insert(ID($_DFF_NN0_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_NN1_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_NP0_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_NP1_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_PN0_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_PN1_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_PP0_));
 | 
			
		||||
		reg_ct.insert(ID($_DFF_PP1_));
 | 
			
		||||
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_NNN_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_NNP_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_NPN_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_NPP_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_PNN_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_PNP_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_PPN_));
 | 
			
		||||
		reg_ct.insert(ID($_DFFSR_PPP_));
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++) {
 | 
			
		||||
| 
						 | 
				
			
			@ -2107,7 +1990,6 @@ struct VerilogBackend : public Backend {
 | 
			
		|||
 | 
			
		||||
		auto_name_map.clear();
 | 
			
		||||
		reg_wires.clear();
 | 
			
		||||
		reg_ct.clear();
 | 
			
		||||
	}
 | 
			
		||||
} VerilogBackend;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue