mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-31 03:32:29 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into eddie/synth_xilinx_fine
This commit is contained in:
		
						commit
						31ff0d8ef5
					
				
					 22 changed files with 321 additions and 225 deletions
				
			
		
							
								
								
									
										8
									
								
								Makefile
									
										
									
									
									
								
							
							
						
						
									
										8
									
								
								Makefile
									
										
									
									
									
								
							|  | @ -294,7 +294,7 @@ endif | ||||||
| PY_WRAPPER_FILE = kernel/python_wrappers | PY_WRAPPER_FILE = kernel/python_wrappers | ||||||
| OBJS += $(PY_WRAPPER_FILE).o | OBJS += $(PY_WRAPPER_FILE).o | ||||||
| PY_GEN_SCRIPT= py_wrap_generator | PY_GEN_SCRIPT= py_wrap_generator | ||||||
| PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()") | PY_WRAP_INCLUDES := $(shell python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).print_includes()") | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
| ifeq ($(ENABLE_READLINE),1) | ifeq ($(ENABLE_READLINE),1) | ||||||
|  | @ -550,9 +550,9 @@ libyosys.so: $(filter-out kernel/driver.o,$(OBJS)) | ||||||
| 	$(Q) mkdir -p $(dir $@) | 	$(Q) mkdir -p $(dir $@) | ||||||
| 	$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P - | 	$(P) cat $< | grep -E -v "#[ ]*(include|error)" | $(LD) -x c++ -o $@ -E -P - | ||||||
| 
 | 
 | ||||||
| $(PY_WRAPPER_FILE).cc: $(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES) | $(PY_WRAPPER_FILE).cc: misc/$(PY_GEN_SCRIPT).py $(PY_WRAP_INCLUDES) | ||||||
| 	$(Q) mkdir -p $(dir $@) | 	$(Q) mkdir -p $(dir $@) | ||||||
| 	$(P) python$(PYTHON_VERSION) -c "import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")" | 	$(P) python$(PYTHON_VERSION) -c "from misc import $(PY_GEN_SCRIPT); $(PY_GEN_SCRIPT).gen_wrappers(\"$(PY_WRAPPER_FILE).cc\")" | ||||||
| 
 | 
 | ||||||
| %.o: %.cpp | %.o: %.cpp | ||||||
| 	$(Q) mkdir -p $(dir $@) | 	$(Q) mkdir -p $(dir $@) | ||||||
|  | @ -685,7 +685,7 @@ ifeq ($(ENABLE_LIBYOSYS),1) | ||||||
| ifeq ($(ENABLE_PYOSYS),1) | ifeq ($(ENABLE_PYOSYS),1) | ||||||
| 	$(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys | 	$(INSTALL_SUDO) mkdir -p $(PYTHON_DESTDIR)/pyosys | ||||||
| 	$(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys | 	$(INSTALL_SUDO) cp libyosys.so $(PYTHON_DESTDIR)/pyosys | ||||||
| 	$(INSTALL_SUDO) cp __init__.py $(PYTHON_DESTDIR)/pyosys | 	$(INSTALL_SUDO) cp misc/__init__.py $(PYTHON_DESTDIR)/pyosys | ||||||
| endif | endif | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -164,6 +164,7 @@ struct FirrtlWorker | ||||||
| 	}; | 	}; | ||||||
| 	/* Memories defined within this module. */ | 	/* Memories defined within this module. */ | ||||||
| 	 struct memory { | 	 struct memory { | ||||||
|  | 		 Cell *pCell;					// for error reporting
 | ||||||
| 		 string name;					// memory name
 | 		 string name;					// memory name
 | ||||||
| 		 int abits;						// number of address bits
 | 		 int abits;						// number of address bits
 | ||||||
| 		 int size;						// size (in units) of the memory
 | 		 int size;						// size (in units) of the memory
 | ||||||
|  | @ -174,8 +175,37 @@ struct FirrtlWorker | ||||||
| 		 vector<write_port> write_ports; | 		 vector<write_port> write_ports; | ||||||
| 		 std::string init_file; | 		 std::string init_file; | ||||||
| 		 std::string init_file_srcFileSpec; | 		 std::string init_file_srcFileSpec; | ||||||
| 		 memory(string name, int abits, int size, int width) : name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") {} | 		 string srcLine; | ||||||
| 		 memory() : read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} | 		 memory(Cell *pCell, string name, int abits, int size, int width) : pCell(pCell), name(name), abits(abits), size(size), width(width), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec("") { | ||||||
|  | 			// Provide defaults for abits or size if one (but not the other) is specified.
 | ||||||
|  | 			if (this->abits == 0 && this->size != 0) { | ||||||
|  | 				this->abits = ceil_log2(this->size); | ||||||
|  | 			} else if (this->abits != 0 && this->size == 0) { | ||||||
|  | 				this->size = 1 << this->abits; | ||||||
|  | 			} | ||||||
|  | 			// Sanity-check this construction.
 | ||||||
|  | 			if (this->name == "") { | ||||||
|  | 				log_error("Nameless memory%s\n", this->atLine()); | ||||||
|  | 			} | ||||||
|  | 			if (this->abits == 0 && this->size == 0) { | ||||||
|  | 				log_error("Memory %s has zero address bits and size%s\n", this->name.c_str(), this->atLine()); | ||||||
|  | 			} | ||||||
|  | 			if (this->width == 0) { | ||||||
|  | 				log_error("Memory %s has zero width%s\n", this->name.c_str(), this->atLine()); | ||||||
|  | 			} | ||||||
|  | 		 } | ||||||
|  | 		// We need a default constructor for the dict insert.
 | ||||||
|  | 	   memory() : pCell(0), read_latency(0), write_latency(1), init_file(""), init_file_srcFileSpec(""){} | ||||||
|  | 
 | ||||||
|  | 		const char *atLine() { | ||||||
|  | 			if (srcLine == "") { | ||||||
|  | 				if (pCell) { | ||||||
|  | 					auto p = pCell->attributes.find("\\src"); | ||||||
|  | 					srcLine = " at " + p->second.decode_string(); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 			return srcLine.c_str(); | ||||||
|  | 		} | ||||||
| 		 void add_memory_read_port(read_port &rp) { | 		 void add_memory_read_port(read_port &rp) { | ||||||
| 			 read_ports.push_back(rp); | 			 read_ports.push_back(rp); | ||||||
| 		 } | 		 } | ||||||
|  | @ -604,7 +634,7 @@ struct FirrtlWorker | ||||||
| 				int abits = cell->parameters.at("\\ABITS").as_int(); | 				int abits = cell->parameters.at("\\ABITS").as_int(); | ||||||
| 				int width = cell->parameters.at("\\WIDTH").as_int(); | 				int width = cell->parameters.at("\\WIDTH").as_int(); | ||||||
| 				int size = cell->parameters.at("\\SIZE").as_int(); | 				int size = cell->parameters.at("\\SIZE").as_int(); | ||||||
| 				memory m(mem_id, abits, size, width); | 				memory m(cell, mem_id, abits, size, width); | ||||||
| 				int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); | 				int rd_ports = cell->parameters.at("\\RD_PORTS").as_int(); | ||||||
| 				int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); | 				int wr_ports = cell->parameters.at("\\WR_PORTS").as_int(); | ||||||
| 
 | 
 | ||||||
|  | @ -681,6 +711,8 @@ struct FirrtlWorker | ||||||
| 			{ | 			{ | ||||||
| 				std::string cell_type = fid(cell->type); | 				std::string cell_type = fid(cell->type); | ||||||
| 				std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); | 				std::string mem_id = make_id(cell->parameters["\\MEMID"].decode_string()); | ||||||
|  | 				int abits = cell->parameters.at("\\ABITS").as_int(); | ||||||
|  | 				int width = cell->parameters.at("\\WIDTH").as_int(); | ||||||
| 				memory *mp = nullptr; | 				memory *mp = nullptr; | ||||||
| 				if (cell->type == "$meminit" ) { | 				if (cell->type == "$meminit" ) { | ||||||
| 					log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); | 					log_error("$meminit (%s.%s.%s) currently unsupported\n", log_id(module), log_id(cell), mem_id.c_str()); | ||||||
|  | @ -693,6 +725,11 @@ struct FirrtlWorker | ||||||
| 					Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); | 					Const clk_enable = cell->parameters.at("\\CLK_ENABLE"); | ||||||
| 					Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); | 					Const clk_polarity = cell->parameters.at("\\CLK_POLARITY"); | ||||||
| 
 | 
 | ||||||
|  | 					// Do we already have an entry for this memory?
 | ||||||
|  | 					if (memories.count(mem_id) == 0) { | ||||||
|  | 						memory m(cell, mem_id, abits, 0, width); | ||||||
|  | 						register_memory(m); | ||||||
|  | 					} | ||||||
| 					mp = &memories.at(mem_id); | 					mp = &memories.at(mem_id); | ||||||
| 					int portNum = 0; | 					int portNum = 0; | ||||||
| 					bool transparency = false; | 					bool transparency = false; | ||||||
|  | @ -890,7 +927,7 @@ struct FirrtlWorker | ||||||
| 
 | 
 | ||||||
| 		// If we have any memory definitions, output them.
 | 		// If we have any memory definitions, output them.
 | ||||||
| 		for (auto kv : memories) { | 		for (auto kv : memories) { | ||||||
| 			memory m = kv.second; | 			memory &m = kv.second; | ||||||
| 			f << stringf("    mem %s:\n", m.name.c_str()); | 			f << stringf("    mem %s:\n", m.name.c_str()); | ||||||
| 			f << stringf("      data-type => UInt<%d>\n", m.width); | 			f << stringf("      data-type => UInt<%d>\n", m.width); | ||||||
| 			f << stringf("      depth => %d\n", m.size); | 			f << stringf("      depth => %d\n", m.size); | ||||||
|  |  | ||||||
|  | @ -1172,6 +1172,15 @@ bool AstNode::simplify(bool const_fold, bool at_zero, bool in_lvalue, int stage, | ||||||
| 			varbuf->children[0] = buf; | 			varbuf->children[0] = buf; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | #if 0 | ||||||
|  | 		if (type == AST_FOR) { | ||||||
|  | 			AstNode *buf = next_ast->clone(); | ||||||
|  | 			delete buf->children[1]; | ||||||
|  | 			buf->children[1] = varbuf->children[0]->clone(); | ||||||
|  | 			current_block->children.insert(current_block->children.begin() + current_block_idx++, buf); | ||||||
|  | 		} | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| 		current_scope[varbuf->str] = backup_scope_varbuf; | 		current_scope[varbuf->str] = backup_scope_varbuf; | ||||||
| 		delete varbuf; | 		delete varbuf; | ||||||
| 		delete_children(); | 		delete_children(); | ||||||
|  |  | ||||||
|  | @ -242,8 +242,6 @@ struct VerilogFrontend : public Frontend { | ||||||
| 		nowb_mode = false; | 		nowb_mode = false; | ||||||
| 		default_nettype_wire = true; | 		default_nettype_wire = true; | ||||||
| 
 | 
 | ||||||
| 		log_header(design, "Executing Verilog-2005 frontend.\n"); |  | ||||||
| 
 |  | ||||||
| 		args.insert(args.begin()+1, verilog_defaults.begin(), verilog_defaults.end()); | 		args.insert(args.begin()+1, verilog_defaults.begin(), verilog_defaults.end()); | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
|  | @ -415,6 +413,8 @@ struct VerilogFrontend : public Frontend { | ||||||
| 		} | 		} | ||||||
| 		extra_args(f, filename, args, argidx); | 		extra_args(f, filename, args, argidx); | ||||||
| 
 | 
 | ||||||
|  | 		log_header(design, "Executing Verilog-2005 frontend: %s\n", filename.c_str()); | ||||||
|  | 
 | ||||||
| 		log("Parsing %s%s input from `%s' to AST representation.\n", | 		log("Parsing %s%s input from `%s' to AST representation.\n", | ||||||
| 				formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str()); | 				formal_mode ? "formal " : "", sv_mode ? "SystemVerilog" : "Verilog", filename.c_str()); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -529,13 +529,13 @@ int main(int argc, char **argv) | ||||||
| 			log_error("Can't open dependencies file for writing: %s\n", strerror(errno)); | 			log_error("Can't open dependencies file for writing: %s\n", strerror(errno)); | ||||||
| 		bool first = true; | 		bool first = true; | ||||||
| 		for (auto fn : yosys_output_files) { | 		for (auto fn : yosys_output_files) { | ||||||
| 			fprintf(f, "%s%s", first ? "" : " ", fn.c_str()); | 			fprintf(f, "%s%s", first ? "" : " ", escape_filename_spaces(fn).c_str()); | ||||||
| 			first = false; | 			first = false; | ||||||
| 		} | 		} | ||||||
| 		fprintf(f, ":"); | 		fprintf(f, ":"); | ||||||
| 		for (auto fn : yosys_input_files) { | 		for (auto fn : yosys_input_files) { | ||||||
| 			if (yosys_output_files.count(fn) == 0) | 			if (yosys_output_files.count(fn) == 0) | ||||||
| 				fprintf(f, " %s", fn.c_str()); | 				fprintf(f, " %s", escape_filename_spaces(fn).c_str()); | ||||||
| 		} | 		} | ||||||
| 		fprintf(f, "\n"); | 		fprintf(f, "\n"); | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -3456,7 +3456,7 @@ bool RTLIL::SigSpec::operator ==(const RTLIL::SigSpec &other) const | ||||||
| 	pack(); | 	pack(); | ||||||
| 	other.pack(); | 	other.pack(); | ||||||
| 
 | 
 | ||||||
| 	if (chunks_.size() != chunks_.size()) | 	if (chunks_.size() != other.chunks_.size()) | ||||||
| 		return false; | 		return false; | ||||||
| 
 | 
 | ||||||
| 	updhash(); | 	updhash(); | ||||||
|  |  | ||||||
|  | @ -482,6 +482,20 @@ void remove_directory(std::string dirname) | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | std::string escape_filename_spaces(const std::string& filename) | ||||||
|  | { | ||||||
|  | 	std::string out; | ||||||
|  | 	out.reserve(filename.size()); | ||||||
|  | 	for (auto c : filename) | ||||||
|  | 	{ | ||||||
|  | 		if (c == ' ') | ||||||
|  | 			out += "\\ "; | ||||||
|  | 		else | ||||||
|  | 			out.push_back(c); | ||||||
|  | 	} | ||||||
|  | 	return out; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| int GetSize(RTLIL::Wire *wire) | int GetSize(RTLIL::Wire *wire) | ||||||
| { | { | ||||||
| 	return wire->width; | 	return wire->width; | ||||||
|  |  | ||||||
|  | @ -257,6 +257,7 @@ std::string make_temp_dir(std::string template_str = "/tmp/yosys_XXXXXX"); | ||||||
| bool check_file_exists(std::string filename, bool is_exec = false); | bool check_file_exists(std::string filename, bool is_exec = false); | ||||||
| bool is_absolute_path(std::string filename); | bool is_absolute_path(std::string filename); | ||||||
| void remove_directory(std::string dirname); | void remove_directory(std::string dirname); | ||||||
|  | std::string escape_filename_spaces(const std::string& filename); | ||||||
| 
 | 
 | ||||||
| template<typename T> int GetSize(const T &obj) { return obj.size(); } | template<typename T> int GetSize(const T &obj) { return obj.size(); } | ||||||
| int GetSize(RTLIL::Wire *wire); | int GetSize(RTLIL::Wire *wire); | ||||||
|  |  | ||||||
|  | @ -291,7 +291,7 @@ struct QwpWorker | ||||||
| 		// gaussian elimination
 | 		// gaussian elimination
 | ||||||
| 		for (int i = 0; i < N; i++) | 		for (int i = 0; i < N; i++) | ||||||
| 		{ | 		{ | ||||||
| 			if (config.verbose && ((i+1) % (N/15)) == 0) | 			if (config.verbose && N > 15 && ((i+1) % (N/15)) == 0) | ||||||
| 				log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N); | 				log("> Solved %d%%: %d/%d\n", (100*(i+1))/N, i+1, N); | ||||||
| 
 | 
 | ||||||
| 			// find best row
 | 			// find best row
 | ||||||
|  |  | ||||||
|  | @ -44,7 +44,10 @@ struct EquivOptPass:public ScriptPass | ||||||
| 		log("        useful for handling architecture-specific primitives.\n"); | 		log("        useful for handling architecture-specific primitives.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("    -assert\n"); | 		log("    -assert\n"); | ||||||
| 		log("        produce an error if the circuits are not equivalent\n"); | 		log("        produce an error if the circuits are not equivalent.\n"); | ||||||
|  | 		log("\n"); | ||||||
|  | 		log("    -undef\n"); | ||||||
|  | 		log("        enable modelling of undef states during equiv_induct.\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("The following commands are executed by this verification command:\n"); | 		log("The following commands are executed by this verification command:\n"); | ||||||
| 		help_script(); | 		help_script(); | ||||||
|  | @ -52,13 +55,14 @@ struct EquivOptPass:public ScriptPass | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	std::string command, techmap_opts; | 	std::string command, techmap_opts; | ||||||
| 	bool assert; | 	bool assert, undef; | ||||||
| 
 | 
 | ||||||
| 	void clear_flags() YS_OVERRIDE | 	void clear_flags() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		command = ""; | 		command = ""; | ||||||
| 		techmap_opts = ""; | 		techmap_opts = ""; | ||||||
| 		assert = false; | 		assert = false; | ||||||
|  | 		undef = false; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE | 	void execute(std::vector < std::string > args, RTLIL::Design * design) YS_OVERRIDE | ||||||
|  | @ -84,6 +88,10 @@ struct EquivOptPass:public ScriptPass | ||||||
| 				assert = true; | 				assert = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
|  | 			if (args[argidx] == "-undef") { | ||||||
|  | 				undef = true; | ||||||
|  | 				continue; | ||||||
|  | 			} | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
|  | @ -139,6 +147,11 @@ struct EquivOptPass:public ScriptPass | ||||||
| 
 | 
 | ||||||
| 		if (check_label("prove")) { | 		if (check_label("prove")) { | ||||||
| 			run("equiv_make gold gate equiv"); | 			run("equiv_make gold gate equiv"); | ||||||
|  | 			if (help_mode) | ||||||
|  | 				run("equiv_induct [-undef] equiv"); | ||||||
|  | 			else if (undef) | ||||||
|  | 				run("equiv_induct -undef equiv"); | ||||||
|  | 			else | ||||||
| 				run("equiv_induct equiv"); | 				run("equiv_induct equiv"); | ||||||
| 			if (help_mode) | 			if (help_mode) | ||||||
| 				run("equiv_status [-assert] equiv"); | 				run("equiv_status [-assert] equiv"); | ||||||
|  |  | ||||||
|  | @ -281,13 +281,26 @@ void rmunused_module_signals(RTLIL::Module *module, bool purge_mode, bool verbos | ||||||
| 				maybe_del_wires.push_back(wire); | 				maybe_del_wires.push_back(wire); | ||||||
| 			} else { | 			} else { | ||||||
| 				log_assert(GetSize(s1) == GetSize(s2)); | 				log_assert(GetSize(s1) == GetSize(s2)); | ||||||
|  | 				Const initval; | ||||||
|  | 				if (wire->attributes.count("\\init")) | ||||||
|  | 					initval = wire->attributes.at("\\init"); | ||||||
|  | 				if (GetSize(initval) != GetSize(wire)) | ||||||
|  | 					initval.bits.resize(GetSize(wire), State::Sx); | ||||||
| 				RTLIL::SigSig new_conn; | 				RTLIL::SigSig new_conn; | ||||||
| 				for (int i = 0; i < GetSize(s1); i++) | 				for (int i = 0; i < GetSize(s1); i++) | ||||||
| 					if (s1[i] != s2[i]) { | 					if (s1[i] != s2[i]) { | ||||||
|  | 						if (s2[i] == State::Sx && (initval[i] == State::S0 || initval[i] == State::S1)) { | ||||||
|  | 							s2[i] = initval[i]; | ||||||
|  | 							initval[i] = State::Sx; | ||||||
|  | 						} | ||||||
| 						new_conn.first.append_bit(s1[i]); | 						new_conn.first.append_bit(s1[i]); | ||||||
| 						new_conn.second.append_bit(s2[i]); | 						new_conn.second.append_bit(s2[i]); | ||||||
| 					} | 					} | ||||||
| 				if (new_conn.first.size() > 0) { | 				if (new_conn.first.size() > 0) { | ||||||
|  | 					if (initval.is_fully_undef()) | ||||||
|  | 						wire->attributes.erase("\\init"); | ||||||
|  | 					else | ||||||
|  | 						wire->attributes.at("\\init") = initval; | ||||||
| 					used_signals.add(new_conn.first); | 					used_signals.add(new_conn.first); | ||||||
| 					used_signals.add(new_conn.second); | 					used_signals.add(new_conn.second); | ||||||
| 					module->connect(new_conn); | 					module->connect(new_conn); | ||||||
|  |  | ||||||
|  | @ -39,6 +39,9 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) | ||||||
| 	SigPool used_signals; | 	SigPool used_signals; | ||||||
| 	SigPool all_signals; | 	SigPool all_signals; | ||||||
| 
 | 
 | ||||||
|  | 	dict<SigBit, pair<Wire*, State>> initbits; | ||||||
|  | 	pool<Wire*> revisit_initwires; | ||||||
|  | 
 | ||||||
| 	for (auto cell : module->cells()) | 	for (auto cell : module->cells()) | ||||||
| 	for (auto &conn : cell->connections()) { | 	for (auto &conn : cell->connections()) { | ||||||
| 		if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) | 		if (!ct.cell_known(cell->type) || ct.cell_output(cell->type, conn.first)) | ||||||
|  | @ -48,6 +51,14 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	for (auto wire : module->wires()) { | 	for (auto wire : module->wires()) { | ||||||
|  | 		if (wire->attributes.count("\\init")) { | ||||||
|  | 			SigSpec sig = sigmap(wire); | ||||||
|  | 			Const initval = wire->attributes.at("\\init"); | ||||||
|  | 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { | ||||||
|  | 				if (initval[i] == State::S0 || initval[i] == State::S1) | ||||||
|  | 					initbits[sig[i]] = make_pair(wire, initval[i]); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
| 		if (wire->port_input) | 		if (wire->port_input) | ||||||
| 			driven_signals.add(sigmap(wire)); | 			driven_signals.add(sigmap(wire)); | ||||||
| 		if (wire->port_output) | 		if (wire->port_output) | ||||||
|  | @ -67,10 +78,38 @@ void replace_undriven(RTLIL::Design *design, RTLIL::Module *module) | ||||||
| 		if (sig.size() == 0) | 		if (sig.size() == 0) | ||||||
| 			continue; | 			continue; | ||||||
| 
 | 
 | ||||||
| 		log_debug("Setting undriven signal in %s to undef: %s\n", RTLIL::id2cstr(module->name), log_signal(c)); | 		Const val(RTLIL::State::Sx, GetSize(sig)); | ||||||
| 		module->connect(RTLIL::SigSig(c, RTLIL::SigSpec(RTLIL::State::Sx, c.width))); | 		for (int i = 0; i < GetSize(sig); i++) { | ||||||
|  | 			SigBit bit = sigmap(sig[i]); | ||||||
|  | 			auto cursor = initbits.find(bit); | ||||||
|  | 			if (cursor != initbits.end()) { | ||||||
|  | 				revisit_initwires.insert(cursor->second.first); | ||||||
|  | 				val[i] = cursor->second.second; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		log_debug("Setting undriven signal in %s to constant: %s = %s\n", RTLIL::id2cstr(module->name), log_signal(sig), log_signal(val)); | ||||||
|  | 		module->connect(sig, val); | ||||||
| 		did_something = true; | 		did_something = true; | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	if (!revisit_initwires.empty()) | ||||||
|  | 	{ | ||||||
|  | 		SigMap sm2(module); | ||||||
|  | 
 | ||||||
|  | 		for (auto wire : revisit_initwires) { | ||||||
|  | 			SigSpec sig = sm2(wire); | ||||||
|  | 			Const initval = wire->attributes.at("\\init"); | ||||||
|  | 			for (int i = 0; i < GetSize(initval) && i < GetSize(wire); i++) { | ||||||
|  | 				if (SigBit(initval[i]) == sig[i]) | ||||||
|  | 					initval[i] = State::Sx; | ||||||
|  | 			} | ||||||
|  | 			if (initval.is_fully_undef()) | ||||||
|  | 				wire->attributes.erase("\\init"); | ||||||
|  | 			else | ||||||
|  | 				wire->attributes["\\init"] = initval; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) | void replace_cell(SigMap &assign_map, RTLIL::Module *module, RTLIL::Cell *cell, std::string info, std::string out_port, RTLIL::SigSpec out_val) | ||||||
|  |  | ||||||
|  | @ -180,6 +180,8 @@ struct WreduceWorker | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			auto info = mi.query(sig_q[i]); | 			auto info = mi.query(sig_q[i]); | ||||||
|  | 			if (info == nullptr) | ||||||
|  | 				return; | ||||||
| 			if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | 			if (!info->is_output && GetSize(info->ports) == 1 && !keep_bits.count(mi.sigmap(sig_q[i]))) { | ||||||
| 				remove_init_bits.insert(sig_q[i]); | 				remove_init_bits.insert(sig_q[i]); | ||||||
| 				sig_d.remove(i); | 				sig_d.remove(i); | ||||||
|  |  | ||||||
|  | @ -1169,6 +1169,7 @@ struct SatPass : public Pass { | ||||||
| 			if (args[argidx] == "-tempinduct-def") { | 			if (args[argidx] == "-tempinduct-def") { | ||||||
| 				tempinduct = true; | 				tempinduct = true; | ||||||
| 				tempinduct_def = true; | 				tempinduct_def = true; | ||||||
|  | 				enable_undef = true; | ||||||
| 				continue; | 				continue; | ||||||
| 			} | 			} | ||||||
| 			if (args[argidx] == "-tempinduct-baseonly") { | 			if (args[argidx] == "-tempinduct-baseonly") { | ||||||
|  |  | ||||||
|  | @ -178,7 +178,17 @@ struct ShregmapTechXilinx7 : ShregmapTech | ||||||
| 
 | 
 | ||||||
| 		// Only map if $shiftx exclusively covers the shift register
 | 		// Only map if $shiftx exclusively covers the shift register
 | ||||||
| 		if (shiftx->type == "$shiftx") { | 		if (shiftx->type == "$shiftx") { | ||||||
| 			if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) | 			if (GetSize(taps) > shiftx->getParam("\\A_WIDTH").as_int()) | ||||||
|  | 				return false; | ||||||
|  | 			// Due to padding the most significant bits of A may be 1'bx,
 | ||||||
|  | 			//   and if so, discount them
 | ||||||
|  | 			if (GetSize(taps) < shiftx->getParam("\\A_WIDTH").as_int()) { | ||||||
|  | 				const SigSpec A = shiftx->getPort("\\A"); | ||||||
|  | 				const int A_width = shiftx->getParam("\\A_WIDTH").as_int(); | ||||||
|  | 				for (int i = GetSize(taps); i < A_width; ++i) | ||||||
|  | 					if (A[i] != RTLIL::Sx) return false; | ||||||
|  | 			} | ||||||
|  | 			else if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int()) | ||||||
| 				return false; | 				return false; | ||||||
| 		} | 		} | ||||||
| 		else if (shiftx->type == "$mux") { | 		else if (shiftx->type == "$mux") { | ||||||
|  |  | ||||||
|  | @ -253,7 +253,7 @@ struct SynthEcp5Pass : public ScriptPass | ||||||
| 			if (!nodffe) | 			if (!nodffe) | ||||||
| 				run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); | 				run("dff2dffe -direct-match $_DFF_* -direct-match $__DFFS_*"); | ||||||
| 			run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | 			run("techmap -D NO_LUT -map +/ecp5/cells_map.v"); | ||||||
| 			run("opt_expr -mux_undef"); | 			run("opt_expr -undriven -mux_undef"); | ||||||
| 			run("simplemap"); | 			run("simplemap"); | ||||||
| 			run("ecp5_ffinit"); | 			run("ecp5_ffinit"); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -225,12 +225,14 @@ struct SynthIce40Pass : public ScriptPass | ||||||
| 			run("proc"); | 			run("proc"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (flatten && check_label("flatten", "(unless -noflatten)")) | 		if (check_label("flatten", "(unless -noflatten)")) | ||||||
| 		{ | 		{ | ||||||
|  | 			if (flatten) { | ||||||
| 				run("flatten"); | 				run("flatten"); | ||||||
| 				run("tribuf -logic"); | 				run("tribuf -logic"); | ||||||
| 				run("deminout"); | 				run("deminout"); | ||||||
| 			} | 			} | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label("coarse")) | 		if (check_label("coarse")) | ||||||
| 		{ | 		{ | ||||||
|  |  | ||||||
|  | @ -25,18 +25,9 @@ | ||||||
| USING_YOSYS_NAMESPACE | USING_YOSYS_NAMESPACE | ||||||
| PRIVATE_NAMESPACE_BEGIN | PRIVATE_NAMESPACE_BEGIN | ||||||
| 
 | 
 | ||||||
| bool check_label(bool &active, std::string run_from, std::string run_to, std::string label) | struct SynthXilinxPass : public ScriptPass | ||||||
| { | { | ||||||
| 	if (label == run_from) | 	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { } | ||||||
| 		active = true; |  | ||||||
| 	if (label == run_to) |  | ||||||
| 		active = false; |  | ||||||
| 	return active; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| struct SynthXilinxPass : public Pass |  | ||||||
| { |  | ||||||
| 	SynthXilinxPass() : Pass("synth_xilinx", "synthesis for Xilinx FPGAs") { } |  | ||||||
| 
 | 
 | ||||||
| 	void help() YS_OVERRIDE | 	void help() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
|  | @ -85,81 +76,30 @@ struct SynthXilinxPass : public Pass | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 		log("The following commands are executed by this synthesis command:\n"); | 		log("The following commands are executed by this synthesis command:\n"); | ||||||
| 		log("\n"); | 		help_script(); | ||||||
| 		log("    begin:\n"); |  | ||||||
| 		log("        read_verilog -lib +/xilinx/cells_sim.v\n"); |  | ||||||
| 		log("        read_verilog -lib +/xilinx/cells_xtra.v\n"); |  | ||||||
| 		log("        read_verilog -lib +/xilinx/brams_bb.v\n"); |  | ||||||
| 		log("        hierarchy -check -top <top>\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    flatten:     (only if -flatten)\n"); |  | ||||||
| 		log("        proc\n"); |  | ||||||
| 		log("        flatten\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    coarse:\n"); |  | ||||||
| 		log("        synth -run coarse\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    bram: (only executed when '-nobram' is not given)\n"); |  | ||||||
| 		log("        memory_bram -rules +/xilinx/brams.txt\n"); |  | ||||||
| 		log("        techmap -map +/xilinx/brams_map.v\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    dram: (only executed when '-nodram' is not given)\n"); |  | ||||||
| 		log("        memory_bram -rules +/xilinx/drams.txt\n"); |  | ||||||
| 		log("        techmap -map +/xilinx/drams_map.v\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    fine:\n"); |  | ||||||
| 		log("        opt -fast -full\n"); |  | ||||||
| 		log("        memory_map\n"); |  | ||||||
| 		log("        dffsr2dff\n"); |  | ||||||
| 		log("        dff2dffe\n"); |  | ||||||
| 		log("        techmap -map +/xilinx/arith_map.v\n"); |  | ||||||
| 		log("        opt -full\n"); |  | ||||||
| 		log("        simplemap t:$dff t:$dffe (without '-nosrl' only)\n"); |  | ||||||
| 		log("        pmux2shiftx (without '-nosrl' only)\n"); |  | ||||||
| 		log("        opt_expr -mux_undef (without '-nosrl' only)\n"); |  | ||||||
| 		log("        shregmap -tech xilinx -minlen 3 (without '-nosrl' only)\n"); |  | ||||||
| 		log("        opt -fast\n"); |  | ||||||
| 		log("        techmap\n"); |  | ||||||
| 		log("        opt -fast\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    map_cells:\n"); |  | ||||||
| 		log("        techmap -map +/xilinx/cells_map.v\n"); |  | ||||||
| 		log("        clean\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    map_luts:\n"); |  | ||||||
| 		log("        techmap -map +/techmap.v -D _NO_POS_SR -map +/xilinx/ff_map.v\n"); |  | ||||||
| 		log("        abc -luts 2:2,3,6:5,10,20 [-dff]\n"); |  | ||||||
| 		log("        clean\n"); |  | ||||||
| 		log("        shregmap -minlen 3 -init -params -enpol any_or_none (without '-nosrl' only)\n"); |  | ||||||
| 		log("        techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); |  | ||||||
| 		log("        dffinit -ff FDRE   Q INIT -ff FDCE   Q INIT -ff FDPE   Q INIT -ff FDSE   Q INIT \\\n"); |  | ||||||
| 		log("                -ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT\n"); |  | ||||||
| 		log("        clean\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    check:\n"); |  | ||||||
| 		log("        hierarchy -check\n"); |  | ||||||
| 		log("        stat\n"); |  | ||||||
| 		log("        check -noinit\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    edif:     (only if -edif)\n"); |  | ||||||
| 		log("        write_edif <file-name>\n"); |  | ||||||
| 		log("\n"); |  | ||||||
| 		log("    blif:     (only if -blif)\n"); |  | ||||||
| 		log("        write_blif <file-name>\n"); |  | ||||||
| 		log("\n"); | 		log("\n"); | ||||||
| 	} | 	} | ||||||
|  | 
 | ||||||
|  | 	std::string top_opt, edif_file, blif_file; | ||||||
|  | 	bool flatten, retime, vpr, nobram, nodram, nosrl; | ||||||
|  | 
 | ||||||
|  | 	void clear_flags() YS_OVERRIDE | ||||||
|  | 	{ | ||||||
|  | 		top_opt = "-auto-top"; | ||||||
|  | 		edif_file.clear(); | ||||||
|  | 		blif_file.clear(); | ||||||
|  | 		flatten = false; | ||||||
|  | 		retime = false; | ||||||
|  | 		vpr = false; | ||||||
|  | 		nobram = false; | ||||||
|  | 		nodram = false; | ||||||
|  | 		nosrl = false; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | 	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 		std::string top_opt = "-auto-top"; |  | ||||||
| 		std::string edif_file; |  | ||||||
| 		std::string blif_file; |  | ||||||
| 		std::string run_from, run_to; | 		std::string run_from, run_to; | ||||||
| 		bool flatten = false; | 		clear_flags(); | ||||||
| 		bool retime = false; |  | ||||||
| 		bool vpr = false; |  | ||||||
| 		bool nobram = false; |  | ||||||
| 		bool nodram = false; |  | ||||||
| 		bool nosrl = false; |  | ||||||
| 
 | 
 | ||||||
| 		size_t argidx; | 		size_t argidx; | ||||||
| 		for (argidx = 1; argidx < args.size(); argidx++) | 		for (argidx = 1; argidx < args.size(); argidx++) | ||||||
|  | @ -215,130 +155,122 @@ struct SynthXilinxPass : public Pass | ||||||
| 		if (!design->full_selection()) | 		if (!design->full_selection()) | ||||||
| 			log_cmd_error("This command only operates on fully selected designs!\n"); | 			log_cmd_error("This command only operates on fully selected designs!\n"); | ||||||
| 
 | 
 | ||||||
| 		bool active = run_from.empty(); |  | ||||||
| 
 |  | ||||||
| 		log_header(design, "Executing SYNTH_XILINX pass.\n"); | 		log_header(design, "Executing SYNTH_XILINX pass.\n"); | ||||||
| 		log_push(); | 		log_push(); | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "begin")) | 		run_script(design, run_from, run_to); | ||||||
|  | 
 | ||||||
|  | 		log_pop(); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	void script() YS_OVERRIDE | ||||||
| 	{ | 	{ | ||||||
| 			if (vpr) { | 		if (check_label("begin")) { | ||||||
| 				Pass::call(design, "read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); | 			if (vpr) | ||||||
| 			} else { | 				run("read_verilog -lib -D_EXPLICIT_CARRY +/xilinx/cells_sim.v"); | ||||||
| 				Pass::call(design, "read_verilog -lib +/xilinx/cells_sim.v"); | 			else | ||||||
|  | 				run("read_verilog -lib +/xilinx/cells_sim.v"); | ||||||
|  | 
 | ||||||
|  | 			run("read_verilog -lib +/xilinx/cells_xtra.v"); | ||||||
|  | 
 | ||||||
|  | 			if (!nobram || help_mode) | ||||||
|  | 				run("read_verilog -lib +/xilinx/brams_bb.v", "(skip if '-nobram')"); | ||||||
|  | 
 | ||||||
|  | 			run(stringf("hierarchy -check %s", top_opt.c_str())); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 			Pass::call(design, "read_verilog -lib +/xilinx/cells_xtra.v"); | 		if (check_label("flatten", "(with '-flatten' only)")) { | ||||||
| 
 | 			if (flatten || help_mode) { | ||||||
| 			if (!nobram) { | 				run("proc"); | ||||||
| 				Pass::call(design, "read_verilog -lib +/xilinx/brams_bb.v"); | 				run("flatten"); | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			Pass::call(design, stringf("hierarchy -check %s", top_opt.c_str())); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (flatten && check_label(active, run_from, run_to, "flatten")) |  | ||||||
| 		{ |  | ||||||
| 			Pass::call(design, "proc"); |  | ||||||
| 			Pass::call(design, "flatten"); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (check_label(active, run_from, run_to, "coarse")) |  | ||||||
| 		{ |  | ||||||
| 			Pass::call(design, "synth -run coarse"); |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		if (check_label(active, run_from, run_to, "bram")) |  | ||||||
| 		{ |  | ||||||
| 			if (!nobram) { |  | ||||||
| 				Pass::call(design, "memory_bram -rules +/xilinx/brams.txt"); |  | ||||||
| 				Pass::call(design, "techmap -map +/xilinx/brams_map.v"); |  | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "dram")) | 		if (check_label("coarse")) { | ||||||
| 		{ | 			run("synth -run coarse"); | ||||||
| 			if (!nodram) { | 		} | ||||||
| 				Pass::call(design, "memory_bram -rules +/xilinx/drams.txt"); | 
 | ||||||
| 				Pass::call(design, "techmap -map +/xilinx/drams_map.v"); | 		if (check_label("bram", "(skip if '-nobram')")) { | ||||||
|  | 			if (!nobram || help_mode) { | ||||||
|  | 				run("memory_bram -rules +/xilinx/brams.txt"); | ||||||
|  | 				run("techmap -map +/xilinx/brams_map.v"); | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "fine")) | 		if (check_label("dram", "(skip if '-nodram')")) { | ||||||
| 		{ | 			if (!nodram || help_mode) { | ||||||
| 			if (!nosrl) { | 				run("memory_bram -rules +/xilinx/drams.txt"); | ||||||
|  | 				run("techmap -map +/xilinx/drams_map.v"); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		if (check_label("fine")) { | ||||||
|  | 			run("opt -fast"); | ||||||
|  | 			run("memory_map"); | ||||||
|  | 			run("dffsr2dff"); | ||||||
|  | 			run("dff2dffe"); | ||||||
|  | 
 | ||||||
| 			// shregmap -tech xilinx can cope with $shiftx and $mux
 | 			// shregmap -tech xilinx can cope with $shiftx and $mux
 | ||||||
| 			//   cells for identifiying variable-length shift registers,
 | 			//   cells for identifiying variable-length shift registers,
 | ||||||
| 			//   so attempt to convert $pmux-es to the former
 | 			//   so attempt to convert $pmux-es to the former
 | ||||||
| 				Pass::call(design, "pmux2shiftx"); | 			if (!nosrl || help_mode) | ||||||
| 			} | 				run("pmux2shiftx", "(skip if '-nosrl')"); | ||||||
| 
 | 
 | ||||||
| 			Pass::call(design, "opt -fast -full"); | 			run("opt -full"); | ||||||
| 			Pass::call(design, "memory_map"); |  | ||||||
| 			Pass::call(design, "dffsr2dff"); |  | ||||||
| 			Pass::call(design, "dff2dffe"); |  | ||||||
| 
 | 
 | ||||||
| 			if (vpr) { | 			if (!vpr || help_mode) | ||||||
| 				Pass::call(design, "techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); | 				run("techmap -map +/xilinx/arith_map.v"); | ||||||
| 			} else { | 			else | ||||||
| 				Pass::call(design, "techmap -map +/xilinx/arith_map.v"); | 				run("techmap -map +/xilinx/arith_map.v -D _EXPLICIT_CARRY"); | ||||||
| 			} |  | ||||||
| 
 | 
 | ||||||
| 			Pass::call(design, "opt -full"); | 			if (!nosrl || help_mode) { | ||||||
| 
 |  | ||||||
| 			if (!nosrl) { |  | ||||||
| 				// shregmap operates on bit-level flops, not word-level,
 | 				// shregmap operates on bit-level flops, not word-level,
 | ||||||
| 				//   so break those down here
 | 				//   so break those down here
 | ||||||
| 				Pass::call(design, "simplemap t:$dff t:$dffe"); | 				run("simplemap t:$dff t:$dffe", "(skip if '-nosrl')"); | ||||||
| 				Pass::call(design, "show -format pdf -prefix show *depth=3*"); |  | ||||||
| 				// shregmap with '-tech xilinx' infers variable length shift regs
 | 				// shregmap with '-tech xilinx' infers variable length shift regs
 | ||||||
| 				Pass::call(design, "shregmap -tech xilinx -minlen 3"); | 				run("shregmap -tech xilinx -minlen 3", "(skip if '-nosrl')"); | ||||||
| 				Pass::call(design, "opt -fast"); |  | ||||||
| 			} | 			} | ||||||
| 
 | 
 | ||||||
| 			Pass::call(design, "techmap"); | 			run("techmap"); | ||||||
| 			Pass::call(design, "opt -fast"); | 			run("opt -fast"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "map_cells")) | 		if (check_label("map_cells")) { | ||||||
| 		{ | 			run("techmap -map +/techmap.v -map +/xilinx/cells_map.v"); | ||||||
| 			Pass::call(design, "techmap -map +/xilinx/cells_map.v"); | 			run("clean"); | ||||||
| 			Pass::call(design, "clean"); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "map_luts")) | 		if (check_label("map_luts")) { | ||||||
| 		{ | 			if (help_mode) | ||||||
| 			Pass::call(design, "abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); | 				run("abc -luts 2:2,3,6:5,10,20 [-dff]"); | ||||||
| 			Pass::call(design, "clean"); | 			else | ||||||
|  | 				run("abc -luts 2:2,3,6:5,10,20" + string(retime ? " -dff" : "")); | ||||||
|  | 			run("clean"); | ||||||
| 			// This shregmap call infers fixed length shift registers after abc
 | 			// This shregmap call infers fixed length shift registers after abc
 | ||||||
| 			//   has performed any necessary retiming
 | 			//   has performed any necessary retiming
 | ||||||
| 			if (!nosrl) | 			if (!nosrl || help_mode) | ||||||
| 				Pass::call(design, "shregmap -minlen 3 -init -params -enpol any_or_none"); | 				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')"); | ||||||
| 			Pass::call(design, "techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); | 			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v"); | ||||||
| 			Pass::call(design, "dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " | 			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT " | ||||||
| 					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); | 					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT"); | ||||||
| 			Pass::call(design, "clean"); | 			run("clean"); | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "check")) | 		if (check_label("check")) { | ||||||
| 		{ | 			run("hierarchy -check"); | ||||||
| 			Pass::call(design, "hierarchy -check"); | 			run("stat"); | ||||||
| 			Pass::call(design, "stat"); | 			run("check -noinit"); | ||||||
| 			Pass::call(design, "check -noinit"); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		if (check_label(active, run_from, run_to, "edif")) | 		if (check_label("edif")) { | ||||||
| 		{ | 			if (!edif_file.empty() || help_mode) | ||||||
| 			if (!edif_file.empty()) | 				run(stringf("write_edif -pvector bra %s", edif_file.c_str())); | ||||||
| 				Pass::call(design, stringf("write_edif -pvector bra %s", edif_file.c_str())); |  | ||||||
| 		} |  | ||||||
| 		if (check_label(active, run_from, run_to, "blif")) |  | ||||||
| 		{ |  | ||||||
| 			if (!blif_file.empty()) |  | ||||||
| 				Pass::call(design, stringf("write_blif %s", edif_file.c_str())); |  | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		log_pop(); | 		if (check_label("blif")) { | ||||||
|  | 			if (!blif_file.empty() || help_mode) | ||||||
|  | 				run(stringf("write_blif %s", edif_file.c_str())); | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| } SynthXilinxPass; | } SynthXilinxPass; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										22
									
								
								tests/memories/firrtl_938.v
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/memories/firrtl_938.v
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,22 @@ | ||||||
|  | module top | ||||||
|  | ( | ||||||
|  | 	input [7:0] data_a, | ||||||
|  | 	input [6:1] addr_a, | ||||||
|  | 	input we_a, clk, | ||||||
|  | 	output reg [7:0] q_a | ||||||
|  | ); | ||||||
|  | 	// Declare the RAM variable | ||||||
|  | 	reg [7:0] ram[63:0]; | ||||||
|  | 
 | ||||||
|  | 	// Port A | ||||||
|  | 	always @ (posedge clk) | ||||||
|  | 	begin | ||||||
|  | 		if (we_a) | ||||||
|  | 		begin | ||||||
|  | 			ram[addr_a] <= data_a; | ||||||
|  | 			q_a <= data_a; | ||||||
|  | 		end | ||||||
|  | 			q_a <= ram[addr_a]; | ||||||
|  | 	end | ||||||
|  | 
 | ||||||
|  | endmodule | ||||||
|  | @ -16,6 +16,7 @@ operators.v	$pow | ||||||
| partsel.v	drops modules | partsel.v	drops modules | ||||||
| process.v	drops modules | process.v	drops modules | ||||||
| realexpr.v	drops modules | realexpr.v	drops modules | ||||||
|  | retime.v	Initial value (11110101) for (retime_test.ff) not supported | ||||||
| scopes.v	original verilog issues ( -x where x isn't declared signed) | scopes.v	original verilog issues ( -x where x isn't declared signed) | ||||||
| sincos.v	$adff | sincos.v	$adff | ||||||
| specify.v	no code (empty module generates error | specify.v	no code (empty module generates error | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue