mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-10-30 19:22:31 +00:00 
			
		
		
		
	Merge branch 'master' of https://github.com/cliffordwolf/yosys into btor
added case for memwr cell that is used in muxes (same cell is used more than one time) corrected bug for xnor and logic_not added pmux cell translation Conflicts: backends/btor/btor.cc
This commit is contained in:
		
						commit
						d3c67ad9b6
					
				
					 513 changed files with 34858 additions and 12079 deletions
				
			
		|  | @ -1,3 +0,0 @@ | |||
| 
 | ||||
| OBJS += backends/autotest/autotest.o | ||||
| 
 | ||||
|  | @ -1,336 +0,0 @@ | |||
| /*
 | ||||
|  *  yosys -- Yosys Open SYnthesis Suite | ||||
|  * | ||||
|  *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at> | ||||
|  *   | ||||
|  *  Permission to use, copy, modify, and/or distribute this software for any | ||||
|  *  purpose with or without fee is hereby granted, provided that the above | ||||
|  *  copyright notice and this permission notice appear in all copies. | ||||
|  *   | ||||
|  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||||
|  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||||
|  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||||
|  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||||
|  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||||
|  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||||
|  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/log.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| #define NUM_ITER 1000 | ||||
| 
 | ||||
| static std::string id(std::string internal_id) | ||||
| { | ||||
| 	const char *str = internal_id.c_str(); | ||||
| 	bool do_escape = false; | ||||
| 
 | ||||
| 	if (*str == '\\') | ||||
| 		str++; | ||||
| 
 | ||||
| 	if ('0' <= *str && *str <= '9') | ||||
| 		do_escape = true; | ||||
| 
 | ||||
| 	for (int i = 0; str[i]; i++) { | ||||
| 		if ('0' <= str[i] && str[i] <= '9') | ||||
| 			continue; | ||||
| 		if ('a' <= str[i] && str[i] <= 'z') | ||||
| 			continue; | ||||
| 		if ('A' <= str[i] && str[i] <= 'Z') | ||||
| 			continue; | ||||
| 		if (str[i] == '_') | ||||
| 			continue; | ||||
| 		do_escape = true; | ||||
| 		break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (do_escape) | ||||
| 		return "\\" + std::string(str) + " "; | ||||
| 	return std::string(str); | ||||
| } | ||||
| 
 | ||||
| static std::string idx(std::string str) | ||||
| { | ||||
| 	if (str[0] == '\\') | ||||
| 		return str.substr(1); | ||||
| 	return str; | ||||
| } | ||||
| 
 | ||||
| static std::string idy(std::string str1, std::string str2 = std::string(), std::string str3 = std::string()) | ||||
| { | ||||
| 	str1 = idx(str1); | ||||
| 	if (!str2.empty()) | ||||
| 		str1 += "_" + idx(str2); | ||||
| 	if (!str3.empty()) | ||||
| 		str1 += "_" + idx(str3); | ||||
| 	return id(str1); | ||||
| } | ||||
| 
 | ||||
| static void autotest(FILE *f, RTLIL::Design *design) | ||||
| { | ||||
| 	fprintf(f, "module testbench;\n\n"); | ||||
| 
 | ||||
| 	fprintf(f, "integer i;\n\n"); | ||||
| 
 | ||||
| 	fprintf(f, "reg [31:0] xorshift128_x = 123456789;\n"); | ||||
| 	fprintf(f, "reg [31:0] xorshift128_y = 362436069;\n"); | ||||
| 	fprintf(f, "reg [31:0] xorshift128_z = 521288629;\n"); | ||||
| 	fprintf(f, "reg [31:0] xorshift128_w = 88675123;\n"); | ||||
| 	fprintf(f, "reg [31:0] xorshift128_t;\n\n"); | ||||
| 	fprintf(f, "task xorshift128;\n"); | ||||
| 	fprintf(f, "begin\n"); | ||||
| 	fprintf(f, "\txorshift128_t = xorshift128_x ^ (xorshift128_x << 11);\n"); | ||||
| 	fprintf(f, "\txorshift128_x = xorshift128_y;\n"); | ||||
| 	fprintf(f, "\txorshift128_y = xorshift128_z;\n"); | ||||
| 	fprintf(f, "\txorshift128_z = xorshift128_w;\n"); | ||||
| 	fprintf(f, "\txorshift128_w = xorshift128_w ^ (xorshift128_w >> 19) ^ xorshift128_t ^ (xorshift128_t >> 8);\n"); | ||||
| 	fprintf(f, "end\n"); | ||||
| 	fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 	for (auto it = design->modules.begin(); it != design->modules.end(); it++) | ||||
| 	{ | ||||
| 		std::map<std::string, int> signal_in; | ||||
| 		std::map<std::string, std::string> signal_const; | ||||
| 		std::map<std::string, int> signal_clk; | ||||
| 		std::map<std::string, int> signal_out; | ||||
| 
 | ||||
| 		RTLIL::Module *mod = it->second; | ||||
| 
 | ||||
| 		if (mod->get_bool_attribute("\\gentb_skip")) | ||||
| 			continue; | ||||
| 
 | ||||
| 		int count_ports = 0; | ||||
| 		log("Generating test bench for module `%s'.\n", it->first.c_str()); | ||||
| 		for (auto it2 = mod->wires.begin(); it2 != mod->wires.end(); it2++) { | ||||
| 			RTLIL::Wire *wire = it2->second; | ||||
| 			if (wire->port_output) { | ||||
| 				count_ports++; | ||||
| 				signal_out[idy("sig", mod->name, wire->name)] = wire->width; | ||||
| 				fprintf(f, "wire [%d:0] %s;\n", wire->width-1, idy("sig", mod->name, wire->name).c_str()); | ||||
| 			} else if (wire->port_input) { | ||||
| 				count_ports++; | ||||
| 				bool is_clksignal = wire->get_bool_attribute("\\gentb_clock"); | ||||
| 				for (auto it3 = mod->processes.begin(); it3 != mod->processes.end(); it3++) | ||||
| 				for (auto it4 = it3->second->syncs.begin(); it4 != it3->second->syncs.end(); it4++) { | ||||
| 					if ((*it4)->type == RTLIL::ST0 || (*it4)->type == RTLIL::ST1) | ||||
| 						continue; | ||||
| 					RTLIL::SigSpec &signal = (*it4)->signal; | ||||
| 					for (size_t i = 0; i < signal.chunks.size(); i++) { | ||||
| 						if (signal.chunks[i].wire == wire) | ||||
| 							is_clksignal = true; | ||||
| 					} | ||||
| 				} | ||||
| 				if (is_clksignal && wire->attributes.count("\\gentb_constant") == 0) { | ||||
| 					signal_clk[idy("sig", mod->name, wire->name)] = wire->width; | ||||
| 				} else { | ||||
| 					signal_in[idy("sig", mod->name, wire->name)] = wire->width; | ||||
| 					if (wire->attributes.count("\\gentb_constant") != 0) | ||||
| 						signal_const[idy("sig", mod->name, wire->name)] = wire->attributes["\\gentb_constant"].as_string(); | ||||
| 				} | ||||
| 				fprintf(f, "reg [%d:0] %s;\n", wire->width-1, idy("sig", mod->name, wire->name).c_str()); | ||||
| 			} | ||||
| 		} | ||||
| 		fprintf(f, "%s %s(\n", id(mod->name).c_str(), idy("uut", mod->name).c_str()); | ||||
| 		for (auto it2 = mod->wires.begin(); it2 != mod->wires.end(); it2++) { | ||||
| 			RTLIL::Wire *wire = it2->second; | ||||
| 			if (wire->port_output || wire->port_input) | ||||
| 				fprintf(f, "\t.%s(%s)%s\n", id(wire->name).c_str(), | ||||
| 						idy("sig", mod->name, wire->name).c_str(), --count_ports ? "," : ""); | ||||
| 		} | ||||
| 		fprintf(f, ");\n\n"); | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "reset").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		int delay_counter = 0; | ||||
| 		for (auto it = signal_in.begin(); it != signal_in.end(); it++) | ||||
| 			fprintf(f, "\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); | ||||
| 		for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) | ||||
| 			fprintf(f, "\t%s <= #%d 0;\n", it->first.c_str(), ++delay_counter*2); | ||||
| 		for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { | ||||
| 			fprintf(f, "\t#100; %s <= 1;\n", it->first.c_str()); | ||||
| 			fprintf(f, "\t#100; %s <= 0;\n", it->first.c_str()); | ||||
| 		} | ||||
| 		delay_counter = 0; | ||||
| 		for (auto it = signal_in.begin(); it != signal_in.end(); it++) | ||||
| 			fprintf(f, "\t%s <= #%d ~0;\n", it->first.c_str(), ++delay_counter*2); | ||||
| 		for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { | ||||
| 			fprintf(f, "\t#100; %s <= 1;\n", it->first.c_str()); | ||||
| 			fprintf(f, "\t#100; %s <= 0;\n", it->first.c_str()); | ||||
| 		} | ||||
| 		delay_counter = 0; | ||||
| 		for (auto it = signal_in.begin(); it != signal_in.end(); it++) { | ||||
| 			if (signal_const.count(it->first) == 0) | ||||
| 				continue; | ||||
| 			fprintf(f, "\t%s <= #%d 'b%s;\n", it->first.c_str(), ++delay_counter*2, signal_const[it->first].c_str()); | ||||
| 		} | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "update_data").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		delay_counter = 0; | ||||
| 		for (auto it = signal_in.begin(); it != signal_in.end(); it++) { | ||||
| 			if (signal_const.count(it->first) > 0) | ||||
| 				continue; | ||||
| 			fprintf(f, "\txorshift128;\n"); | ||||
| 			fprintf(f, "\t%s <= #%d { xorshift128_x, xorshift128_y, xorshift128_z, xorshift128_w };\n", it->first.c_str(), ++delay_counter*2); | ||||
| 		} | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "update_clock").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		if (signal_clk.size()) { | ||||
| 			fprintf(f, "\txorshift128;\n"); | ||||
| 			fprintf(f, "\t{"); | ||||
| 			int total_clock_bits = 0; | ||||
| 			for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { | ||||
| 				fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); | ||||
| 				total_clock_bits += it->second; | ||||
| 			} | ||||
| 			fprintf(f, " } = {"); | ||||
| 			for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) | ||||
| 				fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); | ||||
| 			fprintf(f, " } ^ (%d'b1 << (xorshift128_w %% %d));\n", total_clock_bits, total_clock_bits); | ||||
| 		} | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 		char shorthand = 'A'; | ||||
| 		std::vector<std::string> header1; | ||||
| 		std::string header2 = ""; | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "print_status").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		fprintf(f, "\t$display(\"#OUT# %%b %%b %%b %%t %%d\", {"); | ||||
| 		if (signal_in.size()) | ||||
| 			for (auto it = signal_in.begin(); it != signal_in.end(); it++) { | ||||
| 				fprintf(f, "%s %s", it == signal_in.begin() ? "" : ",", it->first.c_str()); | ||||
| 				int len = it->second; | ||||
| 				if (len > 1) | ||||
| 					header2 += "/", len--; | ||||
| 				while (len > 1) | ||||
| 					header2 += "-", len--; | ||||
| 				if (len > 0) | ||||
| 					header2 += shorthand, len--; | ||||
| 				header1.push_back("    " + it->first); | ||||
| 				header1.back()[0] = shorthand++; | ||||
| 			} | ||||
| 		else { | ||||
| 			fprintf(f, " 1'bx"); | ||||
| 			header2 += "#"; | ||||
| 		} | ||||
| 		fprintf(f, " }, {"); | ||||
| 		header2 += " "; | ||||
| 		if (signal_clk.size()) { | ||||
| 			for (auto it = signal_clk.begin(); it != signal_clk.end(); it++) { | ||||
| 				fprintf(f, "%s %s", it == signal_clk.begin() ? "" : ",", it->first.c_str()); | ||||
| 				int len = it->second; | ||||
| 				if (len > 1) | ||||
| 					header2 += "/", len--; | ||||
| 				while (len > 1) | ||||
| 					header2 += "-", len--; | ||||
| 				if (len > 0) | ||||
| 					header2 += shorthand, len--; | ||||
| 				header1.push_back("    " + it->first); | ||||
| 				header1.back()[0] = shorthand++; | ||||
| 			} | ||||
| 		} else { | ||||
| 			fprintf(f, " 1'bx"); | ||||
| 			header2 += "#"; | ||||
| 		} | ||||
| 		fprintf(f, " }, {"); | ||||
| 		header2 += " "; | ||||
| 		if (signal_out.size()) { | ||||
| 			for (auto it = signal_out.begin(); it != signal_out.end(); it++) { | ||||
| 				fprintf(f, "%s %s", it == signal_out.begin() ? "" : ",", it->first.c_str()); | ||||
| 				int len = it->second; | ||||
| 				if (len > 1) | ||||
| 					header2 += "/", len--; | ||||
| 				while (len > 1) | ||||
| 					header2 += "-", len--; | ||||
| 				if (len > 0) | ||||
| 					header2 += shorthand, len--; | ||||
| 				header1.push_back("    " + it->first); | ||||
| 				header1.back()[0] = shorthand++; | ||||
| 			} | ||||
| 		} else { | ||||
| 			fprintf(f, " 1'bx"); | ||||
| 			header2 += "#"; | ||||
| 		} | ||||
| 		fprintf(f, " }, $time, i);\n"); | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "print_header").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		fprintf(f, "\t$display(\"#OUT#\");\n"); | ||||
| 		for (auto &hdr : header1) | ||||
| 			fprintf(f, "\t$display(\"#OUT#   %s\");\n", hdr.c_str()); | ||||
| 		fprintf(f, "\t$display(\"#OUT#\");\n"); | ||||
| 		fprintf(f, "\t$display(\"#OUT# %s\");\n", header2.c_str()); | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 
 | ||||
| 		fprintf(f, "task %s;\n", idy(mod->name, "test").c_str()); | ||||
| 		fprintf(f, "begin\n"); | ||||
| 		fprintf(f, "\t$display(\"#OUT#\\n#OUT# ==== %s ====\");\n", idy(mod->name).c_str()); | ||||
| 		fprintf(f, "\t%s;\n", idy(mod->name, "reset").c_str()); | ||||
| 		fprintf(f, "\tfor (i=0; i<%d; i=i+1) begin\n", NUM_ITER); | ||||
| 		fprintf(f, "\t\tif (i %% 20 == 0) %s;\n", idy(mod->name, "print_header").c_str()); | ||||
| 		fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "update_data").c_str()); | ||||
| 		fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "update_clock").c_str()); | ||||
| 		fprintf(f, "\t\t#100; %s;\n", idy(mod->name, "print_status").c_str()); | ||||
| 		fprintf(f, "\tend\n"); | ||||
| 		fprintf(f, "end\n"); | ||||
| 		fprintf(f, "endtask\n\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(f, "initial begin\n"); | ||||
| 	fprintf(f, "\t// $dumpfile(\"testbench.vcd\");\n"); | ||||
| 	fprintf(f, "\t// $dumpvars(0, testbench);\n"); | ||||
| 	for (auto it = design->modules.begin(); it != design->modules.end(); it++) | ||||
| 		if (!it->second->get_bool_attribute("\\gentb_skip")) | ||||
| 			fprintf(f, "\t%s;\n", idy(it->first, "test").c_str()); | ||||
| 	fprintf(f, "\t$finish;\n"); | ||||
| 	fprintf(f, "end\n\n"); | ||||
| 
 | ||||
| 	fprintf(f, "endmodule\n"); | ||||
| } | ||||
| 
 | ||||
| struct AutotestBackend : public Backend { | ||||
| 	AutotestBackend() : Backend("autotest", "generate simple test benches") { } | ||||
| 	virtual void help() | ||||
| 	{ | ||||
| 		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | ||||
| 		log("\n"); | ||||
| 		log("    write_autotest [filename]\n"); | ||||
| 		log("\n"); | ||||
| 		log("Automatically create primitive verilog test benches for all modules in the\n"); | ||||
| 		log("design. The generated testbenches toggle the input pins of the module in\n"); | ||||
| 		log("a semi-random manner and dumps the resulting output signals.\n"); | ||||
| 		log("\n"); | ||||
| 		log("This can be used to check the synthesis results for simple circuits by\n"); | ||||
| 		log("comparing the testbench output for the input files and the synthesis results.\n"); | ||||
| 		log("\n"); | ||||
| 		log("The backend automatically detects clock signals. Additionally a signal can\n"); | ||||
| 		log("be forced to be interpreted as clock signal by setting the attribute\n"); | ||||
| 		log("'gentb_clock' on the signal.\n"); | ||||
| 		log("\n"); | ||||
| 		log("The attribute 'gentb_constant' can be used to force a signal to a constant\n"); | ||||
| 		log("value after initialization. This can e.g. be used to force a reset signal\n"); | ||||
| 		log("low in order to explore more inner states in a state machine.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		log_header("Executing AUTOTEST backend (auto-generate pseudo-random test benches).\n"); | ||||
| 		extra_args(f, filename, args, 1); | ||||
| 		autotest(f, design); | ||||
| 	} | ||||
| } AutotestBackend; | ||||
|   | ||||
|  | @ -27,29 +27,30 @@ | |||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| struct BlifDumperConfig | ||||
| { | ||||
| 	bool subckt_mode; | ||||
| 	bool icells_mode; | ||||
| 	bool conn_mode; | ||||
| 	bool impltf_mode; | ||||
| 	bool gates_mode; | ||||
| 	bool param_mode; | ||||
| 
 | ||||
| 	std::string buf_type, buf_in, buf_out; | ||||
| 	std::string true_type, true_out, false_type, false_out; | ||||
| 
 | ||||
| 	BlifDumperConfig() : subckt_mode(false), conn_mode(false), impltf_mode(false) { } | ||||
| 	BlifDumperConfig() : icells_mode(false), conn_mode(false), impltf_mode(false), gates_mode(false), param_mode(false) { } | ||||
| }; | ||||
| 
 | ||||
| struct BlifDumper | ||||
| { | ||||
| 	FILE *f; | ||||
| 	std::ostream &f; | ||||
| 	RTLIL::Module *module; | ||||
| 	RTLIL::Design *design; | ||||
| 	BlifDumperConfig *config; | ||||
| 	CellTypes ct; | ||||
| 
 | ||||
| 	BlifDumper(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig *config) : | ||||
| 	BlifDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig *config) : | ||||
| 			f(f), module(module), design(design), config(config), ct(design) | ||||
| 	{ | ||||
| 	} | ||||
|  | @ -66,34 +67,42 @@ struct BlifDumper | |||
| 		return cstr_buf.back().c_str(); | ||||
| 	} | ||||
| 
 | ||||
| 	const char *cstr(RTLIL::SigSpec sig) | ||||
| 	const char *cstr(RTLIL::SigBit sig) | ||||
| 	{ | ||||
| 		sig.optimize(); | ||||
| 		log_assert(sig.width == 1); | ||||
| 		if (sig.wire == NULL) | ||||
| 			return sig == RTLIL::State::S1 ?  "$true" : "$false"; | ||||
| 
 | ||||
| 		if (sig.chunks.at(0).wire == NULL) | ||||
| 			return sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S1 ?  "$true" : "$false"; | ||||
| 
 | ||||
| 		std::string str = RTLIL::unescape_id(sig.chunks.at(0).wire->name); | ||||
| 		std::string str = RTLIL::unescape_id(sig.wire->name); | ||||
| 		for (size_t i = 0; i < str.size(); i++) | ||||
| 			if (str[i] == '#' || str[i] == '=') | ||||
| 				str[i] = '?'; | ||||
| 
 | ||||
| 		if (sig.chunks.at(0).wire->width != 1) | ||||
| 			str += stringf("[%d]", sig.chunks.at(0).offset); | ||||
| 		if (sig.wire->width != 1) | ||||
| 			str += stringf("[%d]", sig.offset); | ||||
| 
 | ||||
| 		cstr_buf.push_back(str); | ||||
| 		return cstr_buf.back().c_str(); | ||||
| 	} | ||||
| 
 | ||||
| 	const char *subckt_or_gate(std::string cell_type) | ||||
| 	{ | ||||
| 		if (!config->gates_mode) | ||||
| 			return "subckt"; | ||||
| 		if (!design->modules_.count(RTLIL::escape_id(cell_type))) | ||||
| 			return "gate"; | ||||
| 		if (design->modules_.at(RTLIL::escape_id(cell_type))->get_bool_attribute("\\blackbox")) | ||||
| 			return "gate"; | ||||
| 		return "subckt"; | ||||
| 	} | ||||
| 
 | ||||
| 	void dump() | ||||
| 	{ | ||||
| 		fprintf(f, "\n"); | ||||
| 		fprintf(f, ".model %s\n", cstr(module->name)); | ||||
| 		f << stringf("\n"); | ||||
| 		f << stringf(".model %s\n", cstr(module->name)); | ||||
| 
 | ||||
| 		std::map<int, RTLIL::Wire*> inputs, outputs; | ||||
| 
 | ||||
| 		for (auto &wire_it : module->wires) { | ||||
| 		for (auto &wire_it : module->wires_) { | ||||
| 			RTLIL::Wire *wire = wire_it.second; | ||||
| 			if (wire->port_input) | ||||
| 				inputs[wire->port_id] = wire; | ||||
|  | @ -101,107 +110,150 @@ struct BlifDumper | |||
| 				outputs[wire->port_id] = wire; | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(f, ".inputs"); | ||||
| 		f << stringf(".inputs"); | ||||
| 		for (auto &it : inputs) { | ||||
| 			RTLIL::Wire *wire = it.second; | ||||
| 			for (int i = 0; i < wire->width; i++) | ||||
| 				fprintf(f, " %s", cstr(RTLIL::SigSpec(wire, 1, i))); | ||||
| 				f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i))); | ||||
| 		} | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 
 | ||||
| 		fprintf(f, ".outputs"); | ||||
| 		f << stringf(".outputs"); | ||||
| 		for (auto &it : outputs) { | ||||
| 			RTLIL::Wire *wire = it.second; | ||||
| 			for (int i = 0; i < wire->width; i++) | ||||
| 				fprintf(f, " %s", cstr(RTLIL::SigSpec(wire, 1, i))); | ||||
| 				f << stringf(" %s", cstr(RTLIL::SigSpec(wire, i))); | ||||
| 		} | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 
 | ||||
| 		if (!config->impltf_mode) { | ||||
| 			if (!config->false_type.empty()) | ||||
| 				fprintf(f, ".subckt %s %s=$false\n", config->false_type.c_str(), config->false_out.c_str()); | ||||
| 				f << stringf(".%s %s %s=$false\n", subckt_or_gate(config->false_type), | ||||
| 						config->false_type.c_str(), config->false_out.c_str()); | ||||
| 			else | ||||
| 				fprintf(f, ".names $false\n"); | ||||
| 				f << stringf(".names $false\n"); | ||||
| 			if (!config->true_type.empty()) | ||||
| 				fprintf(f, ".subckt %s %s=$true\n", config->true_type.c_str(), config->true_out.c_str()); | ||||
| 				f << stringf(".%s %s %s=$true\n", subckt_or_gate(config->true_type), | ||||
| 						config->true_type.c_str(), config->true_out.c_str()); | ||||
| 			else | ||||
| 				fprintf(f, ".names $true\n1\n"); | ||||
| 				f << stringf(".names $true\n1\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &cell_it : module->cells) | ||||
| 		for (auto &cell_it : module->cells_) | ||||
| 		{ | ||||
| 			RTLIL::Cell *cell = cell_it.second; | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_INV_") { | ||||
| 				fprintf(f, ".names %s %s\n0 1\n", | ||||
| 						cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\Y"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_NOT_") { | ||||
| 				f << stringf(".names %s %s\n0 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\Y"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_AND_") { | ||||
| 				fprintf(f, ".names %s %s %s\n11 1\n", | ||||
| 						cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_AND_") { | ||||
| 				f << stringf(".names %s %s %s\n11 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_OR_") { | ||||
| 				fprintf(f, ".names %s %s %s\n1- 1\n-1 1\n", | ||||
| 						cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_OR_") { | ||||
| 				f << stringf(".names %s %s %s\n1- 1\n-1 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_XOR_") { | ||||
| 				fprintf(f, ".names %s %s %s\n10 1\n01 1\n", | ||||
| 						cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), cstr(cell->connections.at("\\Y"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_XOR_") { | ||||
| 				f << stringf(".names %s %s %s\n10 1\n01 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), cstr(cell->getPort("\\Y"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_MUX_") { | ||||
| 				fprintf(f, ".names %s %s %s %s\n1-0 1\n-11 1\n", | ||||
| 						cstr(cell->connections.at("\\A")), cstr(cell->connections.at("\\B")), | ||||
| 						cstr(cell->connections.at("\\S")), cstr(cell->connections.at("\\Y"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_MUX_") { | ||||
| 				f << stringf(".names %s %s %s %s\n1-0 1\n-11 1\n", | ||||
| 						cstr(cell->getPort("\\A")), cstr(cell->getPort("\\B")), | ||||
| 						cstr(cell->getPort("\\S")), cstr(cell->getPort("\\Y"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_DFF_N_") { | ||||
| 				fprintf(f, ".latch %s %s fe %s\n", | ||||
| 						cstr(cell->connections.at("\\D")), cstr(cell->connections.at("\\Q")), cstr(cell->connections.at("\\C"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_DFF_N_") { | ||||
| 				f << stringf(".latch %s %s fe %s\n", | ||||
| 						cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), cstr(cell->getPort("\\C"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			if (!config->subckt_mode && cell->type == "$_DFF_P_") { | ||||
| 				fprintf(f, ".latch %s %s re %s\n", | ||||
| 						cstr(cell->connections.at("\\D")), cstr(cell->connections.at("\\Q")), cstr(cell->connections.at("\\C"))); | ||||
| 			if (!config->icells_mode && cell->type == "$_DFF_P_") { | ||||
| 				f << stringf(".latch %s %s re %s\n", | ||||
| 						cstr(cell->getPort("\\D")), cstr(cell->getPort("\\Q")), cstr(cell->getPort("\\C"))); | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			fprintf(f, ".subckt %s", cstr(cell->type)); | ||||
| 			for (auto &conn : cell->connections) | ||||
| 			for (int i = 0; i < conn.second.width; i++) { | ||||
| 				if (conn.second.width == 1) | ||||
| 					fprintf(f, " %s", cstr(conn.first)); | ||||
| 			if (!config->icells_mode && cell->type == "$lut") { | ||||
| 				f << stringf(".names"); | ||||
| 				auto &inputs = cell->getPort("\\A"); | ||||
| 				auto width = cell->parameters.at("\\WIDTH").as_int(); | ||||
| 				log_assert(inputs.size() == width); | ||||
| 				for (int i = 0; i < inputs.size(); i++) { | ||||
| 					f << stringf(" %s", cstr(inputs.extract(i, 1))); | ||||
| 				} | ||||
| 				auto &output = cell->getPort("\\Y"); | ||||
| 				log_assert(output.size() == 1); | ||||
| 				f << stringf(" %s", cstr(output)); | ||||
| 				f << stringf("\n"); | ||||
| 				auto mask = cell->parameters.at("\\LUT").as_string(); | ||||
| 				for (int i = 0; i < (1 << width); i++) { | ||||
| 					if (mask[i] == '0') continue; | ||||
| 					for (int j = width-1; j >= 0; j--) { | ||||
| 						f << ((i>>j)&1 ? '1' : '0'); | ||||
| 					} | ||||
| 					f << stringf(" %c\n", mask[i]); | ||||
| 				} | ||||
| 				continue; | ||||
| 			} | ||||
| 
 | ||||
| 			f << stringf(".%s %s", subckt_or_gate(cell->type.str()), cstr(cell->type)); | ||||
| 			for (auto &conn : cell->connections()) | ||||
| 			for (int i = 0; i < conn.second.size(); i++) { | ||||
| 				if (conn.second.size() == 1) | ||||
| 					f << stringf(" %s", cstr(conn.first)); | ||||
| 				else | ||||
| 					fprintf(f, " %s[%d]", cstr(conn.first), i); | ||||
| 				fprintf(f, "=%s", cstr(conn.second.extract(i, 1))); | ||||
| 					f << stringf(" %s[%d]", cstr(conn.first), i); | ||||
| 				f << stringf("=%s", cstr(conn.second.extract(i, 1))); | ||||
| 			} | ||||
| 			fprintf(f, "\n"); | ||||
| 			f << stringf("\n"); | ||||
| 
 | ||||
| 			if (config->param_mode) | ||||
| 				for (auto ¶m : cell->parameters) { | ||||
| 					f << stringf(".param %s ", RTLIL::id2cstr(param.first)); | ||||
| 					if (param.second.flags & RTLIL::CONST_FLAG_STRING) { | ||||
| 						std::string str = param.second.decode_string(); | ||||
| 						f << stringf("\""); | ||||
| 						for (char ch : str) | ||||
| 							if (ch == '"' || ch == '\\') | ||||
| 								f << stringf("\\%c", ch); | ||||
| 							else if (ch < 32 || ch >= 127) | ||||
| 								f << stringf("\\%03o", ch); | ||||
| 							else | ||||
| 								f << stringf("%c", ch); | ||||
| 						f << stringf("\"\n"); | ||||
| 					} else | ||||
| 						f << stringf("%s\n", param.second.as_string().c_str()); | ||||
| 				} | ||||
| 		} | ||||
| 
 | ||||
| 		for (auto &conn : module->connections) | ||||
| 		for (int i = 0; i < conn.first.width; i++) | ||||
| 		for (auto &conn : module->connections()) | ||||
| 		for (int i = 0; i < conn.first.size(); i++) | ||||
| 			if (config->conn_mode) | ||||
| 				fprintf(f, ".conn %s %s\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); | ||||
| 				f << stringf(".conn %s %s\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); | ||||
| 			else if (!config->buf_type.empty()) | ||||
| 				fprintf(f, ".subckt %s %s=%s %s=%s\n", config->buf_type.c_str(), config->buf_in.c_str(), cstr(conn.second.extract(i, 1)), | ||||
| 				f << stringf(".%s %s %s=%s %s=%s\n", subckt_or_gate(config->buf_type), config->buf_type.c_str(), config->buf_in.c_str(), cstr(conn.second.extract(i, 1)), | ||||
| 						config->buf_out.c_str(), cstr(conn.first.extract(i, 1))); | ||||
| 			else | ||||
| 				fprintf(f, ".names %s %s\n1 1\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); | ||||
| 				f << stringf(".names %s %s\n1 1\n", cstr(conn.second.extract(i, 1)), cstr(conn.first.extract(i, 1))); | ||||
| 
 | ||||
| 
 | ||||
| 		fprintf(f, ".end\n"); | ||||
| 		f << stringf(".end\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	static void dump(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig &config) | ||||
| 	static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BlifDumperConfig &config) | ||||
| 	{ | ||||
| 		BlifDumper dumper(f, module, design, &config); | ||||
| 		dumper.dump(); | ||||
|  | @ -228,23 +280,30 @@ struct BlifBackend : public Backend { | |||
| 		log("    -false <cell-type> <out-port>\n"); | ||||
| 		log("        use the specified cell types to drive nets that are constant 1 or 0\n"); | ||||
| 		log("\n"); | ||||
| 		log("The following options can be usefull when the generated file is not going to be\n"); | ||||
| 		log("The following options can be useful when the generated file is not going to be\n"); | ||||
| 		log("read by a BLIF parser but a custom tool. It is recommended to not name the output\n"); | ||||
| 		log("file *.blif when any of this options is used.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -subckt\n"); | ||||
| 		log("    -icells\n"); | ||||
| 		log("        do not translate Yosys's internal gates to generic BLIF logic\n"); | ||||
| 		log("        functions. Instead create .subckt lines for all cells.\n"); | ||||
| 		log("        functions. Instead create .subckt or .gate lines for all cells.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -gates\n"); | ||||
| 		log("        print .gate instead of .subckt lines for all cells that are not\n"); | ||||
| 		log("        instantiations of other modules from this design.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -conn\n"); | ||||
| 		log("        do not generate buffers for connected wires. instead use the\n"); | ||||
| 		log("        non-standard .conn statement.\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -param\n"); | ||||
| 		log("        use the non-standard .param statement to write module parameters\n"); | ||||
| 		log("\n"); | ||||
| 		log("    -impltf\n"); | ||||
| 		log("        do not write definitions for the $true and $false wires.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		std::string top_module_name; | ||||
| 		std::string buf_type, buf_in, buf_out; | ||||
|  | @ -277,14 +336,22 @@ struct BlifBackend : public Backend { | |||
| 				config.false_out = args[++argidx]; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-subckt") { | ||||
| 				config.subckt_mode = true; | ||||
| 			if (args[argidx] == "-icells") { | ||||
| 				config.icells_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-gates") { | ||||
| 				config.gates_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-conn") { | ||||
| 				config.conn_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-param") { | ||||
| 				config.param_mode = true; | ||||
| 				continue; | ||||
| 			} | ||||
| 			if (args[argidx] == "-impltf") { | ||||
| 				config.impltf_mode = true; | ||||
| 				continue; | ||||
|  | @ -294,15 +361,15 @@ struct BlifBackend : public Backend { | |||
| 		extra_args(f, filename, args, argidx); | ||||
| 
 | ||||
| 		if (top_module_name.empty()) | ||||
| 			for (auto & mod_it:design->modules) | ||||
| 			for (auto & mod_it:design->modules_) | ||||
| 				if (mod_it.second->get_bool_attribute("\\top")) | ||||
| 					top_module_name = mod_it.first; | ||||
| 					top_module_name = mod_it.first.str(); | ||||
| 
 | ||||
| 		fprintf(f, "# Generated by %s\n", yosys_version_str); | ||||
| 		*f << stringf("# Generated by %s\n", yosys_version_str); | ||||
| 
 | ||||
| 		std::vector<RTLIL::Module*> mod_list; | ||||
| 
 | ||||
| 		for (auto module_it : design->modules) | ||||
| 		for (auto module_it : design->modules_) | ||||
| 		{ | ||||
| 			RTLIL::Module *module = module_it.second; | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
|  | @ -314,7 +381,7 @@ struct BlifBackend : public Backend { | |||
| 				log_error("Found munmapped emories in module %s: unmapped memories are not supported in BLIF backend!\n", RTLIL::id2cstr(module->name)); | ||||
| 
 | ||||
| 			if (module->name == RTLIL::escape_id(top_module_name)) { | ||||
| 				BlifDumper::dump(f, module, design, config); | ||||
| 				BlifDumper::dump(*f, module, design, config); | ||||
| 				top_module_name.clear(); | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -326,7 +393,7 @@ struct BlifBackend : public Backend { | |||
| 			log_error("Can't find top module `%s'!\n", top_module_name.c_str()); | ||||
| 
 | ||||
| 		for (auto module : mod_list) | ||||
| 			BlifDumper::dump(f, module, design, config); | ||||
| 			BlifDumper::dump(*f, module, design, config); | ||||
| 	} | ||||
| } BlifBackend; | ||||
| 
 | ||||
|  |  | |||
|  | @ -28,7 +28,6 @@ | |||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| #include <math.h> | ||||
| 
 | ||||
| struct BtorDumperConfig | ||||
|  | @ -46,9 +45,9 @@ struct BtorDumperConfig | |||
| struct WireInfo | ||||
| { | ||||
| 	RTLIL::IdString cell_name; | ||||
| 	RTLIL::SigChunk *chunk; | ||||
| 	const RTLIL::SigChunk *chunk; | ||||
| 
 | ||||
| 	WireInfo(RTLIL::IdString c, RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { } | ||||
| 	WireInfo(RTLIL::IdString c, const RTLIL::SigChunk* ch) : cell_name(c), chunk(ch) { } | ||||
| }; | ||||
| 
 | ||||
| struct WireInfoOrder | ||||
|  | @ -61,7 +60,7 @@ struct WireInfoOrder | |||
| 
 | ||||
| struct BtorDumper | ||||
| { | ||||
| 	FILE *f; | ||||
| 	std::ostream &f; | ||||
| 	RTLIL::Module *module; | ||||
| 	RTLIL::Design *design; | ||||
| 	BtorDumperConfig *config; | ||||
|  | @ -75,14 +74,14 @@ struct BtorDumper | |||
| 	std::string str;//temp string for writing file
 | ||||
| 	std::map<RTLIL::IdString, bool> basic_wires;//input wires and registers	
 | ||||
| 	RTLIL::IdString curr_cell; //current cell being dumped
 | ||||
|         std::set<int> mem_next; //if memory (line_number) already has next
 | ||||
|         std::map<std::string, std::string> cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation
 | ||||
| 	BtorDumper(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) : | ||||
| 			f(f), module(module), design(design), config(config), ct(design), sigmap(module) | ||||
| 	std::map<std::string, std::string> cell_type_translation, s_cell_type_translation; //RTLIL to BTOR translation
 | ||||
| 	std::set<int> mem_next; //if memory (line_number) already has next
 | ||||
|     	BtorDumper(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig *config) : | ||||
|     		f(f), module(module), design(design), config(config), ct(design), sigmap(module) | ||||
| 	{ | ||||
| 		line_num=0; | ||||
| 		str.clear(); | ||||
| 		for(auto it=module->wires.begin(); it!=module->wires.end(); ++it) | ||||
| 		for(auto it=module->wires_.begin(); it!=module->wires_.end(); ++it) | ||||
| 		{ | ||||
| 			if(it->second->port_input) | ||||
| 			{ | ||||
|  | @ -113,6 +112,8 @@ struct BtorDumper | |||
| 		cell_type_translation["$shl"] = "sll"; | ||||
| 		cell_type_translation["$sshr"] = "sra"; | ||||
| 		cell_type_translation["$sshl"] = "sll"; | ||||
| 		cell_type_translation["$shift"] = "srl"; | ||||
| 		cell_type_translation["$shiftx"] = "srl"; | ||||
| 		cell_type_translation["$lt"] = "ult"; | ||||
| 		cell_type_translation["$le"] = "ulte"; | ||||
| 		cell_type_translation["$gt"] = "ugt"; | ||||
|  | @ -174,7 +175,7 @@ struct BtorDumper | |||
| 				++line_num; | ||||
| 				line_ref[wire->name]=line_num;			 | ||||
| 				str = stringf("%d var %d %s", line_num, wire->width, cstr(wire->name)); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				return line_num; | ||||
| 			} | ||||
| 			else return it->second; | ||||
|  | @ -194,11 +195,11 @@ struct BtorDumper | |||
| 					if(cell_id == curr_cell) | ||||
| 						break; | ||||
| 					log(" -- found cell %s\n", cstr(cell_id)); | ||||
| 					RTLIL::Cell* cell = module->cells.at(cell_id); | ||||
| 					RTLIL::SigSpec* cell_output = get_cell_output(cell); | ||||
| 					RTLIL::Cell* cell = module->cells_.at(cell_id); | ||||
| 					const RTLIL::SigSpec* cell_output = get_cell_output(cell); | ||||
| 					int cell_line = dump_cell(cell);				 | ||||
| 
 | ||||
| 					if(dep_set.size()==1 && wire->width == cell_output->width) | ||||
| 					if(dep_set.size()==1 && wire->width == cell_output->size()) | ||||
| 					{ | ||||
| 						wire_line = cell_line; | ||||
| 						break; | ||||
|  | @ -207,22 +208,22 @@ struct BtorDumper | |||
| 					{ | ||||
| 						int prev_wire_line=0; //previously dumped wire line
 | ||||
| 						int start_bit=0; | ||||
| 						for(unsigned j=0; j<cell_output->chunks.size(); ++j) | ||||
| 						for(unsigned j=0; j<cell_output->chunks().size(); ++j) | ||||
| 						{ | ||||
| 							start_bit+=cell_output->chunks[j].width; | ||||
| 							if(cell_output->chunks[j].wire->name == wire->name) | ||||
| 							start_bit+=cell_output->chunks().at(j).width; | ||||
| 							if(cell_output->chunks().at(j).wire->name == wire->name) | ||||
| 							{ | ||||
| 								prev_wire_line = wire_line; | ||||
| 								wire_line = ++line_num; | ||||
| 								str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks[j].width, | ||||
|  									cell_line, start_bit-1, start_bit-cell_output->chunks[j].width); | ||||
| 								fprintf(f, "%s\n", str.c_str()); | ||||
| 								wire_width += cell_output->chunks[j].width; | ||||
| 								str = stringf("%d slice %d %d %d %d;1", line_num, cell_output->chunks().at(j).width, | ||||
| 									cell_line, start_bit-1, start_bit-cell_output->chunks().at(j).width); | ||||
| 								f << stringf("%s\n", str.c_str()); | ||||
| 								wire_width += cell_output->chunks().at(j).width; | ||||
| 								if(prev_wire_line!=0) | ||||
| 								{ | ||||
| 									++line_num; | ||||
| 									str = stringf("%d concat %d %d %d", line_num, wire_width, wire_line, prev_wire_line); | ||||
| 									fprintf(f, "%s\n", str.c_str()); | ||||
| 									f << stringf("%s\n", str.c_str()); | ||||
| 									wire_line = line_num; | ||||
| 								} | ||||
| 							} | ||||
|  | @ -233,7 +234,7 @@ struct BtorDumper | |||
| 				{ | ||||
| 					log(" - checking sigmap\n");						 | ||||
| 					RTLIL::SigSpec s = RTLIL::SigSpec(wire); | ||||
| 					wire_line = dump_sigspec(&s, s.width); | ||||
| 					wire_line = dump_sigspec(&s, s.size()); | ||||
| 					line_ref[wire->name]=wire_line; | ||||
| 				} | ||||
| 				line_ref[wire->name]=wire_line; | ||||
|  | @ -245,7 +246,7 @@ struct BtorDumper | |||
| 				return it->second; | ||||
| 			} | ||||
| 		} | ||||
| 		assert(false); | ||||
| 		log_abort(); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
|  | @ -259,7 +260,7 @@ struct BtorDumper | |||
| 			int address_bits = ceil(log(memory->size)/log(2)); | ||||
| 			str = stringf("%d array %d %d", line_num, memory->width, address_bits); | ||||
| 			line_ref[memory->name]=line_num;			 | ||||
| 			fprintf(f, "%s\n", str.c_str()); | ||||
| 			f << stringf("%s\n", str.c_str()); | ||||
| 			return line_num; | ||||
| 		} | ||||
| 		else return it->second; | ||||
|  | @ -279,12 +280,12 @@ struct BtorDumper | |||
| 
 | ||||
| 			++line_num; | ||||
| 			str = stringf("%d const %d %s", line_num, width, data_str.c_str()); | ||||
| 			fprintf(f, "%s\n", str.c_str()); | ||||
| 			f << stringf("%s\n", str.c_str()); | ||||
| 			return line_num; | ||||
| 		} | ||||
| 		else | ||||
| 			log("writing const error\n");		 | ||||
| 		assert(false); | ||||
| 		log_abort(); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	 | ||||
|  | @ -294,7 +295,8 @@ struct BtorDumper | |||
| 		int l=-1; | ||||
| 		if(chunk->wire == NULL) | ||||
| 		{ | ||||
| 			l=dump_const(&chunk->data, chunk->width, chunk->offset);			 | ||||
| 			RTLIL::Const data_const(chunk->data); | ||||
| 			l=dump_const(&data_const, chunk->width, chunk->offset);			 | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
|  | @ -303,11 +305,11 @@ struct BtorDumper | |||
| 			else  | ||||
| 			{ | ||||
| 				int wire_line_num = dump_wire(chunk->wire); | ||||
| 				assert(wire_line_num>0); | ||||
| 				log_assert(wire_line_num>0); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d slice %d %d %d %d;2", line_num, chunk->width, wire_line_num,  | ||||
| 					chunk->width + chunk->offset - 1, chunk->offset); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				l = line_num;				  | ||||
| 			} | ||||
| 		} | ||||
|  | @ -322,24 +324,24 @@ struct BtorDumper | |||
| 		auto it = sig_ref.find(s); | ||||
| 		if(it == std::end(sig_ref)) | ||||
| 		{ | ||||
| 			if (s.chunks.size() == 1)  | ||||
| 			if (s.is_chunk()) | ||||
| 			{ | ||||
| 				l = dump_sigchunk(&s.chunks[0]); | ||||
| 				l = dump_sigchunk(&s.chunks().front()); | ||||
| 			}  | ||||
| 			else  | ||||
| 			{ | ||||
| 				int l1, l2, w1, w2; | ||||
| 				l1 = dump_sigchunk(&s.chunks[0]); | ||||
| 				assert(l1>0); | ||||
| 				w1 = s.chunks[0].width; | ||||
| 				for (unsigned i=1; i < s.chunks.size(); ++i) | ||||
| 				l1 = dump_sigchunk(&s.chunks().front()); | ||||
| 				log_assert(l1>0); | ||||
| 				w1 = s.chunks().front().width; | ||||
| 				for (unsigned i=1; i < s.chunks().size(); ++i) | ||||
| 				{ | ||||
| 					l2 = dump_sigchunk(&s.chunks[i]); | ||||
| 					assert(l2>0); | ||||
| 					w2 = s.chunks[i].width; | ||||
| 					l2 = dump_sigchunk(&s.chunks().at(i)); | ||||
| 					log_assert(l2>0); | ||||
| 					w2 = s.chunks().at(i).width; | ||||
| 					++line_num; | ||||
| 					str = stringf("%d concat %d %d %d", line_num, w1+w2, l2, l1); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					l1=line_num; | ||||
| 					w1+=w2; | ||||
| 				} | ||||
|  | @ -352,30 +354,30 @@ struct BtorDumper | |||
| 			l = it->second; | ||||
| 		} | ||||
| 		 | ||||
| 		if (expected_width != s.width) | ||||
| 		if (expected_width != s.size()) | ||||
| 		{ | ||||
| 			log(" - changing width of sigspec\n"); | ||||
| 			//TODO: this block may not be needed anymore, due to explicit type conversion by "splice" command
 | ||||
| 			if(expected_width > s.width) | ||||
| 			if(expected_width > s.size()) | ||||
| 			{ | ||||
| 				//TODO: case the signal is signed
 | ||||
| 				++line_num; | ||||
| 				str = stringf ("%d zero %d", line_num, expected_width - s.width); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				str = stringf ("%d zero %d", line_num, expected_width - s.size()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf ("%d concat %d %d %d", line_num, expected_width, line_num-1, l); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				l = line_num; | ||||
| 			} | ||||
| 			else if(expected_width < s.width) | ||||
| 			else if(expected_width < s.size()) | ||||
| 			{ | ||||
| 				++line_num; | ||||
| 				str = stringf ("%d slice %d %d %d %d;3", line_num, expected_width, l, expected_width-1, 0); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				l = line_num; | ||||
| 			} | ||||
| 		} | ||||
| 		assert(l>0); | ||||
| 		log_assert(l>0); | ||||
| 		return l; | ||||
| 	} | ||||
| 	 | ||||
|  | @ -389,29 +391,29 @@ struct BtorDumper | |||
| 			if(cell->type == "$assert") | ||||
| 			{ | ||||
| 				log("writing assert cell - %s\n", cstr(cell->type)); | ||||
| 				const RTLIL::SigSpec* expr = &cell->connections.at(RTLIL::IdString("\\A")); | ||||
| 				const RTLIL::SigSpec* en = &cell->connections.at(RTLIL::IdString("\\EN")); | ||||
| 				assert(expr->width == 1); | ||||
| 				assert(en->width == 1); | ||||
| 				const RTLIL::SigSpec* expr = &cell->getPort(RTLIL::IdString("\\A")); | ||||
| 				const RTLIL::SigSpec* en = &cell->getPort(RTLIL::IdString("\\EN")); | ||||
| 				log_assert(expr->size() == 1); | ||||
| 				log_assert(en->size() == 1); | ||||
| 				int expr_line = dump_sigspec(expr, 1); | ||||
| 				int en_line = dump_sigspec(en, 1); | ||||
| 				int one_line = ++line_num; | ||||
| 				str = stringf("%d one 1", line_num); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at("$eq").c_str(), 1, en_line, one_line); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), 1, line_num-1, | ||||
| 					expr_line, one_line); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				int cell_line = ++line_num; | ||||
| 				str = stringf("%d %s %d %d", line_num, cell_type_translation.at("$assert").c_str(), 1, -1*(line_num-1)); | ||||
| 				//multiplying the line number with -1, which means logical negation
 | ||||
| 				//the reason for negative sign is that the properties in btor are given as "negation of the original property"
 | ||||
| 				//bug identified by bobosoft
 | ||||
| 				//http://www.reddit.com/r/yosys/comments/1w3xig/btor_backend_bug/
 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				line_ref[cell->name]=cell_line; | ||||
| 			} | ||||
| 			//unary cells
 | ||||
|  | @ -422,20 +424,20 @@ struct BtorDumper | |||
| 				int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
| 				w = w>output_width ? w:output_width; //padding of w
 | ||||
| 				int l = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), w);				 | ||||
| 				int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w);				 | ||||
| 				int cell_line = l; | ||||
| 				if(cell->type != "$pos") | ||||
| 				{	 | ||||
| 					cell_line = ++line_num; | ||||
| 					bool reduced = (cell->type == "$not" || cell->type == "$neg") ? false : true; | ||||
| 					str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type).c_str(), reduced?output_width:w, l); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					str = stringf ("%d %s %d %d", cell_line, cell_type_translation.at(cell->type.str()).c_str(), reduced?output_width:w, l); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 				} | ||||
| 				if(output_width < w && (cell->type == "$not" || cell->type == "$neg" || cell->type == "$pos")) | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d slice %d %d %d %d;4", line_num, output_width, cell_line, output_width-1, 0); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					cell_line = line_num; | ||||
| 				}				 | ||||
| 				line_ref[cell->name]=cell_line; | ||||
|  | @ -445,25 +447,23 @@ struct BtorDumper | |||
| 				log("writing unary cell - %s\n", cstr(cell->type)); | ||||
| 				int w = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
| 				assert(output_width == 1); | ||||
| 				int l = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), w); | ||||
| 				log_assert(output_width == 1); | ||||
| 				int l = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), w); | ||||
| 				if(cell->type == "$logic_not" && w > 1) | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
|                                         l = line_num; | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 				} | ||||
| 				else if(cell->type == "$reduce_xnor") | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_xor").c_str(), output_width, l); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
|                                         l = line_num; | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 				}		 | ||||
| 				++line_num; | ||||
| 				str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$not").c_str(), output_width, l); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			//binary cells
 | ||||
|  | @ -473,7 +473,7 @@ struct BtorDumper | |||
| 			{ | ||||
| 				log("writing binary cell - %s\n", cstr(cell->type)); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
| 				assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || | ||||
| 				log_assert(!(cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || | ||||
| 					cell->type == "$ge" || cell->type == "$gt") || output_width == 1); | ||||
| 				bool l1_signed = cell->parameters.at(RTLIL::IdString("\\A_SIGNED")).as_bool(); | ||||
| 				bool l2_signed = cell->parameters.at(RTLIL::IdString("\\B_SIGNED")).as_bool(); | ||||
|  | @ -485,21 +485,21 @@ struct BtorDumper | |||
| 				l1_width = l1_width > l2_width ? l1_width : l2_width; | ||||
| 				l2_width = l2_width > l1_width ? l2_width : l1_width; | ||||
| 
 | ||||
| 				int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); | ||||
| 				int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); | ||||
| 				 | ||||
| 				++line_num; | ||||
| 				std::string op = cell_type_translation.at(cell->type); | ||||
| 				std::string op = cell_type_translation.at(cell->type.str()); | ||||
| 				if(cell->type == "$lt" || cell->type == "$le" || | ||||
| 				 cell->type == "$eq" || cell->type == "$ne" || cell->type == "$eqx" || cell->type == "$nex" || | ||||
| 				 cell->type == "$ge" || cell->type == "$gt") | ||||
| 				{ | ||||
| 					if(l1_signed) | ||||
| 						op = s_cell_type_translation.at(cell->type); | ||||
| 						op = s_cell_type_translation.at(cell->type.str()); | ||||
| 				} | ||||
| 				 | ||||
| 				str = stringf ("%d %s %d %d %d", line_num, op.c_str(), output_width, l1, l2); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 
 | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
|  | @ -514,18 +514,18 @@ struct BtorDumper | |||
| 				int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				int l2_width = 	cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); | ||||
| 				 | ||||
| 				assert(l1_signed == l2_signed); | ||||
| 				log_assert(l1_signed == l2_signed); | ||||
| 				l1_width = l1_width > output_width ? l1_width : output_width;					 | ||||
| 				l1_width = l1_width > l2_width ? l1_width : l2_width; | ||||
| 				l2_width = l2_width > l1_width ? l2_width : l1_width; | ||||
| 
 | ||||
| 				int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); | ||||
| 				int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); | ||||
| 				 | ||||
| 				++line_num; | ||||
| 				std::string op = cell_type_translation.at(cell->type); | ||||
| 				std::string op = cell_type_translation.at(cell->type.str()); | ||||
| 				if(cell->type == "$div" && l1_signed) | ||||
| 					op = s_cell_type_translation.at(cell->type); | ||||
| 					op = s_cell_type_translation.at(cell->type.str()); | ||||
| 				else if(cell->type == "$mod") | ||||
| 				{ | ||||
| 					if(l1_signed) | ||||
|  | @ -534,17 +534,17 @@ struct BtorDumper | |||
| 						op = s_cell_type_translation.at("$mody"); | ||||
| 				} | ||||
| 				str = stringf ("%d %s %d %d %d", line_num, op.c_str(), l1_width, l1, l2); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 
 | ||||
| 				if(output_width < l1_width) | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, line_num-1, output_width-1, 0); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 				} | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl") | ||||
| 			else if(cell->type == "$shr" || cell->type == "$shl" || cell->type == "$sshr" || cell->type == "$sshl" || cell->type == "$shift" || cell->type == "$shiftx") | ||||
| 			{ | ||||
| 				log("writing binary cell - %s\n", cstr(cell->type)); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
|  | @ -553,32 +553,32 @@ struct BtorDumper | |||
| 				int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				l1_width = pow(2, ceil(log(l1_width)/log(2))); | ||||
| 				int l2_width = 	cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); | ||||
| 				//assert(l2_width <= ceil(log(l1_width)/log(2)) );
 | ||||
| 				int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), ceil(log(l1_width)/log(2))); | ||||
| 				//log_assert(l2_width <= ceil(log(l1_width)/log(2)) );
 | ||||
| 				int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), l1_width); | ||||
| 				int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), ceil(log(l1_width)/log(2))); | ||||
| 				int cell_output = ++line_num; | ||||
| 				str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), l1_width, l1, l2); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), l1_width, l1, l2); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 
 | ||||
| 				if(l2_width > ceil(log(l1_width)/log(2))) | ||||
| 				{ | ||||
| 					int extra_width = l2_width - ceil(log(l1_width)/log(2)); | ||||
| 					l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), l2_width); | ||||
| 					l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), l2_width); | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d slice %d %d %d %d;6", line_num, extra_width, l2, l2_width-1, l2_width-extra_width); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d one %d", line_num, extra_width); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					int mux = ++line_num; | ||||
| 					str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$gt").c_str(), 1, line_num-2, line_num-1); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					++line_num; | ||||
| 					str = stringf("%d %s %d", line_num, l1_signed && cell->type == "$sshr" ? "ones":"zero", l1_width); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d %d %d", line_num, cell_type_translation.at("$mux").c_str(), l1_width, mux, line_num-1, cell_output); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					cell_output = line_num; | ||||
| 				} | ||||
| 
 | ||||
|  | @ -586,7 +586,7 @@ struct BtorDumper | |||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d slice %d %d %d %d;5", line_num, output_width, cell_output, output_width-1, 0); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					cell_output = line_num; | ||||
| 				} | ||||
| 				line_ref[cell->name] = cell_output;	 | ||||
|  | @ -595,23 +595,23 @@ struct BtorDumper | |||
| 			{ | ||||
| 				log("writing binary cell - %s\n", cstr(cell->type)); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
| 				assert(output_width == 1); | ||||
| 				int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); | ||||
| 				int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width); | ||||
| 				log_assert(output_width == 1); | ||||
| 				int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); | ||||
| 				int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); | ||||
| 				int l1_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				int l2_width = 	cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); | ||||
| 				if(l1_width >1) | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l1); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					l1 = line_num; | ||||
| 				} | ||||
| 				if(l2_width > 1) | ||||
| 				{ | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d", line_num, cell_type_translation.at("$reduce_or").c_str(), output_width, l2); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					l2 = line_num; | ||||
| 				} | ||||
| 				if(cell->type == "$logic_and") | ||||
|  | @ -624,7 +624,7 @@ struct BtorDumper | |||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at("$or").c_str(), output_width, l1, l2); | ||||
| 				} | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			//multiplexers
 | ||||
|  | @ -632,13 +632,14 @@ struct BtorDumper | |||
| 			{ | ||||
| 				log("writing mux cell\n"); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
| 				int l1 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); | ||||
| 				int l2 = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width); | ||||
| 				int s = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\S")), 1); | ||||
| 				int l1 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); | ||||
| 				int l2 = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width); | ||||
| 				int s = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), 1); | ||||
| 				++line_num; | ||||
| 				str = stringf ("%d %s %d %d %d %d",  | ||||
| 					line_num, cell_type_translation.at(cell->type).c_str(), output_width, s, l2, l1);//if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell
 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 					line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, s, l2, l1); | ||||
| 				//if s is 0 then l1, if s is 1 then l2 //according to the implementation of mux cell
 | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			else if(cell->type == "$pmux") | ||||
|  | @ -646,97 +647,97 @@ struct BtorDumper | |||
|                           log("writing pmux cell\n"); | ||||
|                           int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
|                           int select_width = cell->parameters.at(RTLIL::IdString("\\S_WIDTH")).as_int(); | ||||
|                           int default_case = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\A")), output_width); | ||||
|                           int cases = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\B")), output_width*select_width); | ||||
|                           int select = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\S")), select_width); | ||||
|                           int default_case = dump_sigspec(&cell->getPort(RTLIL::IdString("\\A")), output_width); | ||||
|                           int cases = dump_sigspec(&cell->getPort(RTLIL::IdString("\\B")), output_width*select_width); | ||||
|                           int select = dump_sigspec(&cell->getPort(RTLIL::IdString("\\S")), select_width); | ||||
|                           int *c = new int[select_width]; | ||||
|                            | ||||
|                           for (int i=0; i<select_width; ++i) | ||||
|                           { | ||||
|                             ++line_num; | ||||
|                             str = stringf ("%d slice 1 %d %d %d", line_num, select, i, i); | ||||
|                             fprintf(f, "%s\n", str.c_str()); | ||||
|                             f << stringf("%s\n", str.c_str()); | ||||
|                             c[i] = line_num; | ||||
|                             ++line_num; | ||||
|                             str = stringf ("%d slice %d %d %d %d", line_num, output_width, cases, i*output_width+output_width-1,  | ||||
|                                            i*output_width); | ||||
|                             fprintf(f, "%s\n", str.c_str()); | ||||
|                             f << stringf("%s\n", str.c_str()); | ||||
|                           } | ||||
|                            | ||||
|                           ++line_num; | ||||
|                           str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[select_width-1], c[select_width-1]+1, default_case); | ||||
|                           fprintf(f, "%s\n", str.c_str()); | ||||
|                           f << stringf("%s\n", str.c_str()); | ||||
|                            | ||||
|                           for (int i=select_width-2; i>=0; --i) | ||||
|                           { | ||||
|                             ++line_num; | ||||
|                             str = stringf ("%d cond %d %d %d %d", line_num, output_width, c[i], c[i]+1, line_num-1); | ||||
|                             fprintf(f, "%s\n", str.c_str()); | ||||
|                             f << stringf("%s\n", str.c_str()); | ||||
|                           } | ||||
| 
 | ||||
|                           line_ref[cell->name]=line_num; | ||||
|                         } | ||||
|                         //registers
 | ||||
|             //registers
 | ||||
| 			else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") | ||||
| 			{ | ||||
| 				//TODO: remodelling fo adff cells
 | ||||
| 				log("writing cell - %s\n", cstr(cell->type)); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
| 				log(" - width is %d\n", output_width); | ||||
| 				int cond = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLK")), 1); | ||||
| 				int cond = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); | ||||
| 				bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); | ||||
| 				const RTLIL::SigSpec* cell_output = &cell->connections.at(RTLIL::IdString("\\Q")); | ||||
| 				int value = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\D")), output_width); | ||||
| 				const RTLIL::SigSpec* cell_output = &cell->getPort(RTLIL::IdString("\\Q")); | ||||
| 				int value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\D")), output_width); | ||||
| 				unsigned start_bit = 0; | ||||
| 				for(unsigned i=0; i<cell_output->chunks.size(); ++i) | ||||
| 				for(unsigned i=0; i<cell_output->chunks().size(); ++i) | ||||
| 				{ | ||||
| 					output_width = cell_output->chunks[i].width; | ||||
| 					assert( output_width == cell_output->chunks[i].wire->width);//full reg is given the next value
 | ||||
| 					int reg = dump_wire(cell_output->chunks[i].wire);//register
 | ||||
| 					output_width = cell_output->chunks().at(i).width; | ||||
| 					log_assert( output_width == cell_output->chunks().at(i).wire->width);//full reg is given the next value
 | ||||
| 					int reg = dump_wire(cell_output->chunks().at(i).wire);//register
 | ||||
| 					int slice = value; | ||||
| 					if(cell_output->chunks.size()>1) | ||||
| 					if(cell_output->chunks().size()>1) | ||||
| 					{ | ||||
| 						start_bit+=output_width; | ||||
| 						slice = ++line_num; | ||||
| 						str = stringf ("%d slice %d %d %d %d;", line_num, output_width, value, start_bit-1,  | ||||
| 							start_bit-output_width); | ||||
| 						fprintf(f, "%s\n", str.c_str()); | ||||
| 						f << stringf("%s\n", str.c_str()); | ||||
| 					} | ||||
| 					if(cell->type == "$dffsr") | ||||
| 					{ | ||||
| 						int sync_reset = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLR")), 1); | ||||
| 						int sync_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLR")), 1); | ||||
| 						bool sync_reset_pol = cell->parameters.at(RTLIL::IdString("\\CLR_POLARITY")).as_bool(); | ||||
| 						int sync_reset_value = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\SET")), | ||||
| 						int sync_reset_value = dump_sigspec(&cell->getPort(RTLIL::IdString("\\SET")), | ||||
| 							output_width); | ||||
| 						bool sync_reset_value_pol = cell->parameters.at(RTLIL::IdString("\\SET_POLARITY")).as_bool(); | ||||
| 						++line_num; | ||||
| 						str = stringf ("%d %s %d %s%d %s%d %d", line_num, cell_type_translation.at("$mux").c_str(),  | ||||
| 							output_width, sync_reset_pol ? "":"-", sync_reset, sync_reset_value_pol? "":"-",  | ||||
| 							sync_reset_value, slice); | ||||
| 						fprintf(f, "%s\n", str.c_str()); | ||||
| 						f << stringf("%s\n", str.c_str()); | ||||
| 						slice = line_num; | ||||
| 					} | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(),  | ||||
| 						output_width, polarity?"":"-", cond, slice, reg); | ||||
| 				 | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 					int next = line_num; | ||||
| 					if(cell->type == "$adff") | ||||
| 					{ | ||||
| 						int async_reset = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ARST")), 1); | ||||
| 						int async_reset = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ARST")), 1); | ||||
| 						bool async_reset_pol = cell->parameters.at(RTLIL::IdString("\\ARST_POLARITY")).as_bool(); | ||||
| 						int async_reset_value = dump_const(&cell->parameters.at(RTLIL::IdString("\\ARST_VALUE")), | ||||
| 							output_width, 0); | ||||
| 						++line_num; | ||||
| 						str = stringf ("%d %s %d %s%d %d %d", line_num, cell_type_translation.at("$mux").c_str(),  | ||||
| 							output_width, async_reset_pol ? "":"-", async_reset, async_reset_value, next); | ||||
| 						fprintf(f, "%s\n", str.c_str()); | ||||
| 						f << stringf("%s\n", str.c_str()); | ||||
| 					} | ||||
| 					++line_num; | ||||
| 					str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(),  | ||||
| 					str = stringf ("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(),  | ||||
| 						output_width, reg, next); | ||||
| 					fprintf(f, "%s\n", str.c_str()); | ||||
| 					f << stringf("%s\n", str.c_str()); | ||||
| 				} | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
|  | @ -749,11 +750,11 @@ struct BtorDumper | |||
| 				str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); | ||||
| 				int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); | ||||
| 				int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); | ||||
| 				int address = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ADDR")), address_width); | ||||
| 				int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); | ||||
| 				int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d read %d %d %d", line_num, data_width, mem, address);	 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			else if(cell->type == "$memwr") | ||||
|  | @ -761,13 +762,13 @@ struct BtorDumper | |||
| 				log("writing memwr cell\n"); | ||||
| 				if (cell->parameters.at("\\CLK_ENABLE").as_bool() == false) | ||||
| 					log_error("The btor backen does not support $memwr cells without built-in registers. Run memory_dff (but with -wr_only).\n"); | ||||
| 				int clk = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\CLK")), 1); | ||||
| 				int clk = dump_sigspec(&cell->getPort(RTLIL::IdString("\\CLK")), 1); | ||||
| 				bool polarity = cell->parameters.at(RTLIL::IdString("\\CLK_POLARITY")).as_bool(); | ||||
| 				int enable = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\EN")), 1); | ||||
| 				int enable = dump_sigspec(&cell->getPort(RTLIL::IdString("\\EN")), 1); | ||||
| 				int address_width = cell->parameters.at(RTLIL::IdString("\\ABITS")).as_int(); | ||||
| 				int address = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\ADDR")), address_width); | ||||
|                                 int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
| 				int data = dump_sigspec(&cell->connections.at(RTLIL::IdString("\\DATA")), data_width); | ||||
| 				int address = dump_sigspec(&cell->getPort(RTLIL::IdString("\\ADDR")), address_width); | ||||
| 				int data_width = cell->parameters.at(RTLIL::IdString("\\WIDTH")).as_int(); | ||||
| 				int data = dump_sigspec(&cell->getPort(RTLIL::IdString("\\DATA")), data_width); | ||||
| 				str = cell->parameters.at(RTLIL::IdString("\\MEMID")).decode_string(); | ||||
| 				int mem = dump_memory(module->memories.at(RTLIL::IdString(str.c_str()))); | ||||
| 				//check if the memory has already next
 | ||||
|  | @ -779,68 +780,67 @@ struct BtorDumper | |||
|                                         RTLIL::Memory *memory = module->memories.at(RTLIL::IdString(str.c_str())); | ||||
|                                         int address_bits = ceil(log(memory->size)/log(2)); | ||||
|                                         str = stringf("%d array %d %d", line_num, memory->width, address_bits); | ||||
|                                         fprintf(f, "%s\n", str.c_str()); | ||||
|                                         f << stringf("%s\n", str.c_str()); | ||||
|                                         ++line_num; | ||||
|                                         str = stringf("%d eq 1 %d %d", line_num, mem, line_num - 1); | ||||
|                                         fprintf(f, "%s\n", str.c_str()); | ||||
|                                         f << stringf("%s\n", str.c_str()); | ||||
|                                         mem = line_num - 1; | ||||
|                                 } | ||||
|                                 ++line_num; | ||||
|                 		++line_num; | ||||
| 				if(polarity) | ||||
| 					str = stringf("%d one 1", line_num); | ||||
| 				else | ||||
| 					str = stringf("%d zero 1", line_num); | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d eq 1 %d %d", line_num, clk, line_num-1);	 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d and 1 %d %d", line_num, line_num-1, enable);	 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d write %d %d %d %d %d", line_num, data_width, address_width, mem, address, data);	 | ||||
| 				fprintf(f, "%s\n", str.c_str()); | ||||
| 				f << stringf("%s\n", str.c_str()); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d acond %d %d %d %d %d", line_num, data_width, address_width, line_num-2/*enable*/, line_num-1, mem);	 | ||||
| 				fprintf(f, "%s\n", str.c_str());				 | ||||
| 				f << stringf("%s\n", str.c_str());				 | ||||
| 				++line_num; | ||||
| 				str = stringf("%d anext %d %d %d %d", line_num, data_width, address_width, mem, line_num-1);	 | ||||
| 				fprintf(f, "%s\n", str.c_str());				 | ||||
| 				f << stringf("%s\n", str.c_str());				 | ||||
| 				mem_next.insert(mem); | ||||
|                                 line_ref[cell->name]=line_num; | ||||
| 				line_ref[cell->name]=line_num; | ||||
| 			} | ||||
| 			else if(cell->type == "$slice") | ||||
| 			{ | ||||
| 				log("writing slice cell\n"); | ||||
| 				const RTLIL::SigSpec* input = &cell->connections.at(RTLIL::IdString("\\A")); | ||||
| 				const RTLIL::SigSpec* input = &cell->getPort(RTLIL::IdString("\\A")); | ||||
| 				int input_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				assert(input->width == input_width); | ||||
| 				log_assert(input->size() == input_width); | ||||
| 				int input_line = dump_sigspec(input, input_width); | ||||
| 				const RTLIL::SigSpec* output = &cell->connections.at(RTLIL::IdString("\\Y")); | ||||
| 				const RTLIL::SigSpec* output = &cell->getPort(RTLIL::IdString("\\Y")); | ||||
| 				int output_width = cell->parameters.at(RTLIL::IdString("\\Y_WIDTH")).as_int(); | ||||
| 				assert(output->width == output_width); | ||||
| 				log_assert(output->size() == output_width); | ||||
| 				int offset = cell->parameters.at(RTLIL::IdString("\\OFFSET")).as_int();	 | ||||
| 				++line_num; | ||||
| 				str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(),  | ||||
|                                               output_width, input_line, output_width+offset-1, offset);	 | ||||
| 				fprintf(f, "%s\n", str.c_str());				 | ||||
| 				str = stringf("%d %s %d %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), output_width, input_line, output_width+offset-1, offset); | ||||
| 				f << stringf("%s\n", str.c_str());				 | ||||
| 				line_ref[cell->name]=line_num;	 | ||||
| 			} | ||||
| 			else if(cell->type == "$concat") | ||||
| 			{ | ||||
| 				log("writing concat cell\n"); | ||||
| 				const RTLIL::SigSpec* input_a = &cell->connections.at(RTLIL::IdString("\\A")); | ||||
| 				const RTLIL::SigSpec* input_a = &cell->getPort(RTLIL::IdString("\\A")); | ||||
| 				int input_a_width = cell->parameters.at(RTLIL::IdString("\\A_WIDTH")).as_int(); | ||||
| 				assert(input_a->width == input_a_width); | ||||
| 				log_assert(input_a->size() == input_a_width); | ||||
| 				int input_a_line = dump_sigspec(input_a, input_a_width); | ||||
| 				const RTLIL::SigSpec* input_b = &cell->connections.at(RTLIL::IdString("\\B")); | ||||
| 				const RTLIL::SigSpec* input_b = &cell->getPort(RTLIL::IdString("\\B")); | ||||
| 				int input_b_width = cell->parameters.at(RTLIL::IdString("\\B_WIDTH")).as_int(); | ||||
| 				assert(input_b->width == input_b_width); | ||||
| 				log_assert(input_b->size() == input_b_width); | ||||
| 				int input_b_line = dump_sigspec(input_b, input_b_width); | ||||
| 				++line_num; | ||||
| 				str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type).c_str(), input_a_width+input_b_width,  | ||||
| 				str = stringf("%d %s %d %d %d", line_num, cell_type_translation.at(cell->type.str()).c_str(), input_a_width+input_b_width,  | ||||
| 					input_a_line, input_b_line);	 | ||||
| 				fprintf(f, "%s\n", str.c_str());				 | ||||
| 				f << stringf("%s\n", str.c_str());				 | ||||
| 				line_ref[cell->name]=line_num;				 | ||||
| 			} | ||||
| 			curr_cell.clear(); | ||||
|  | @ -852,12 +852,12 @@ struct BtorDumper | |||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell) | ||||
| 	const RTLIL::SigSpec* get_cell_output(RTLIL::Cell* cell) | ||||
| 	{ | ||||
| 		RTLIL::SigSpec *output_sig = nullptr; | ||||
| 		const RTLIL::SigSpec *output_sig = nullptr; | ||||
| 		if (cell->type == "$memrd") | ||||
| 		{ | ||||
| 			output_sig = &cell->connections.at(RTLIL::IdString("\\DATA")); | ||||
| 			output_sig = &cell->getPort(RTLIL::IdString("\\DATA")); | ||||
| 		} | ||||
| 		else if(cell->type == "$memwr" || cell->type == "$assert") | ||||
| 		{ | ||||
|  | @ -865,11 +865,11 @@ struct BtorDumper | |||
| 		} | ||||
| 		else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") | ||||
| 		{ | ||||
| 			output_sig = &cell->connections.at(RTLIL::IdString("\\Q")); | ||||
| 			output_sig = &cell->getPort(RTLIL::IdString("\\Q")); | ||||
| 		} | ||||
| 		else  | ||||
| 		{ | ||||
| 			output_sig = &cell->connections.at(RTLIL::IdString("\\Y")); | ||||
| 			output_sig = &cell->getPort(RTLIL::IdString("\\Y")); | ||||
| 		} | ||||
| 		return output_sig; | ||||
| 	} | ||||
|  | @ -879,19 +879,19 @@ struct BtorDumper | |||
| 		int l = dump_wire(wire); | ||||
| 		++line_num; | ||||
| 		str = stringf("%d root 1 %d", line_num, l); | ||||
| 		fprintf(f, "%s\n", str.c_str()); | ||||
| 		f << stringf("%s\n", str.c_str()); | ||||
| 	} | ||||
| 
 | ||||
| 	void dump() | ||||
| 	{ | ||||
| 		fprintf(f, ";module %s\n", cstr(module->name)); | ||||
| 		f << stringf(";module %s\n", cstr(module->name)); | ||||
| 		 | ||||
| 		log("creating intermediate wires map\n"); | ||||
| 		//creating map of intermediate wires as output of some cell
 | ||||
| 		for (auto it = module->cells.begin(); it != module->cells.end(); ++it) | ||||
| 		for (auto it = module->cells_.begin(); it != module->cells_.end(); ++it) | ||||
| 		{ | ||||
| 			RTLIL::Cell *cell = it->second; | ||||
| 			RTLIL::SigSpec* output_sig = get_cell_output(cell); | ||||
| 			const RTLIL::SigSpec* output_sig = get_cell_output(cell); | ||||
| 			if(output_sig==nullptr) | ||||
| 				continue; | ||||
| 			RTLIL::SigSpec s = sigmap(*output_sig); | ||||
|  | @ -899,11 +899,11 @@ struct BtorDumper | |||
| 			log(" - %s\n", cstr(it->second->type)); | ||||
| 			if (cell->type == "$memrd") | ||||
| 			{ | ||||
| 				for(unsigned i=0; i<output_sig->chunks.size(); ++i) | ||||
| 				for(unsigned i=0; i<output_sig->chunks().size(); ++i) | ||||
| 				{ | ||||
| 					RTLIL::Wire *w = output_sig->chunks[i].wire; | ||||
| 					RTLIL::Wire *w = output_sig->chunks().at(i).wire; | ||||
| 					RTLIL::IdString wire_id = w->name; | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); | ||||
| 				} | ||||
| 			} | ||||
| 			else if(cell->type == "$memwr") | ||||
|  | @ -912,22 +912,22 @@ struct BtorDumper | |||
| 			} | ||||
| 			else if(cell->type == "$dff" || cell->type == "$adff" || cell->type == "$dffsr") | ||||
| 			{ | ||||
| 				RTLIL::IdString wire_id = output_sig->chunks[0].wire->name; | ||||
| 				for(unsigned i=0; i<output_sig->chunks.size(); ++i) | ||||
| 				RTLIL::IdString wire_id = output_sig->chunks().front().wire->name; | ||||
| 				for(unsigned i=0; i<output_sig->chunks().size(); ++i) | ||||
| 				{ | ||||
| 					RTLIL::Wire *w = output_sig->chunks[i].wire; | ||||
| 					RTLIL::Wire *w = output_sig->chunks().at(i).wire; | ||||
| 					RTLIL::IdString wire_id = w->name; | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); | ||||
| 					basic_wires[wire_id] = true; | ||||
| 				} | ||||
| 			} | ||||
| 			else  | ||||
| 			{ | ||||
| 				for(unsigned i=0; i<output_sig->chunks.size(); ++i) | ||||
| 				for(unsigned i=0; i<output_sig->chunks().size(); ++i) | ||||
| 				{ | ||||
| 					RTLIL::Wire *w = output_sig->chunks[i].wire; | ||||
| 					RTLIL::Wire *w = output_sig->chunks().at(i).wire; | ||||
| 					RTLIL::IdString wire_id = w->name; | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks[i])); | ||||
| 					inter_wire_map[wire_id].insert(WireInfo(cell->name,&output_sig->chunks().at(i))); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | @ -936,23 +936,23 @@ struct BtorDumper | |||
| 		std::map<int, RTLIL::Wire*> inputs, outputs; | ||||
| 		std::vector<RTLIL::Wire*> safety; | ||||
| 		 | ||||
| 		for (auto &wire_it : module->wires) { | ||||
| 		for (auto &wire_it : module->wires_) { | ||||
| 			RTLIL::Wire *wire = wire_it.second; | ||||
| 			if (wire->port_input) | ||||
| 				inputs[wire->port_id] = wire; | ||||
| 			if (wire->port_output) { | ||||
| 				outputs[wire->port_id] = wire; | ||||
| 				if (wire->name.find("safety") != std::string::npos ) | ||||
| 				if (wire->name.str().find("safety") != std::string::npos ) | ||||
| 					safety.push_back(wire); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(f, ";inputs\n"); | ||||
| 		f << stringf(";inputs\n"); | ||||
| 		for (auto &it : inputs) { | ||||
| 			RTLIL::Wire *wire = it.second; | ||||
| 			dump_wire(wire); | ||||
| 		} | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 		 | ||||
| 		log("writing memories\n"); | ||||
| 		for(auto mem_it = module->memories.begin(); mem_it != module->memories.end(); ++mem_it) | ||||
|  | @ -967,7 +967,7 @@ struct BtorDumper | |||
| 		} | ||||
| 
 | ||||
| 		log("writing cells\n"); | ||||
| 		for(auto cell_it = module->cells.begin(); cell_it != module->cells.end(); ++cell_it) | ||||
| 		for(auto cell_it = module->cells_.begin(); cell_it != module->cells_.end(); ++cell_it) | ||||
| 		{ | ||||
| 			dump_cell(cell_it->second);	 | ||||
| 		} | ||||
|  | @ -975,19 +975,19 @@ struct BtorDumper | |||
| 		for(auto it: safety) | ||||
| 			dump_property(it); | ||||
| 
 | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 		 | ||||
| 		log("writing outputs info\n"); | ||||
| 		fprintf(f, ";outputs\n"); | ||||
| 		f << stringf(";outputs\n"); | ||||
| 		for (auto &it : outputs) { | ||||
| 			RTLIL::Wire *wire = it.second; | ||||
| 			int l = dump_wire(wire); | ||||
| 			fprintf(f, ";%d %s", l, cstr(wire->name)); | ||||
| 			f << stringf(";%d %s", l, cstr(wire->name)); | ||||
| 		} | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	static void dump(FILE *f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config) | ||||
| 	static void dump(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, BtorDumperConfig &config) | ||||
| 	{ | ||||
| 		BtorDumper dumper(f, module, design, &config); | ||||
| 		dumper.dump(); | ||||
|  | @ -1006,7 +1006,7 @@ struct BtorBackend : public Backend { | |||
| 		log("Write the current design to an BTOR file.\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		std::string top_module_name; | ||||
| 		std::string buf_type, buf_in, buf_out; | ||||
|  | @ -1020,18 +1020,18 @@ struct BtorBackend : public Backend { | |||
| 		extra_args(f, filename, args, argidx); | ||||
| 		 | ||||
| 		if (top_module_name.empty()) | ||||
| 			for (auto & mod_it:design->modules) | ||||
| 			for (auto & mod_it:design->modules_) | ||||
| 				if (mod_it.second->get_bool_attribute("\\top")) | ||||
| 					top_module_name = mod_it.first; | ||||
| 					top_module_name = mod_it.first.str(); | ||||
| 
 | ||||
| 		fprintf(f, "; Generated by %s\n", yosys_version_str); | ||||
| 		fprintf(f, ";  %s developed and maintained by Clifford Wolf <clifford@clifford.at>\n", yosys_version_str); | ||||
| 		fprintf(f, "; BTOR Backend developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy\n"); | ||||
| 		fprintf(f, ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); | ||||
| 		*f << stringf("; Generated by %s\n", yosys_version_str); | ||||
| 		*f << stringf(";  %s developed and maintained by Clifford Wolf <clifford@clifford.at>\n", yosys_version_str); | ||||
| 		*f << stringf("; BTOR Backend developed by Ahmed Irfan <irfan@fbk.eu> - Fondazione Bruno Kessler, Trento, Italy\n"); | ||||
| 		*f << stringf(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n"); | ||||
| 		 | ||||
| 		std::vector<RTLIL::Module*> mod_list; | ||||
| 
 | ||||
| 		for (auto module_it : design->modules) | ||||
| 		for (auto module_it : design->modules_) | ||||
| 		{ | ||||
| 			RTLIL::Module *module = module_it.second; | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
|  | @ -1041,7 +1041,7 @@ struct BtorBackend : public Backend { | |||
| 				log_error("Found unmapped processes in module %s: unmapped processes are not supported in BTOR backend!\n", RTLIL::id2cstr(module->name)); | ||||
| 
 | ||||
| 			if (module->name == RTLIL::escape_id(top_module_name)) { | ||||
| 				BtorDumper::dump(f, module, design, config); | ||||
| 				BtorDumper::dump(*f, module, design, config); | ||||
| 				top_module_name.clear(); | ||||
| 				continue; | ||||
| 			} | ||||
|  | @ -1053,7 +1053,7 @@ struct BtorBackend : public Backend { | |||
| 			log_error("Can't find top module `%s'!\n", top_module_name.c_str()); | ||||
| 
 | ||||
| 		for (auto module : mod_list) | ||||
| 			BtorDumper::dump(f, module, design, config); | ||||
| 			BtorDumper::dump(*f, module, design, config); | ||||
| 	} | ||||
| } BtorBackend; | ||||
| 
 | ||||
|  |  | |||
|  | @ -17,14 +17,14 @@ FULL_PATH=$(readlink -f $1) | |||
| DIR=$(dirname $FULL_PATH) | ||||
| 
 | ||||
| ./yosys -q -p " | ||||
| read_verilog $1;  | ||||
| read_verilog -sv $1;  | ||||
| hierarchy -top $3;  | ||||
| hierarchy -libdir $DIR;  | ||||
| hierarchy -check;  | ||||
| proc;  | ||||
| opt; opt_const -mux_undef; opt; | ||||
| rename -hide;;; | ||||
| techmap -share_map pmux2mux.v;; | ||||
| #techmap -share_map pmux2mux.v;; | ||||
| splice; opt; | ||||
| memory_dff -wr_only; | ||||
| memory_collect;; | ||||
|  |  | |||
|  | @ -26,9 +26,9 @@ | |||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| #define EDIF_NAME(_id) edif_names(RTLIL::unescape_id(_id)).c_str() | ||||
| #define EDIF_DEF(_id) edif_names(RTLIL::unescape_id(_id), true).c_str() | ||||
| #define EDIF_REF(_id) edif_names(RTLIL::unescape_id(_id), false).c_str() | ||||
| 
 | ||||
| namespace | ||||
| { | ||||
|  | @ -40,8 +40,13 @@ namespace | |||
| 
 | ||||
| 		EdifNames() : counter(1) { } | ||||
| 
 | ||||
| 		std::string operator()(std::string id) | ||||
| 		std::string operator()(std::string id, bool define) | ||||
| 		{ | ||||
| 			if (define) { | ||||
| 				std::string new_id = operator()(id, false); | ||||
| 				return new_id != id ? stringf("(rename %s \"%s\")", new_id.c_str(), id.c_str()) : id; | ||||
| 			} | ||||
| 
 | ||||
| 			if (name_map.count(id) > 0) | ||||
| 				return name_map.at(id); | ||||
| 			if (generated_names.count(id) > 0) | ||||
|  | @ -74,7 +79,7 @@ namespace | |||
| 			} | ||||
| 			generated_names.insert(gen_name); | ||||
| 			name_map[id] = gen_name; | ||||
| 			return stringf("(rename %s \"%s\")", gen_name.c_str(), id.c_str()); | ||||
| 			return gen_name; | ||||
| 		} | ||||
| 	}; | ||||
| } | ||||
|  | @ -98,12 +103,12 @@ struct EdifBackend : public Backend { | |||
| 		log("is targeted.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		log_header("Executing EDIF backend.\n"); | ||||
| 
 | ||||
| 		std::string top_module_name; | ||||
| 		std::map<std::string, std::set<std::string>> lib_cell_ports; | ||||
| 		std::map<RTLIL::IdString, std::set<RTLIL::IdString>> lib_cell_ports; | ||||
| 		CellTypes ct(design); | ||||
| 		EdifNames edif_names; | ||||
| 
 | ||||
|  | @ -119,31 +124,31 @@ struct EdifBackend : public Backend { | |||
| 		extra_args(f, filename, args, argidx); | ||||
| 
 | ||||
| 		if (top_module_name.empty()) | ||||
| 			for (auto & mod_it:design->modules) | ||||
| 			for (auto & mod_it:design->modules_) | ||||
| 				if (mod_it.second->get_bool_attribute("\\top")) | ||||
| 					top_module_name = mod_it.first; | ||||
| 					top_module_name = mod_it.first.str(); | ||||
| 
 | ||||
| 		for (auto module_it : design->modules) | ||||
| 		for (auto module_it : design->modules_) | ||||
| 		{ | ||||
| 			RTLIL::Module *module = module_it.second; | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (top_module_name.empty()) | ||||
| 				top_module_name = module->name; | ||||
| 				top_module_name = module->name.str(); | ||||
| 
 | ||||
| 			if (module->processes.size() != 0) | ||||
| 				log_error("Found unmapped processes in module %s: unmapped processes are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); | ||||
| 			if (module->memories.size() != 0) | ||||
| 				log_error("Found munmapped emories in module %s: unmapped memories are not supported in EDIF backend!\n", RTLIL::id2cstr(module->name)); | ||||
| 
 | ||||
| 			for (auto cell_it : module->cells) | ||||
| 			for (auto cell_it : module->cells_) | ||||
| 			{ | ||||
| 				RTLIL::Cell *cell = cell_it.second; | ||||
| 				if (!design->modules.count(cell->type) || design->modules.at(cell->type)->get_bool_attribute("\\blackbox")) { | ||||
| 				if (!design->modules_.count(cell->type) || design->modules_.at(cell->type)->get_bool_attribute("\\blackbox")) { | ||||
| 					lib_cell_ports[cell->type]; | ||||
| 					for (auto p : cell->connections) { | ||||
| 						if (p.second.width > 1) | ||||
| 					for (auto p : cell->connections()) { | ||||
| 						if (p.second.size() > 1) | ||||
| 							log_error("Found multi-bit port %s on library cell %s.%s (%s): not supported in EDIF backend!\n", | ||||
| 									RTLIL::id2cstr(p.first), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); | ||||
| 						lib_cell_ports[cell->type].insert(p.first); | ||||
|  | @ -155,38 +160,38 @@ struct EdifBackend : public Backend { | |||
| 		if (top_module_name.empty()) | ||||
| 			log_error("No module found in design!\n"); | ||||
| 
 | ||||
| 		fprintf(f, "(edif %s\n", EDIF_NAME(top_module_name)); | ||||
| 		fprintf(f, "  (edifVersion 2 0 0)\n"); | ||||
| 		fprintf(f, "  (edifLevel 0)\n"); | ||||
| 		fprintf(f, "  (keywordMap (keywordLevel 0))\n"); | ||||
| 		fprintf(f, "  (comment \"Generated by %s\")\n", yosys_version_str); | ||||
| 		*f << stringf("(edif %s\n", EDIF_DEF(top_module_name)); | ||||
| 		*f << stringf("  (edifVersion 2 0 0)\n"); | ||||
| 		*f << stringf("  (edifLevel 0)\n"); | ||||
| 		*f << stringf("  (keywordMap (keywordLevel 0))\n"); | ||||
| 		*f << stringf("  (comment \"Generated by %s\")\n", yosys_version_str); | ||||
| 
 | ||||
| 		fprintf(f, "  (external LIB\n"); | ||||
| 		fprintf(f, "    (edifLevel 0)\n"); | ||||
| 		fprintf(f, "    (technology (numberDefinition))\n"); | ||||
| 		*f << stringf("  (external LIB\n"); | ||||
| 		*f << stringf("    (edifLevel 0)\n"); | ||||
| 		*f << stringf("    (technology (numberDefinition))\n"); | ||||
| 
 | ||||
| 		fprintf(f, "    (cell GND\n"); | ||||
| 		fprintf(f, "      (cellType GENERIC)\n"); | ||||
| 		fprintf(f, "      (view VIEW_NETLIST\n"); | ||||
| 		fprintf(f, "        (viewType NETLIST)\n"); | ||||
| 		fprintf(f, "        (interface (port G (direction OUTPUT)))\n"); | ||||
| 		fprintf(f, "      )\n"); | ||||
| 		fprintf(f, "    )\n"); | ||||
| 		*f << stringf("    (cell GND\n"); | ||||
| 		*f << stringf("      (cellType GENERIC)\n"); | ||||
| 		*f << stringf("      (view VIEW_NETLIST\n"); | ||||
| 		*f << stringf("        (viewType NETLIST)\n"); | ||||
| 		*f << stringf("        (interface (port G (direction OUTPUT)))\n"); | ||||
| 		*f << stringf("      )\n"); | ||||
| 		*f << stringf("    )\n"); | ||||
| 
 | ||||
| 		fprintf(f, "    (cell VCC\n"); | ||||
| 		fprintf(f, "      (cellType GENERIC)\n"); | ||||
| 		fprintf(f, "      (view VIEW_NETLIST\n"); | ||||
| 		fprintf(f, "        (viewType NETLIST)\n"); | ||||
| 		fprintf(f, "        (interface (port P (direction OUTPUT)))\n"); | ||||
| 		fprintf(f, "      )\n"); | ||||
| 		fprintf(f, "    )\n"); | ||||
| 		*f << stringf("    (cell VCC\n"); | ||||
| 		*f << stringf("      (cellType GENERIC)\n"); | ||||
| 		*f << stringf("      (view VIEW_NETLIST\n"); | ||||
| 		*f << stringf("        (viewType NETLIST)\n"); | ||||
| 		*f << stringf("        (interface (port P (direction OUTPUT)))\n"); | ||||
| 		*f << stringf("      )\n"); | ||||
| 		*f << stringf("    )\n"); | ||||
| 
 | ||||
| 		for (auto &cell_it : lib_cell_ports) { | ||||
| 			fprintf(f, "    (cell %s\n", EDIF_NAME(cell_it.first)); | ||||
| 			fprintf(f, "      (cellType GENERIC)\n"); | ||||
| 			fprintf(f, "      (view VIEW_NETLIST\n"); | ||||
| 			fprintf(f, "        (viewType NETLIST)\n"); | ||||
| 			fprintf(f, "        (interface\n"); | ||||
| 			*f << stringf("    (cell %s\n", EDIF_DEF(cell_it.first)); | ||||
| 			*f << stringf("      (cellType GENERIC)\n"); | ||||
| 			*f << stringf("      (view VIEW_NETLIST\n"); | ||||
| 			*f << stringf("        (viewType NETLIST)\n"); | ||||
| 			*f << stringf("        (interface\n"); | ||||
| 			for (auto &port_it : cell_it.second) { | ||||
| 				const char *dir = "INOUT"; | ||||
| 				if (ct.cell_known(cell_it.first)) { | ||||
|  | @ -195,23 +200,23 @@ struct EdifBackend : public Backend { | |||
| 					else if (!ct.cell_input(cell_it.first, port_it)) | ||||
| 						dir = "OUTPUT"; | ||||
| 				} | ||||
| 				fprintf(f, "          (port %s (direction %s))\n", EDIF_NAME(port_it), dir); | ||||
| 				*f << stringf("          (port %s (direction %s))\n", EDIF_DEF(port_it), dir); | ||||
| 			} | ||||
| 			fprintf(f, "        )\n"); | ||||
| 			fprintf(f, "      )\n"); | ||||
| 			fprintf(f, "    )\n"); | ||||
| 			*f << stringf("        )\n"); | ||||
| 			*f << stringf("      )\n"); | ||||
| 			*f << stringf("    )\n"); | ||||
| 		} | ||||
| 		fprintf(f, "  )\n"); | ||||
| 		*f << stringf("  )\n"); | ||||
| 
 | ||||
| 		std::vector<RTLIL::Module*> sorted_modules; | ||||
| 
 | ||||
| 		// extract module dependencies
 | ||||
| 		std::map<RTLIL::Module*, std::set<RTLIL::Module*>> module_deps; | ||||
| 		for (auto &mod_it : design->modules) { | ||||
| 		for (auto &mod_it : design->modules_) { | ||||
| 			module_deps[mod_it.second] = std::set<RTLIL::Module*>(); | ||||
| 			for (auto &cell_it : mod_it.second->cells) | ||||
| 				if (design->modules.count(cell_it.second->type) > 0) | ||||
| 					module_deps[mod_it.second].insert(design->modules.at(cell_it.second->type)); | ||||
| 			for (auto &cell_it : mod_it.second->cells_) | ||||
| 				if (design->modules_.count(cell_it.second->type) > 0) | ||||
| 					module_deps[mod_it.second].insert(design->modules_.at(cell_it.second->type)); | ||||
| 		} | ||||
| 
 | ||||
| 		// simple good-enough topological sort
 | ||||
|  | @ -233,9 +238,9 @@ struct EdifBackend : public Backend { | |||
| 		} | ||||
| 
 | ||||
| 
 | ||||
| 		fprintf(f, "  (library DESIGN\n"); | ||||
| 		fprintf(f, "    (edifLevel 0)\n"); | ||||
| 		fprintf(f, "    (technology (numberDefinition))\n"); | ||||
| 		*f << stringf("  (library DESIGN\n"); | ||||
| 		*f << stringf("    (edifLevel 0)\n"); | ||||
| 		*f << stringf("    (technology (numberDefinition))\n"); | ||||
| 		for (auto module : sorted_modules) | ||||
| 		{ | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
|  | @ -244,12 +249,12 @@ struct EdifBackend : public Backend { | |||
| 			SigMap sigmap(module); | ||||
| 			std::map<RTLIL::SigSpec, std::set<std::string>> net_join_db; | ||||
| 
 | ||||
| 			fprintf(f, "    (cell %s\n", EDIF_NAME(module->name)); | ||||
| 			fprintf(f, "      (cellType GENERIC)\n"); | ||||
| 			fprintf(f, "      (view VIEW_NETLIST\n"); | ||||
| 			fprintf(f, "        (viewType NETLIST)\n"); | ||||
| 			fprintf(f, "        (interface\n"); | ||||
| 			for (auto &wire_it : module->wires) { | ||||
| 			*f << stringf("    (cell %s\n", EDIF_DEF(module->name)); | ||||
| 			*f << stringf("      (cellType GENERIC)\n"); | ||||
| 			*f << stringf("      (view VIEW_NETLIST\n"); | ||||
| 			*f << stringf("        (viewType NETLIST)\n"); | ||||
| 			*f << stringf("        (interface\n"); | ||||
| 			for (auto &wire_it : module->wires_) { | ||||
| 				RTLIL::Wire *wire = wire_it.second; | ||||
| 				if (wire->port_id == 0) | ||||
| 					continue; | ||||
|  | @ -259,31 +264,31 @@ struct EdifBackend : public Backend { | |||
| 				else if (!wire->port_input) | ||||
| 					dir = "OUTPUT"; | ||||
| 				if (wire->width == 1) { | ||||
| 					fprintf(f, "          (port %s (direction %s))\n", EDIF_NAME(wire->name), dir); | ||||
| 					*f << stringf("          (port %s (direction %s))\n", EDIF_DEF(wire->name), dir); | ||||
| 					RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire)); | ||||
| 					net_join_db[sig].insert(stringf("(portRef %s)", EDIF_NAME(wire->name))); | ||||
| 					net_join_db[sig].insert(stringf("(portRef %s)", EDIF_REF(wire->name))); | ||||
| 				} else { | ||||
| 					fprintf(f, "          (port (array %s %d) (direction %s))\n", EDIF_NAME(wire->name), wire->width, dir); | ||||
| 					*f << stringf("          (port (array %s %d) (direction %s))\n", EDIF_DEF(wire->name), wire->width, dir); | ||||
| 					for (int i = 0; i < wire->width; i++) { | ||||
| 						RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, 1, i)); | ||||
| 						net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_NAME(wire->name), i)); | ||||
| 						RTLIL::SigSpec sig = sigmap(RTLIL::SigSpec(wire, i)); | ||||
| 						net_join_db[sig].insert(stringf("(portRef (member %s %d))", EDIF_REF(wire->name), i)); | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			fprintf(f, "        )\n"); | ||||
| 			fprintf(f, "        (contents\n"); | ||||
| 			fprintf(f, "          (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); | ||||
| 			fprintf(f, "          (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); | ||||
| 			for (auto &cell_it : module->cells) { | ||||
| 			*f << stringf("        )\n"); | ||||
| 			*f << stringf("        (contents\n"); | ||||
| 			*f << stringf("          (instance GND (viewRef VIEW_NETLIST (cellRef GND (libraryRef LIB))))\n"); | ||||
| 			*f << stringf("          (instance VCC (viewRef VIEW_NETLIST (cellRef VCC (libraryRef LIB))))\n"); | ||||
| 			for (auto &cell_it : module->cells_) { | ||||
| 				RTLIL::Cell *cell = cell_it.second; | ||||
| 				fprintf(f, "          (instance %s\n", EDIF_NAME(cell->name)); | ||||
| 				fprintf(f, "            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_NAME(cell->type), | ||||
| 				*f << stringf("          (instance %s\n", EDIF_DEF(cell->name)); | ||||
| 				*f << stringf("            (viewRef VIEW_NETLIST (cellRef %s%s))", EDIF_REF(cell->type), | ||||
| 						lib_cell_ports.count(cell->type) > 0 ? " (libraryRef LIB)" : ""); | ||||
| 				for (auto &p : cell->parameters) | ||||
| 					if ((p.second.flags & RTLIL::CONST_FLAG_STRING) != 0) | ||||
| 						fprintf(f, "\n            (property %s (string \"%s\"))", EDIF_NAME(p.first), p.second.decode_string().c_str()); | ||||
| 						*f << stringf("\n            (property %s (string \"%s\"))", EDIF_DEF(p.first), p.second.decode_string().c_str()); | ||||
| 					else if (p.second.bits.size() <= 32 && RTLIL::SigSpec(p.second).is_fully_def()) | ||||
| 						fprintf(f, "\n            (property %s (integer %u))", EDIF_NAME(p.first), p.second.as_int()); | ||||
| 						*f << stringf("\n            (property %s (integer %u))", EDIF_DEF(p.first), p.second.as_int()); | ||||
| 					else { | ||||
| 						std::string hex_string = ""; | ||||
| 						for (size_t i = 0; i < p.second.bits.size(); i += 4) { | ||||
|  | @ -295,53 +300,48 @@ struct EdifBackend : public Backend { | |||
| 							char digit_str[2] = { "0123456789abcdef"[digit_value], 0 }; | ||||
| 							hex_string = std::string(digit_str) + hex_string; | ||||
| 						} | ||||
| 						fprintf(f, "\n            (property %s (string \"%s\"))", EDIF_NAME(p.first), hex_string.c_str()); | ||||
| 						*f << stringf("\n            (property %s (string \"%s\"))", EDIF_DEF(p.first), hex_string.c_str()); | ||||
| 					} | ||||
| 				fprintf(f, ")\n"); | ||||
| 				for (auto &p : cell->connections) { | ||||
| 				*f << stringf(")\n"); | ||||
| 				for (auto &p : cell->connections()) { | ||||
| 					RTLIL::SigSpec sig = sigmap(p.second); | ||||
| 					sig.expand(); | ||||
| 					for (int i = 0; i < sig.width; i++) { | ||||
| 						RTLIL::SigSpec sigbit(sig.chunks.at(i)); | ||||
| 						std::string portname = sig.width > 1 ? stringf("%s[%d]", RTLIL::id2cstr(p.first), i) : RTLIL::id2cstr(p.first); | ||||
| 						net_join_db[sigbit].insert(stringf("(portRef %s (instanceRef %s))", edif_names(portname).c_str(), EDIF_NAME(cell->name))); | ||||
| 					} | ||||
| 					for (int i = 0; i < SIZE(sig); i++) | ||||
| 						if (sig.size() == 1) | ||||
| 							net_join_db[sig[i]].insert(stringf("(portRef %s (instanceRef %s))", EDIF_REF(p.first), EDIF_REF(cell->name))); | ||||
| 						else | ||||
| 							net_join_db[sig[i]].insert(stringf("(portRef (member %s %d) (instanceRef %s))", EDIF_REF(p.first), i, EDIF_REF(cell->name))); | ||||
| 				} | ||||
| 			} | ||||
| 			for (auto &it : net_join_db) { | ||||
| 				RTLIL::SigSpec sig = it.first; | ||||
| 				sig.optimize(); | ||||
| 				log_assert(sig.width == 1); | ||||
| 				if (sig.chunks.at(0).wire == NULL) { | ||||
| 					if (sig.chunks.at(0).data.bits.at(0) != RTLIL::State::S0 && sig.chunks.at(0).data.bits.at(0) != RTLIL::State::S1) | ||||
| 						continue; | ||||
| 				} | ||||
| 				RTLIL::SigBit sig = it.first; | ||||
| 				if (sig.wire == NULL && sig != RTLIL::State::S0 && sig != RTLIL::State::S1) | ||||
| 					continue; | ||||
| 				std::string netname = log_signal(sig); | ||||
| 				for (size_t i = 0; i < netname.size(); i++) | ||||
| 					if (netname[i] == ' ' || netname[i] == '\\') | ||||
| 						netname.erase(netname.begin() + i--); | ||||
| 				fprintf(f, "          (net %s (joined\n", edif_names(netname).c_str()); | ||||
| 				*f << stringf("          (net %s (joined\n", EDIF_DEF(netname)); | ||||
| 				for (auto &ref : it.second) | ||||
| 					fprintf(f, "            %s\n", ref.c_str()); | ||||
| 				if (sig.chunks.at(0).wire == NULL) { | ||||
| 					if (sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S0) | ||||
| 						fprintf(f, "            (portRef G (instanceRef GND))\n"); | ||||
| 					if (sig.chunks.at(0).data.bits.at(0) == RTLIL::State::S1) | ||||
| 						fprintf(f, "            (portRef P (instanceRef VCC))\n"); | ||||
| 					*f << stringf("            %s\n", ref.c_str()); | ||||
| 				if (sig.wire == NULL) { | ||||
| 					if (sig == RTLIL::State::S0) | ||||
| 						*f << stringf("            (portRef G (instanceRef GND))\n"); | ||||
| 					if (sig == RTLIL::State::S1) | ||||
| 						*f << stringf("            (portRef P (instanceRef VCC))\n"); | ||||
| 				} | ||||
| 				fprintf(f, "          ))\n"); | ||||
| 				*f << stringf("          ))\n"); | ||||
| 			} | ||||
| 			fprintf(f, "        )\n"); | ||||
| 			fprintf(f, "      )\n"); | ||||
| 			fprintf(f, "    )\n"); | ||||
| 			*f << stringf("        )\n"); | ||||
| 			*f << stringf("      )\n"); | ||||
| 			*f << stringf("    )\n"); | ||||
| 		} | ||||
| 		fprintf(f, "  )\n"); | ||||
| 		*f << stringf("  )\n"); | ||||
| 
 | ||||
| 		fprintf(f, "  (design %s\n", EDIF_NAME(top_module_name)); | ||||
| 		fprintf(f, "    (cellRef %s (libraryRef DESIGN))\n", EDIF_NAME(top_module_name)); | ||||
| 		fprintf(f, "  )\n"); | ||||
| 		*f << stringf("  (design %s\n", EDIF_DEF(top_module_name)); | ||||
| 		*f << stringf("    (cellRef %s (libraryRef DESIGN))\n", EDIF_REF(top_module_name)); | ||||
| 		*f << stringf("  )\n"); | ||||
| 
 | ||||
| 		fprintf(f, ")\n"); | ||||
| 		*f << stringf(")\n"); | ||||
| 	} | ||||
| } EdifBackend; | ||||
| 
 | ||||
|  |  | |||
|  | @ -23,16 +23,12 @@ | |||
|  */ | ||||
| 
 | ||||
| #include "ilang_backend.h" | ||||
| #include "kernel/register.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| #include <string.h> | ||||
| #include "kernel/yosys.h" | ||||
| #include <errno.h> | ||||
| 
 | ||||
| using namespace ILANG_BACKEND; | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int offset, bool autoint) | ||||
| void ILANG_BACKEND::dump_const(std::ostream &f, const RTLIL::Const &data, int width, int offset, bool autoint) | ||||
| { | ||||
| 	if (width < 0) | ||||
| 		width = data.bits.size() - offset; | ||||
|  | @ -40,7 +36,7 @@ void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int | |||
| 		if (width == 32 && autoint) { | ||||
| 			int32_t val = 0; | ||||
| 			for (int i = 0; i < width; i++) { | ||||
| 				assert(offset+i < (int)data.bits.size()); | ||||
| 				log_assert(offset+i < (int)data.bits.size()); | ||||
| 				switch (data.bits[offset+i]) { | ||||
| 				case RTLIL::S0: break; | ||||
| 				case RTLIL::S1: val |= 1 << i; break; | ||||
|  | @ -48,220 +44,230 @@ void ILANG_BACKEND::dump_const(FILE *f, const RTLIL::Const &data, int width, int | |||
| 				} | ||||
| 			} | ||||
| 			if (val >= 0) { | ||||
| 				fprintf(f, "%d", val); | ||||
| 				f << stringf("%d", val); | ||||
| 				return; | ||||
| 			} | ||||
| 		} | ||||
| 		fprintf(f, "%d'", width); | ||||
| 		f << stringf("%d'", width); | ||||
| 		for (int i = offset+width-1; i >= offset; i--) { | ||||
| 			assert(i < (int)data.bits.size()); | ||||
| 			log_assert(i < (int)data.bits.size()); | ||||
| 			switch (data.bits[i]) { | ||||
| 			case RTLIL::S0: fprintf(f, "0"); break; | ||||
| 			case RTLIL::S1: fprintf(f, "1"); break; | ||||
| 			case RTLIL::Sx: fprintf(f, "x"); break; | ||||
| 			case RTLIL::Sz: fprintf(f, "z"); break; | ||||
| 			case RTLIL::Sa: fprintf(f, "-"); break; | ||||
| 			case RTLIL::Sm: fprintf(f, "m"); break; | ||||
| 			case RTLIL::S0: f << stringf("0"); break; | ||||
| 			case RTLIL::S1: f << stringf("1"); break; | ||||
| 			case RTLIL::Sx: f << stringf("x"); break; | ||||
| 			case RTLIL::Sz: f << stringf("z"); break; | ||||
| 			case RTLIL::Sa: f << stringf("-"); break; | ||||
| 			case RTLIL::Sm: f << stringf("m"); break; | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		fprintf(f, "\""); | ||||
| 		f << stringf("\""); | ||||
| 		std::string str = data.decode_string(); | ||||
| 		for (size_t i = 0; i < str.size(); i++) { | ||||
| 			if (str[i] == '\n') | ||||
| 				fprintf(f, "\\n"); | ||||
| 				f << stringf("\\n"); | ||||
| 			else if (str[i] == '\t') | ||||
| 				fprintf(f, "\\t"); | ||||
| 				f << stringf("\\t"); | ||||
| 			else if (str[i] < 32) | ||||
| 				fprintf(f, "\\%03o", str[i]); | ||||
| 				f << stringf("\\%03o", str[i]); | ||||
| 			else if (str[i] == '"') | ||||
| 				fprintf(f, "\\\""); | ||||
| 				f << stringf("\\\""); | ||||
| 			else if (str[i] == '\\') | ||||
| 				fprintf(f, "\\\\"); | ||||
| 				f << stringf("\\\\"); | ||||
| 			else | ||||
| 				fputc(str[i], f); | ||||
| 				f << str[i]; | ||||
| 		} | ||||
| 		fprintf(f, "\""); | ||||
| 		f << stringf("\""); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool autoint) | ||||
| void ILANG_BACKEND::dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint) | ||||
| { | ||||
| 	if (chunk.wire == NULL) { | ||||
| 		dump_const(f, chunk.data, chunk.width, chunk.offset, autoint); | ||||
| 	} else { | ||||
| 		if (chunk.width == chunk.wire->width && chunk.offset == 0) | ||||
| 			fprintf(f, "%s", chunk.wire->name.c_str()); | ||||
| 			f << stringf("%s", chunk.wire->name.c_str()); | ||||
| 		else if (chunk.width == 1) | ||||
| 			fprintf(f, "%s [%d]", chunk.wire->name.c_str(), chunk.offset); | ||||
| 			f << stringf("%s [%d]", chunk.wire->name.c_str(), chunk.offset); | ||||
| 		else | ||||
| 			fprintf(f, "%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset); | ||||
| 			f << stringf("%s [%d:%d]", chunk.wire->name.c_str(), chunk.offset+chunk.width-1, chunk.offset); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_sigspec(FILE *f, const RTLIL::SigSpec &sig, bool autoint) | ||||
| void ILANG_BACKEND::dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint) | ||||
| { | ||||
| 	if (sig.chunks.size() == 1) { | ||||
| 		dump_sigchunk(f, sig.chunks[0], autoint); | ||||
| 	if (sig.is_chunk()) { | ||||
| 		dump_sigchunk(f, sig.as_chunk(), autoint); | ||||
| 	} else { | ||||
| 		fprintf(f, "{ "); | ||||
| 		for (auto it = sig.chunks.rbegin(); it != sig.chunks.rend(); it++) { | ||||
| 		f << stringf("{ "); | ||||
| 		for (auto it = sig.chunks().rbegin(); it != sig.chunks().rend(); it++) { | ||||
| 			dump_sigchunk(f, *it, false); | ||||
| 			fprintf(f, " "); | ||||
| 			f << stringf(" "); | ||||
| 		} | ||||
| 		fprintf(f, "}"); | ||||
| 		f << stringf("}"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_wire(FILE *f, std::string indent, const RTLIL::Wire *wire) | ||||
| void ILANG_BACKEND::dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire) | ||||
| { | ||||
| 	for (auto it = wire->attributes.begin(); it != wire->attributes.end(); it++) { | ||||
| 		fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 	std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(wire->attributes.begin(), wire->attributes.end()); | ||||
| 
 | ||||
| 	for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { | ||||
| 		f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	fprintf(f, "%s" "wire ", indent.c_str()); | ||||
| 	f << stringf("%s" "wire ", indent.c_str()); | ||||
| 	if (wire->width != 1) | ||||
| 		fprintf(f, "width %d ", wire->width); | ||||
| 		f << stringf("width %d ", wire->width); | ||||
| 	if (wire->upto) | ||||
| 		f << stringf("upto "); | ||||
| 	if (wire->start_offset != 0) | ||||
| 		fprintf(f, "offset %d ", wire->start_offset); | ||||
| 		f << stringf("offset %d ", wire->start_offset); | ||||
| 	if (wire->port_input && !wire->port_output) | ||||
| 		fprintf(f, "input %d ", wire->port_id); | ||||
| 		f << stringf("input %d ", wire->port_id); | ||||
| 	if (!wire->port_input && wire->port_output) | ||||
| 		fprintf(f, "output %d ", wire->port_id); | ||||
| 		f << stringf("output %d ", wire->port_id); | ||||
| 	if (wire->port_input && wire->port_output) | ||||
| 		fprintf(f, "inout %d ", wire->port_id); | ||||
| 	fprintf(f, "%s\n", wire->name.c_str()); | ||||
| 		f << stringf("inout %d ", wire->port_id); | ||||
| 	f << stringf("%s\n", wire->name.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_memory(FILE *f, std::string indent, const RTLIL::Memory *memory) | ||||
| void ILANG_BACKEND::dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory) | ||||
| { | ||||
| 	for (auto it = memory->attributes.begin(); it != memory->attributes.end(); it++) { | ||||
| 		fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 	std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(memory->attributes.begin(), memory->attributes.end()); | ||||
| 
 | ||||
| 	for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { | ||||
| 		f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	fprintf(f, "%s" "memory ", indent.c_str()); | ||||
| 	f << stringf("%s" "memory ", indent.c_str()); | ||||
| 	if (memory->width != 1) | ||||
| 		fprintf(f, "width %d ", memory->width); | ||||
| 		f << stringf("width %d ", memory->width); | ||||
| 	if (memory->size != 0) | ||||
| 		fprintf(f, "size %d ", memory->size); | ||||
| 	fprintf(f, "%s\n", memory->name.c_str()); | ||||
| 		f << stringf("size %d ", memory->size); | ||||
| 	f << stringf("%s\n", memory->name.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_cell(FILE *f, std::string indent, const RTLIL::Cell *cell) | ||||
| void ILANG_BACKEND::dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell) | ||||
| { | ||||
| 	for (auto it = cell->attributes.begin(); it != cell->attributes.end(); it++) { | ||||
| 		fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 	std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_attributes(cell->attributes.begin(), cell->attributes.end()); | ||||
| 	std::map<RTLIL::IdString, RTLIL::Const, RTLIL::sort_by_id_str> sorted_parameters(cell->parameters.begin(), cell->parameters.end()); | ||||
| 	std::map<RTLIL::IdString, RTLIL::SigSpec, RTLIL::sort_by_id_str> sorted_connections(cell->connections().begin(), cell->connections().end()); | ||||
| 
 | ||||
| 	for (auto it = sorted_attributes.begin(); it != sorted_attributes.end(); it++) { | ||||
| 		f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	fprintf(f, "%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); | ||||
| 	for (auto it = cell->parameters.begin(); it != cell->parameters.end(); it++) { | ||||
| 		fprintf(f, "%s  parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); | ||||
| 	f << stringf("%s" "cell %s %s\n", indent.c_str(), cell->type.c_str(), cell->name.c_str()); | ||||
| 	for (auto it = sorted_parameters.begin(); it != sorted_parameters.end(); it++) { | ||||
| 		f << stringf("%s  parameter%s %s ", indent.c_str(), (it->second.flags & RTLIL::CONST_FLAG_SIGNED) != 0 ? " signed" : "", it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	for (auto it = cell->connections.begin(); it != cell->connections.end(); it++) { | ||||
| 		fprintf(f, "%s  connect %s ", indent.c_str(), it->first.c_str()); | ||||
| 	for (auto it = sorted_connections.begin(); it != sorted_connections.end(); it++) { | ||||
| 		f << stringf("%s  connect %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_sigspec(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	fprintf(f, "%s" "end\n", indent.c_str()); | ||||
| 	f << stringf("%s" "end\n", indent.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_proc_case_body(FILE *f, std::string indent, const RTLIL::CaseRule *cs) | ||||
| void ILANG_BACKEND::dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs) | ||||
| { | ||||
| 	for (auto it = cs->actions.begin(); it != cs->actions.end(); it++) | ||||
| 	{ | ||||
| 		fprintf(f, "%s" "assign ", indent.c_str()); | ||||
| 		f << stringf("%s" "assign ", indent.c_str()); | ||||
| 		dump_sigspec(f, it->first); | ||||
| 		fprintf(f, " "); | ||||
| 		f << stringf(" "); | ||||
| 		dump_sigspec(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto it = cs->switches.begin(); it != cs->switches.end(); it++) | ||||
| 		dump_proc_switch(f, indent, *it); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_proc_switch(FILE *f, std::string indent, const RTLIL::SwitchRule *sw) | ||||
| void ILANG_BACKEND::dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw) | ||||
| { | ||||
| 	for (auto it = sw->attributes.begin(); it != sw->attributes.end(); it++) { | ||||
| 		fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(f, "%s" "switch ", indent.c_str()); | ||||
| 	f << stringf("%s" "switch ", indent.c_str()); | ||||
| 	dump_sigspec(f, sw->signal); | ||||
| 	fprintf(f, "\n"); | ||||
| 	f << stringf("\n"); | ||||
| 
 | ||||
| 	for (auto it = sw->cases.begin(); it != sw->cases.end(); it++) | ||||
| 	{ | ||||
| 		fprintf(f, "%s  case ", indent.c_str()); | ||||
| 		f << stringf("%s  case ", indent.c_str()); | ||||
| 		for (size_t i = 0; i < (*it)->compare.size(); i++) { | ||||
| 			if (i > 0) | ||||
| 				fprintf(f, ", "); | ||||
| 				f << stringf(", "); | ||||
| 			dump_sigspec(f, (*it)->compare[i]); | ||||
| 		} | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 
 | ||||
| 		dump_proc_case_body(f, indent + "    ", *it); | ||||
| 	} | ||||
| 
 | ||||
| 	fprintf(f, "%s" "end\n", indent.c_str()); | ||||
| 	f << stringf("%s" "end\n", indent.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_proc_sync(FILE *f, std::string indent, const RTLIL::SyncRule *sy) | ||||
| void ILANG_BACKEND::dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy) | ||||
| { | ||||
| 	fprintf(f, "%s" "sync ", indent.c_str()); | ||||
| 	f << stringf("%s" "sync ", indent.c_str()); | ||||
| 	switch (sy->type) { | ||||
| 	if (0) case RTLIL::ST0: fprintf(f, "low "); | ||||
| 	if (0) case RTLIL::ST1: fprintf(f, "high "); | ||||
| 	if (0) case RTLIL::STp: fprintf(f, "posedge "); | ||||
| 	if (0) case RTLIL::STn: fprintf(f, "negedge "); | ||||
| 	if (0) case RTLIL::STe: fprintf(f, "edge "); | ||||
| 	if (0) case RTLIL::ST0: f << stringf("low "); | ||||
| 	if (0) case RTLIL::ST1: f << stringf("high "); | ||||
| 	if (0) case RTLIL::STp: f << stringf("posedge "); | ||||
| 	if (0) case RTLIL::STn: f << stringf("negedge "); | ||||
| 	if (0) case RTLIL::STe: f << stringf("edge "); | ||||
| 		dump_sigspec(f, sy->signal); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 		break; | ||||
| 	case RTLIL::STa: fprintf(f, "always\n"); break; | ||||
| 	case RTLIL::STi: fprintf(f, "init\n"); break; | ||||
| 	case RTLIL::STa: f << stringf("always\n"); break; | ||||
| 	case RTLIL::STi: f << stringf("init\n"); break; | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto it = sy->actions.begin(); it != sy->actions.end(); it++) { | ||||
| 		fprintf(f, "%s  update ", indent.c_str()); | ||||
| 		f << stringf("%s  update ", indent.c_str()); | ||||
| 		dump_sigspec(f, it->first); | ||||
| 		fprintf(f, " "); | ||||
| 		f << stringf(" "); | ||||
| 		dump_sigspec(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_proc(FILE *f, std::string indent, const RTLIL::Process *proc) | ||||
| void ILANG_BACKEND::dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc) | ||||
| { | ||||
| 	for (auto it = proc->attributes.begin(); it != proc->attributes.end(); it++) { | ||||
| 		fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 		dump_const(f, it->second); | ||||
| 		fprintf(f, "\n"); | ||||
| 		f << stringf("\n"); | ||||
| 	} | ||||
| 	fprintf(f, "%s" "process %s\n", indent.c_str(), proc->name.c_str()); | ||||
| 	f << stringf("%s" "process %s\n", indent.c_str(), proc->name.c_str()); | ||||
| 	dump_proc_case_body(f, indent + "  ", &proc->root_case); | ||||
| 	for (auto it = proc->syncs.begin(); it != proc->syncs.end(); it++) | ||||
| 		dump_proc_sync(f, indent + "  ", *it); | ||||
| 	fprintf(f, "%s" "end\n", indent.c_str()); | ||||
| 	f << stringf("%s" "end\n", indent.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_conn(FILE *f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) | ||||
| void ILANG_BACKEND::dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right) | ||||
| { | ||||
| 	fprintf(f, "%s" "connect ", indent.c_str()); | ||||
| 	f << stringf("%s" "connect ", indent.c_str()); | ||||
| 	dump_sigspec(f, left); | ||||
| 	fprintf(f, " "); | ||||
| 	f << stringf(" "); | ||||
| 	dump_sigspec(f, right); | ||||
| 	fprintf(f, "\n"); | ||||
| 	f << stringf("\n"); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module *module, const RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) | ||||
| void ILANG_BACKEND::dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) | ||||
| { | ||||
| 	bool print_header = flag_m || design->selected_whole_module(module->name); | ||||
| 	bool print_body = !flag_n || !design->selected_whole_module(module->name); | ||||
|  | @ -269,51 +275,71 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module | |||
| 	if (print_header) | ||||
| 	{ | ||||
| 		for (auto it = module->attributes.begin(); it != module->attributes.end(); it++) { | ||||
| 			fprintf(f, "%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 			f << stringf("%s" "attribute %s ", indent.c_str(), it->first.c_str()); | ||||
| 			dump_const(f, it->second); | ||||
| 			fprintf(f, "\n"); | ||||
| 			f << stringf("\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(f, "%s" "module %s\n", indent.c_str(), module->name.c_str()); | ||||
| 		f << stringf("%s" "module %s\n", indent.c_str(), module->name.c_str()); | ||||
| 	} | ||||
| 
 | ||||
| 	if (print_body) | ||||
| 	{ | ||||
| 		for (auto it = module->wires.begin(); it != module->wires.end(); it++) | ||||
| 			if (!only_selected || design->selected(module, it->second)) { | ||||
| 		std::vector<RTLIL::Wire*> sorted_wires; | ||||
| 		for (auto it : module->wires()) | ||||
| 			sorted_wires.push_back(it); | ||||
| 		std::sort(sorted_wires.begin(), sorted_wires.end(), RTLIL::sort_by_name_str<RTLIL::Wire>()); | ||||
| 
 | ||||
| 		std::vector<RTLIL::Memory*> sorted_memories; | ||||
| 		for (auto it : module->memories) | ||||
| 			sorted_memories.push_back(it.second); | ||||
| 		std::sort(sorted_memories.begin(), sorted_memories.end(), RTLIL::sort_by_name_str<RTLIL::Memory>()); | ||||
| 
 | ||||
| 		std::vector<RTLIL::Cell*> sorted_cells; | ||||
| 		for (auto it : module->cells()) | ||||
| 			sorted_cells.push_back(it); | ||||
| 		std::sort(sorted_cells.begin(), sorted_cells.end(), RTLIL::sort_by_name_str<RTLIL::Cell>()); | ||||
| 
 | ||||
| 		std::vector<RTLIL::Process*> sorted_processes; | ||||
| 		for (auto it : module->processes) | ||||
| 			sorted_processes.push_back(it.second); | ||||
| 		std::sort(sorted_processes.begin(), sorted_processes.end(), RTLIL::sort_by_name_str<RTLIL::Process>()); | ||||
| 
 | ||||
| 		for (auto it : sorted_wires) | ||||
| 			if (!only_selected || design->selected(module, it)) { | ||||
| 				if (only_selected) | ||||
| 					fprintf(f, "\n"); | ||||
| 				dump_wire(f, indent + "  ", it->second); | ||||
| 					f << stringf("\n"); | ||||
| 				dump_wire(f, indent + "  ", it); | ||||
| 			} | ||||
| 
 | ||||
| 		for (auto it = module->memories.begin(); it != module->memories.end(); it++) | ||||
| 			if (!only_selected || design->selected(module, it->second)) { | ||||
| 		for (auto it : sorted_memories) | ||||
| 			if (!only_selected || design->selected(module, it)) { | ||||
| 				if (only_selected) | ||||
| 					fprintf(f, "\n"); | ||||
| 				dump_memory(f, indent + "  ", it->second); | ||||
| 					f << stringf("\n"); | ||||
| 				dump_memory(f, indent + "  ", it); | ||||
| 			} | ||||
| 
 | ||||
| 		for (auto it = module->cells.begin(); it != module->cells.end(); it++) | ||||
| 			if (!only_selected || design->selected(module, it->second)) { | ||||
| 		for (auto it : sorted_cells) | ||||
| 			if (!only_selected || design->selected(module, it)) { | ||||
| 				if (only_selected) | ||||
| 					fprintf(f, "\n"); | ||||
| 				dump_cell(f, indent + "  ", it->second); | ||||
| 					f << stringf("\n"); | ||||
| 				dump_cell(f, indent + "  ", it); | ||||
| 			} | ||||
| 
 | ||||
| 		for (auto it = module->processes.begin(); it != module->processes.end(); it++) | ||||
| 			if (!only_selected || design->selected(module, it->second)) { | ||||
| 		for (auto it : sorted_processes) | ||||
| 			if (!only_selected || design->selected(module, it)) { | ||||
| 				if (only_selected) | ||||
| 					fprintf(f, "\n"); | ||||
| 				dump_proc(f, indent + "  ", it->second); | ||||
| 					f << stringf("\n"); | ||||
| 				dump_proc(f, indent + "  ", it); | ||||
| 			} | ||||
| 
 | ||||
| 		bool first_conn_line = true; | ||||
| 		for (auto it = module->connections.begin(); it != module->connections.end(); it++) { | ||||
| 		for (auto it = module->connections().begin(); it != module->connections().end(); it++) { | ||||
| 			bool show_conn = !only_selected; | ||||
| 			if (only_selected) { | ||||
| 				RTLIL::SigSpec sigs = it->first; | ||||
| 				sigs.append(it->second); | ||||
| 				for (auto &c : sigs.chunks) { | ||||
| 				for (auto &c : sigs.chunks()) { | ||||
| 					if (c.wire == NULL || !design->selected(module, c.wire)) | ||||
| 						continue; | ||||
| 					show_conn = true; | ||||
|  | @ -321,7 +347,7 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module | |||
| 			} | ||||
| 			if (show_conn) { | ||||
| 				if (only_selected && first_conn_line) | ||||
| 					fprintf(f, "\n"); | ||||
| 					f << stringf("\n"); | ||||
| 				dump_conn(f, indent + "  ", it->first, it->second); | ||||
| 				first_conn_line = false; | ||||
| 			} | ||||
|  | @ -329,27 +355,40 @@ void ILANG_BACKEND::dump_module(FILE *f, std::string indent, const RTLIL::Module | |||
| 	} | ||||
| 
 | ||||
| 	if (print_header) | ||||
| 		fprintf(f, "%s" "end\n", indent.c_str()); | ||||
| 		f << stringf("%s" "end\n", indent.c_str()); | ||||
| } | ||||
| 
 | ||||
| void ILANG_BACKEND::dump_design(FILE *f, const RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) | ||||
| void ILANG_BACKEND::dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m, bool flag_n) | ||||
| { | ||||
| 	int init_autoidx = autoidx; | ||||
| 
 | ||||
| 	if (!flag_m) { | ||||
| 		int count_selected_mods = 0; | ||||
| 		for (auto it = design->modules.begin(); it != design->modules.end(); it++) | ||||
| 		for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { | ||||
| 			if (design->selected_whole_module(it->first)) | ||||
| 				flag_m = true; | ||||
| 			if (design->selected(it->second)) | ||||
| 				count_selected_mods++; | ||||
| 		} | ||||
| 		if (count_selected_mods > 1) | ||||
| 			flag_m = true; | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto it = design->modules.begin(); it != design->modules.end(); it++) { | ||||
| 	if (!only_selected || flag_m) { | ||||
| 		if (only_selected) | ||||
| 			f << stringf("\n"); | ||||
| 		f << stringf("autoidx %d\n", autoidx); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto it = design->modules_.begin(); it != design->modules_.end(); it++) { | ||||
| 		if (!only_selected || design->selected(it->second)) { | ||||
| 			if (only_selected) | ||||
| 				fprintf(f, "\n"); | ||||
| 				f << stringf("\n"); | ||||
| 			dump_module(f, "", it->second, design, only_selected, flag_m, flag_n); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	log_assert(init_autoidx == autoidx); | ||||
| } | ||||
| 
 | ||||
| struct IlangBackend : public Backend { | ||||
|  | @ -367,7 +406,7 @@ struct IlangBackend : public Backend { | |||
| 		log("        only write selected parts of the design.\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		bool selected = false; | ||||
| 
 | ||||
|  | @ -385,8 +424,8 @@ struct IlangBackend : public Backend { | |||
| 		extra_args(f, filename, args, argidx); | ||||
| 
 | ||||
| 		log("Output filename: %s\n", filename.c_str()); | ||||
| 		fprintf(f, "# Generated by %s\n", yosys_version_str); | ||||
| 		ILANG_BACKEND::dump_design(f, design, selected, true, false); | ||||
| 		*f << stringf("# Generated by %s\n", yosys_version_str); | ||||
| 		ILANG_BACKEND::dump_design(*f, design, selected, true, false); | ||||
| 	} | ||||
| } IlangBackend; | ||||
| 
 | ||||
|  | @ -446,25 +485,27 @@ struct DumpPass : public Pass { | |||
| 		} | ||||
| 		extra_args(args, argidx, design); | ||||
| 
 | ||||
| 		FILE *f = NULL; | ||||
| 		char *buf_ptr; | ||||
| 		size_t buf_size; | ||||
| 		std::ostream *f; | ||||
| 		std::stringstream buf; | ||||
| 
 | ||||
| 		if (!filename.empty()) { | ||||
| 			f = fopen(filename.c_str(), append ? "a" : "w"); | ||||
| 			if (f == NULL) | ||||
| 			std::ofstream *ff = new std::ofstream; | ||||
| 			ff->open(filename.c_str(), append ? std::ofstream::app : std::ofstream::trunc); | ||||
| 			if (ff->fail()) { | ||||
| 				delete ff; | ||||
| 				log_error("Can't open file `%s' for writing: %s\n", filename.c_str(), strerror(errno)); | ||||
| 			} | ||||
| 			f = ff; | ||||
| 		} else { | ||||
| 			f = open_memstream(&buf_ptr, &buf_size); | ||||
| 			f = &buf; | ||||
| 		} | ||||
| 
 | ||||
| 		ILANG_BACKEND::dump_design(f, design, true, flag_m, flag_n); | ||||
| 		ILANG_BACKEND::dump_design(*f, design, true, flag_m, flag_n); | ||||
| 
 | ||||
| 		fclose(f); | ||||
| 
 | ||||
| 		if (filename.empty()) { | ||||
| 			log("%s", buf_ptr); | ||||
| 			free(buf_ptr); | ||||
| 		if (!filename.empty()) { | ||||
| 			delete f; | ||||
| 		} else { | ||||
| 			log("%s", buf.str().c_str()); | ||||
| 		} | ||||
| 	} | ||||
| } DumpPass; | ||||
|  |  | |||
|  | @ -25,23 +25,27 @@ | |||
| #ifndef ILANG_BACKEND_H | ||||
| #define ILANG_BACKEND_H | ||||
| 
 | ||||
| #include "kernel/rtlil.h" | ||||
| #include "kernel/yosys.h" | ||||
| #include <stdio.h> | ||||
| 
 | ||||
| YOSYS_NAMESPACE_BEGIN | ||||
| 
 | ||||
| namespace ILANG_BACKEND { | ||||
| 	void dump_const(FILE *f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true); | ||||
| 	void dump_sigchunk(FILE *f, const RTLIL::SigChunk &chunk, bool autoint = true); | ||||
| 	void dump_sigspec(FILE *f, const RTLIL::SigSpec &sig, bool autoint = true); | ||||
| 	void dump_wire(FILE *f, std::string indent, const RTLIL::Wire *wire); | ||||
| 	void dump_memory(FILE *f, std::string indent, const RTLIL::Memory *memory); | ||||
| 	void dump_cell(FILE *f, std::string indent, const RTLIL::Cell *cell); | ||||
| 	void dump_proc_case_body(FILE *f, std::string indent, const RTLIL::CaseRule *cs); | ||||
| 	void dump_proc_switch(FILE *f, std::string indent, const RTLIL::SwitchRule *sw); | ||||
| 	void dump_proc_sync(FILE *f, std::string indent, const RTLIL::SyncRule *sy); | ||||
| 	void dump_proc(FILE *f, std::string indent, const RTLIL::Process *proc); | ||||
| 	void dump_conn(FILE *f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right); | ||||
| 	void dump_module(FILE *f, std::string indent, const RTLIL::Module *module, const RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); | ||||
| 	void dump_design(FILE *f, const RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); | ||||
| 	void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int offset = 0, bool autoint = true); | ||||
| 	void dump_sigchunk(std::ostream &f, const RTLIL::SigChunk &chunk, bool autoint = true); | ||||
| 	void dump_sigspec(std::ostream &f, const RTLIL::SigSpec &sig, bool autoint = true); | ||||
| 	void dump_wire(std::ostream &f, std::string indent, const RTLIL::Wire *wire); | ||||
| 	void dump_memory(std::ostream &f, std::string indent, const RTLIL::Memory *memory); | ||||
| 	void dump_cell(std::ostream &f, std::string indent, const RTLIL::Cell *cell); | ||||
| 	void dump_proc_case_body(std::ostream &f, std::string indent, const RTLIL::CaseRule *cs); | ||||
| 	void dump_proc_switch(std::ostream &f, std::string indent, const RTLIL::SwitchRule *sw); | ||||
| 	void dump_proc_sync(std::ostream &f, std::string indent, const RTLIL::SyncRule *sy); | ||||
| 	void dump_proc(std::ostream &f, std::string indent, const RTLIL::Process *proc); | ||||
| 	void dump_conn(std::ostream &f, std::string indent, const RTLIL::SigSpec &left, const RTLIL::SigSpec &right); | ||||
| 	void dump_module(std::ostream &f, std::string indent, RTLIL::Module *module, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); | ||||
| 	void dump_design(std::ostream &f, RTLIL::Design *design, bool only_selected, bool flag_m = true, bool flag_n = false); | ||||
| } | ||||
| 
 | ||||
| YOSYS_NAMESPACE_END | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
|  | @ -23,30 +23,23 @@ | |||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| 
 | ||||
| static std::string netname(std::set<std::string> &conntypes_code, std::set<std::string> &celltypes_code, std::set<std::string> &constcells_code, RTLIL::SigSpec sig) | ||||
| { | ||||
| 	sig.optimize(); | ||||
| 
 | ||||
| 	if (sig.chunks.size() != 1) | ||||
| error: | ||||
| 	if (!sig.is_fully_const() && !sig.is_wire()) | ||||
| 		log_error("Can't export composite or non-word-wide signal %s.\n", log_signal(sig)); | ||||
| 
 | ||||
| 	conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.width, sig.width, sig.width)); | ||||
| 	conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); | ||||
| 
 | ||||
| 	if (sig.chunks[0].wire == NULL) { | ||||
| 		celltypes_code.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig.width, sig.width, sig.width)); | ||||
| 		constcells_code.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n", sig.width, sig.chunks[0].data.as_int(), | ||||
| 				sig.width, sig.width, sig.chunks[0].data.as_int(), sig.chunks[0].data.as_int())); | ||||
| 		return stringf("CONST_%d_0x%x", sig.width, sig.chunks[0].data.as_int()); | ||||
| 	if (sig.is_fully_const()) { | ||||
| 		celltypes_code.insert(stringf("celltype CONST_%d b%d *CONST cfg:%d VALUE\n", sig.size(), sig.size(), sig.size())); | ||||
| 		constcells_code.insert(stringf("node CONST_%d_0x%x CONST_%d CONST CONST_%d_0x%x VALUE 0x%x\n", | ||||
| 				sig.size(), sig.as_int(), sig.size(), sig.size(), sig.as_int(), sig.as_int())); | ||||
| 		return stringf("CONST_%d_0x%x", sig.size(), sig.as_int()); | ||||
| 	} | ||||
| 
 | ||||
| 	if (sig.chunks[0].offset != 0 || sig.width != sig.chunks[0].wire->width) | ||||
| 		goto error; | ||||
| 
 | ||||
| 	return RTLIL::unescape_id(sig.chunks[0].wire->name); | ||||
| 	return RTLIL::unescape_id(sig.as_wire()->name); | ||||
| } | ||||
| 
 | ||||
| struct IntersynthBackend : public Backend { | ||||
|  | @ -76,7 +69,7 @@ struct IntersynthBackend : public Backend { | |||
| 		log("http://www.clifford.at/intersynth/\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		log_header("Executing INTERSYNTH backend.\n"); | ||||
| 		log_push(); | ||||
|  | @ -108,13 +101,13 @@ struct IntersynthBackend : public Backend { | |||
| 		log("Output filename: %s\n", filename.c_str()); | ||||
| 
 | ||||
| 		for (auto filename : libfiles) { | ||||
| 			FILE *f = fopen(filename.c_str(), "rt"); | ||||
| 			if (f == NULL) | ||||
| 			std::ifstream f; | ||||
| 			f.open(filename.c_str()); | ||||
| 			if (f.fail()) | ||||
| 				log_error("Can't open lib file `%s'.\n", filename.c_str()); | ||||
| 			RTLIL::Design *lib = new RTLIL::Design; | ||||
| 			Frontend::frontend_call(lib, f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog"); | ||||
| 			Frontend::frontend_call(lib, &f, filename, (filename.size() > 3 && filename.substr(filename.size()-3) == ".il") ? "ilang" : "verilog"); | ||||
| 			libs.push_back(lib); | ||||
| 			fclose(f); | ||||
| 		} | ||||
| 
 | ||||
| 		if (libs.size() > 0) | ||||
|  | @ -127,14 +120,14 @@ struct IntersynthBackend : public Backend { | |||
| 		for (auto lib : libs) | ||||
| 			ct.setup_design(lib); | ||||
| 
 | ||||
| 		for (auto module_it : design->modules) | ||||
| 		for (auto module_it : design->modules_) | ||||
| 		{ | ||||
| 			RTLIL::Module *module = module_it.second; | ||||
| 			SigMap sigmap(module); | ||||
| 
 | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
| 				continue; | ||||
| 			if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells.size() == 0) | ||||
| 			if (module->memories.size() == 0 && module->processes.size() == 0 && module->cells_.size() == 0) | ||||
| 				continue; | ||||
| 
 | ||||
| 			if (selected && !design->selected_whole_module(module->name)) { | ||||
|  | @ -153,7 +146,7 @@ struct IntersynthBackend : public Backend { | |||
| 			netlists_code += stringf("netlist %s\n", RTLIL::id2cstr(module->name)); | ||||
| 
 | ||||
| 			// Module Ports: "std::set<string> celltypes_code" prevents duplicate top level ports
 | ||||
| 			for (auto wire_it : module->wires) { | ||||
| 			for (auto wire_it : module->wires_) { | ||||
| 				RTLIL::Wire *wire = wire_it.second; | ||||
| 				if (wire->port_input || wire->port_output) { | ||||
| 					celltypes_code.insert(stringf("celltype !%s b%d %sPORT\n" "%s %s %d %s PORT\n", | ||||
|  | @ -165,7 +158,7 @@ struct IntersynthBackend : public Backend { | |||
| 			} | ||||
| 
 | ||||
| 			// Submodules: "std::set<string> celltypes_code" prevents duplicate cell types 
 | ||||
| 			for (auto cell_it : module->cells) | ||||
| 			for (auto cell_it : module->cells_) | ||||
| 			{ | ||||
| 				RTLIL::Cell *cell = cell_it.second; | ||||
| 				std::string celltype_code, node_code; | ||||
|  | @ -175,11 +168,11 @@ struct IntersynthBackend : public Backend { | |||
| 
 | ||||
| 				celltype_code = stringf("celltype %s", RTLIL::id2cstr(cell->type)); | ||||
| 				node_code = stringf("node %s %s", RTLIL::id2cstr(cell->name), RTLIL::id2cstr(cell->type)); | ||||
| 				for (auto &port : cell->connections) { | ||||
| 				for (auto &port : cell->connections()) { | ||||
| 					RTLIL::SigSpec sig = sigmap(port.second); | ||||
| 					if (sig.width != 0) { | ||||
| 						conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.width, sig.width, sig.width)); | ||||
| 						celltype_code += stringf(" b%d %s%s", sig.width, ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); | ||||
| 					if (sig.size() != 0) { | ||||
| 						conntypes_code.insert(stringf("conntype b%d %d 2 %d\n", sig.size(), sig.size(), sig.size())); | ||||
| 						celltype_code += stringf(" b%d %s%s", sig.size(), ct.cell_output(cell->type, port.first) ? "*" : "", RTLIL::id2cstr(port.first)); | ||||
| 						node_code += stringf(" %s %s", RTLIL::id2cstr(port.first), netname(conntypes_code, celltypes_code, constcells_code, sig).c_str()); | ||||
| 					} | ||||
| 				} | ||||
|  | @ -205,15 +198,15 @@ struct IntersynthBackend : public Backend { | |||
| 		} | ||||
| 
 | ||||
| 		if (!flag_notypes) { | ||||
| 			fprintf(f, "### Connection Types\n"); | ||||
| 			*f << stringf("### Connection Types\n"); | ||||
| 			for (auto code : conntypes_code) | ||||
| 				fprintf(f, "%s", code.c_str()); | ||||
| 			fprintf(f, "\n### Cell Types\n"); | ||||
| 				*f << stringf("%s", code.c_str()); | ||||
| 			*f << stringf("\n### Cell Types\n"); | ||||
| 			for (auto code : celltypes_code) | ||||
| 				fprintf(f, "%s", code.c_str()); | ||||
| 				*f << stringf("%s", code.c_str()); | ||||
| 		} | ||||
| 		fprintf(f, "\n### Netlists\n"); | ||||
| 		fprintf(f, "%s", netlists_code.c_str()); | ||||
| 		*f << stringf("\n### Netlists\n"); | ||||
| 		*f << stringf("%s", netlists_code.c_str()); | ||||
| 
 | ||||
| 		for (auto lib : libs) | ||||
| 			delete lib; | ||||
|  |  | |||
|  | @ -23,53 +23,51 @@ | |||
| #include "kernel/celltypes.h" | ||||
| #include "kernel/log.h" | ||||
| #include <string> | ||||
| #include <assert.h> | ||||
| 
 | ||||
| static void print_spice_net(FILE *f, RTLIL::SigSpec s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter) | ||||
| static void print_spice_net(std::ostream &f, RTLIL::SigBit s, std::string &neg, std::string &pos, std::string &ncpf, int &nc_counter) | ||||
| { | ||||
| 	log_assert(s.chunks.size() == 1 && s.chunks[0].width == 1); | ||||
| 	if (s.chunks[0].wire) { | ||||
| 		if (s.chunks[0].wire->width > 1) | ||||
| 			fprintf(f, " %s[%d]", RTLIL::id2cstr(s.chunks[0].wire->name), s.chunks[0].offset); | ||||
| 	if (s.wire) { | ||||
| 		if (s.wire->width > 1) | ||||
| 			f << stringf(" %s[%d]", RTLIL::id2cstr(s.wire->name), s.offset); | ||||
| 		else | ||||
| 			fprintf(f, " %s", RTLIL::id2cstr(s.chunks[0].wire->name)); | ||||
| 			f << stringf(" %s", RTLIL::id2cstr(s.wire->name)); | ||||
| 	} else { | ||||
| 		if (s.chunks[0].data.bits.at(0) == RTLIL::State::S0) | ||||
| 			fprintf(f, " %s", neg.c_str()); | ||||
| 		else if (s.chunks[0].data.bits.at(0) == RTLIL::State::S1) | ||||
| 			fprintf(f, " %s", pos.c_str()); | ||||
| 		if (s == RTLIL::State::S0) | ||||
| 			f << stringf(" %s", neg.c_str()); | ||||
| 		else if (s == RTLIL::State::S1) | ||||
| 			f << stringf(" %s", pos.c_str()); | ||||
| 		else | ||||
| 			fprintf(f, " %s%d", ncpf.c_str(), nc_counter++); | ||||
| 			f << stringf(" %s%d", ncpf.c_str(), nc_counter++); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian) | ||||
| static void print_spice_module(std::ostream &f, RTLIL::Module *module, RTLIL::Design *design, std::string &neg, std::string &pos, std::string &ncpf, bool big_endian) | ||||
| { | ||||
| 	SigMap sigmap(module); | ||||
| 	int cell_counter = 0, conn_counter = 0, nc_counter = 0; | ||||
| 
 | ||||
| 	for (auto &cell_it : module->cells) | ||||
| 	for (auto &cell_it : module->cells_) | ||||
| 	{ | ||||
| 		RTLIL::Cell *cell = cell_it.second; | ||||
| 		fprintf(f, "X%d", cell_counter++); | ||||
| 		f << stringf("X%d", cell_counter++); | ||||
| 
 | ||||
| 		std::vector<RTLIL::SigSpec> port_sigs; | ||||
| 
 | ||||
| 		if (design->modules.count(cell->type) == 0) | ||||
| 		if (design->modules_.count(cell->type) == 0) | ||||
| 		{ | ||||
| 			log("Warning: no (blackbox) module for cell type `%s' (%s.%s) found! Guessing order of ports.\n", | ||||
| 					RTLIL::id2cstr(cell->type), RTLIL::id2cstr(module->name), RTLIL::id2cstr(cell->name)); | ||||
| 			for (auto &conn : cell->connections) { | ||||
| 			for (auto &conn : cell->connections()) { | ||||
| 				RTLIL::SigSpec sig = sigmap(conn.second); | ||||
| 				port_sigs.push_back(sig); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			RTLIL::Module *mod = design->modules.at(cell->type); | ||||
| 			RTLIL::Module *mod = design->modules_.at(cell->type); | ||||
| 
 | ||||
| 			std::vector<RTLIL::Wire*> ports; | ||||
| 			for (auto wire_it : mod->wires) { | ||||
| 			for (auto wire_it : mod->wires_) { | ||||
| 				RTLIL::Wire *wire = wire_it.second; | ||||
| 				if (wire->port_id == 0) | ||||
| 					continue; | ||||
|  | @ -81,8 +79,8 @@ static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *de | |||
| 			for (RTLIL::Wire *wire : ports) { | ||||
| 				log_assert(wire != NULL); | ||||
| 				RTLIL::SigSpec sig(RTLIL::State::Sz, wire->width); | ||||
| 				if (cell->connections.count(wire->name) > 0) { | ||||
| 					sig = sigmap(cell->connections.at(wire->name)); | ||||
| 				if (cell->hasPort(wire->name)) { | ||||
| 					sig = sigmap(cell->getPort(wire->name)); | ||||
| 					sig.extend(wire->width, false); | ||||
| 				} | ||||
| 				port_sigs.push_back(sig); | ||||
|  | @ -90,22 +88,21 @@ static void print_spice_module(FILE *f, RTLIL::Module *module, RTLIL::Design *de | |||
| 		} | ||||
| 
 | ||||
| 		for (auto &sig : port_sigs) { | ||||
| 			for (int i = 0; i < sig.width; i++) { | ||||
| 				RTLIL::SigSpec s = sig.extract(big_endian ? sig.width - 1 - i : i, 1); | ||||
| 				log_assert(s.chunks.size() == 1 && s.chunks[0].width == 1); | ||||
| 			for (int i = 0; i < sig.size(); i++) { | ||||
| 				RTLIL::SigSpec s = sig.extract(big_endian ? sig.size() - 1 - i : i, 1); | ||||
| 				print_spice_net(f, s, neg, pos, ncpf, nc_counter); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(f, " %s\n", RTLIL::id2cstr(cell->type)); | ||||
| 		f << stringf(" %s\n", RTLIL::id2cstr(cell->type)); | ||||
| 	} | ||||
| 
 | ||||
| 	for (auto &conn : module->connections) | ||||
| 	for (int i = 0; i < conn.first.width; i++) { | ||||
| 		fprintf(f, "V%d", conn_counter++); | ||||
| 	for (auto &conn : module->connections()) | ||||
| 	for (int i = 0; i < conn.first.size(); i++) { | ||||
| 		f << stringf("V%d", conn_counter++); | ||||
| 		print_spice_net(f, conn.first.extract(i, 1), neg, pos, ncpf, nc_counter); | ||||
| 		print_spice_net(f, conn.second.extract(i, 1), neg, pos, ncpf, nc_counter); | ||||
| 		fprintf(f, " DC 0\n"); | ||||
| 		f << stringf(" DC 0\n"); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
|  | @ -136,7 +133,7 @@ struct SpiceBackend : public Backend { | |||
| 		log("        set the specified module as design top module\n"); | ||||
| 		log("\n"); | ||||
| 	} | ||||
| 	virtual void execute(FILE *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	virtual void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) | ||||
| 	{ | ||||
| 		std::string top_module_name; | ||||
| 		RTLIL::Module *top_module = NULL; | ||||
|  | @ -173,14 +170,14 @@ struct SpiceBackend : public Backend { | |||
| 		extra_args(f, filename, args, argidx); | ||||
| 
 | ||||
| 		if (top_module_name.empty()) | ||||
| 			for (auto & mod_it:design->modules) | ||||
| 			for (auto & mod_it:design->modules_) | ||||
| 				if (mod_it.second->get_bool_attribute("\\top")) | ||||
| 					top_module_name = mod_it.first; | ||||
| 					top_module_name = mod_it.first.str(); | ||||
| 
 | ||||
| 		fprintf(f, "* SPICE netlist generated by %s\n", yosys_version_str); | ||||
| 		fprintf(f, "\n"); | ||||
| 		*f << stringf("* SPICE netlist generated by %s\n", yosys_version_str); | ||||
| 		*f << stringf("\n"); | ||||
| 
 | ||||
| 		for (auto module_it : design->modules) | ||||
| 		for (auto module_it : design->modules_) | ||||
| 		{ | ||||
| 			RTLIL::Module *module = module_it.second; | ||||
| 			if (module->get_bool_attribute("\\blackbox")) | ||||
|  | @ -197,7 +194,7 @@ struct SpiceBackend : public Backend { | |||
| 			} | ||||
| 
 | ||||
| 			std::vector<RTLIL::Wire*> ports; | ||||
| 			for (auto wire_it : module->wires) { | ||||
| 			for (auto wire_it : module->wires_) { | ||||
| 				RTLIL::Wire *wire = wire_it.second; | ||||
| 				if (wire->port_id == 0) | ||||
| 					continue; | ||||
|  | @ -206,31 +203,31 @@ struct SpiceBackend : public Backend { | |||
| 				ports.at(wire->port_id-1) = wire; | ||||
| 			} | ||||
| 
 | ||||
| 			fprintf(f, ".SUBCKT %s", RTLIL::id2cstr(module->name)); | ||||
| 			*f << stringf(".SUBCKT %s", RTLIL::id2cstr(module->name)); | ||||
| 			for (RTLIL::Wire *wire : ports) { | ||||
| 				log_assert(wire != NULL); | ||||
| 				if (wire->width > 1) { | ||||
| 					for (int i = 0; i < wire->width; i++) | ||||
| 						fprintf(f, " %s[%d]", RTLIL::id2cstr(wire->name), big_endian ? wire->width - 1 - i : i); | ||||
| 						*f << stringf(" %s[%d]", RTLIL::id2cstr(wire->name), big_endian ? wire->width - 1 - i : i); | ||||
| 				} else | ||||
| 					fprintf(f, " %s", RTLIL::id2cstr(wire->name)); | ||||
| 					*f << stringf(" %s", RTLIL::id2cstr(wire->name)); | ||||
| 			} | ||||
| 			fprintf(f, "\n"); | ||||
| 			print_spice_module(f, module, design, neg, pos, ncpf, big_endian); | ||||
| 			fprintf(f, ".ENDS %s\n\n", RTLIL::id2cstr(module->name)); | ||||
| 			*f << stringf("\n"); | ||||
| 			print_spice_module(*f, module, design, neg, pos, ncpf, big_endian); | ||||
| 			*f << stringf(".ENDS %s\n\n", RTLIL::id2cstr(module->name)); | ||||
| 		} | ||||
| 
 | ||||
| 		if (!top_module_name.empty()) { | ||||
| 			if (top_module == NULL) | ||||
| 				log_error("Can't find top module `%s'!\n", top_module_name.c_str()); | ||||
| 			print_spice_module(f, top_module, design, neg, pos, ncpf, big_endian); | ||||
| 			fprintf(f, "\n"); | ||||
| 			print_spice_module(*f, top_module, design, neg, pos, ncpf, big_endian); | ||||
| 			*f << stringf("\n"); | ||||
| 		} | ||||
| 
 | ||||
| 		fprintf(f, "************************\n"); | ||||
| 		fprintf(f, "* end of SPICE netlist *\n"); | ||||
| 		fprintf(f, "************************\n"); | ||||
| 		fprintf(f, "\n"); | ||||
| 		*f << stringf("************************\n"); | ||||
| 		*f << stringf("* end of SPICE netlist *\n"); | ||||
| 		*f << stringf("************************\n"); | ||||
| 		*f << stringf("\n"); | ||||
| 	} | ||||
| } SpiceBackend; | ||||
| 
 | ||||
|  |  | |||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							|  | @ -29,11 +29,10 @@ | |||
| #ifndef VERILOG_BACKEND_H | ||||
| #define VERILOG_BACKEND_H | ||||
| 
 | ||||
| #include "kernel/rtlil.h" | ||||
| #include <stdio.h> | ||||
| #include "kernel/yosys.h" | ||||
| 
 | ||||
| namespace VERILOG_BACKEND { | ||||
| 	void verilog_backend(FILE *f, std::vector<std::string> args, RTLIL::Design *design); | ||||
| 	void verilog_backend(std::ostream &f, std::vector<std::string> args, RTLIL::Design *design); | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue