mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	abc9_techmap -> _map; called from abc9 script pass along with abc9_ops
This commit is contained in:
		
							parent
							
								
									ec25394808
								
							
						
					
					
						commit
						f348ffa44d
					
				
					 4 changed files with 406 additions and 130 deletions
				
			
		| 
						 | 
				
			
			@ -8,7 +8,8 @@ OBJS += passes/techmap/libparse.o
 | 
			
		|||
ifeq ($(ENABLE_ABC),1)
 | 
			
		||||
OBJS += passes/techmap/abc.o
 | 
			
		||||
OBJS += passes/techmap/abc9.o
 | 
			
		||||
OBJS += passes/techmap/abc9_techmap.o
 | 
			
		||||
OBJS += passes/techmap/abc9_map.o
 | 
			
		||||
OBJS += passes/techmap/abc9_ops.o
 | 
			
		||||
ifneq ($(ABCEXTERNAL),)
 | 
			
		||||
passes/techmap/abc.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
 | 
			
		||||
passes/techmap/abc9.o: CXXFLAGS += -DABCEXTERNAL='"$(ABCEXTERNAL)"'
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										231
									
								
								passes/techmap/abc9.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										231
									
								
								passes/techmap/abc9.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,231 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *            (C) 2019  Eddie Hung    <eddie@fpgeh.com>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  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/celltypes.h"
 | 
			
		||||
#include "kernel/rtlil.h"
 | 
			
		||||
#include "kernel/log.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
#define XC7_WIRE_DELAY 300 // Number with which ABC will map a 6-input gate
 | 
			
		||||
                           // to one LUT6 (instead of a LUT5 + LUT2)
 | 
			
		||||
 | 
			
		||||
struct Abc9Pass : public ScriptPass
 | 
			
		||||
{
 | 
			
		||||
	Abc9Pass() : ScriptPass("abc9", "use ABC9 for technology mapping") { }
 | 
			
		||||
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    abc9 [options] [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("This pass uses the ABC tool [1] for technology mapping of yosys's internal gate\n");
 | 
			
		||||
		log("library to a target architecture.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -exe <command>\n");
 | 
			
		||||
#ifdef ABCEXTERNAL
 | 
			
		||||
		log("        use the specified command instead of \"" ABCEXTERNAL "\" to execute ABC.\n");
 | 
			
		||||
#else
 | 
			
		||||
		log("        use the specified command instead of \"<yosys-bindir>/yosys-abc\" to execute ABC.\n");
 | 
			
		||||
#endif
 | 
			
		||||
		log("        This can e.g. be used to call a specific version of ABC or a wrapper.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -script <file>\n");
 | 
			
		||||
		log("        use the specified ABC script file instead of the default script.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        if <file> starts with a plus sign (+), then the rest of the filename\n");
 | 
			
		||||
		log("        string is interpreted as the command string to be passed to ABC. The\n");
 | 
			
		||||
		log("        leading plus sign is removed and all commas (,) in the string are\n");
 | 
			
		||||
		log("        replaced with blanks before the string is passed to ABC.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        if no -script parameter is given, the following scripts are used:\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts (only one LUT size):\n");
 | 
			
		||||
		// FIXME
 | 
			
		||||
		//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts (different LUT sizes):\n");
 | 
			
		||||
		// FIXME
 | 
			
		||||
		//log("%s\n", fold_abc9_cmd(ABC_COMMAND_LUT).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -fast\n");
 | 
			
		||||
		log("        use different default scripts that are slightly faster (at the cost\n");
 | 
			
		||||
		log("        of output quality):\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts:\n");
 | 
			
		||||
		// FIXME
 | 
			
		||||
		//log("%s\n", fold_abc9_cmd(ABC_FAST_COMMAND_LUT).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -D <picoseconds>\n");
 | 
			
		||||
		log("        set delay target. the string {D} in the default scripts above is\n");
 | 
			
		||||
		log("        replaced by this option when used, and an empty string otherwise\n");
 | 
			
		||||
		log("        (indicating best possible delay).\n");
 | 
			
		||||
//		log("        This also replaces 'dretime' with 'dretime; retime -o {D}' in the\n");
 | 
			
		||||
//		log("        default scripts above.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
//		log("    -S <num>\n");
 | 
			
		||||
//		log("        maximum number of LUT inputs shared.\n");
 | 
			
		||||
//		log("        (replaces {S} in the default scripts above, default: -S 1)\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
		log("    -lut <width>\n");
 | 
			
		||||
		log("        generate netlist using luts of (max) the specified width.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -lut <w1>:<w2>\n");
 | 
			
		||||
		log("        generate netlist using luts of (max) the specified width <w2>. All\n");
 | 
			
		||||
		log("        luts with width <= <w1> have constant cost. for luts larger than <w1>\n");
 | 
			
		||||
		log("        the area cost doubles with each additional input bit. the delay cost\n");
 | 
			
		||||
		log("        is still constant for all lut widths.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -lut <file>\n");
 | 
			
		||||
		log("        pass this file with lut library to ABC.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -luts <cost1>,<cost2>,<cost3>,<sizeN>:<cost4-N>,..\n");
 | 
			
		||||
		log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
 | 
			
		||||
		log("        2, 3, .. inputs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
//		log("    -dff\n");
 | 
			
		||||
//		log("        also pass $_DFF_?_ and $_DFFE_??_ cells through ABC. modules with many\n");
 | 
			
		||||
//		log("        clock domains are automatically partitioned in clock domains and each\n");
 | 
			
		||||
//		log("        domain is passed through ABC independently.\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
//		log("    -clk [!]<clock-signal-name>[,[!]<enable-signal-name>]\n");
 | 
			
		||||
//		log("        use only the specified clock domain. this is like -dff, but only FF\n");
 | 
			
		||||
//		log("        cells that belong to the specified clock domain are used.\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
//		log("    -keepff\n");
 | 
			
		||||
//		log("        set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
 | 
			
		||||
//		log("        them, for example for equivalence checking.)\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
		log("    -nocleanup\n");
 | 
			
		||||
		log("        when this option is used, the temporary files created by this pass\n");
 | 
			
		||||
		log("        are not removed. this is useful for debugging.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -showtmp\n");
 | 
			
		||||
		log("        print the temp dir name in log. usually this is suppressed so that the\n");
 | 
			
		||||
		log("        command output is identical across runs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -markgroups\n");
 | 
			
		||||
		log("        set a 'abcgroup' attribute on all objects created by ABC. The value of\n");
 | 
			
		||||
		log("        this attribute is a unique integer for each ABC process started. This\n");
 | 
			
		||||
		log("        is useful for debugging the partitioning of clock domains.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -box <file>\n");
 | 
			
		||||
		log("        pass this file with box library to ABC. Use with -lut.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
 | 
			
		||||
		log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
 | 
			
		||||
		log("ABC on logic snippets extracted from your design. You will not get any useful\n");
 | 
			
		||||
		log("output when passing an ABC script that writes a file. Instead write your full\n");
 | 
			
		||||
		log("design as BLIF file with write_blif and then load that into ABC externally if\n");
 | 
			
		||||
		log("you want to use ABC to convert your design into another format.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("[1] http://www.eecs.berkeley.edu/~alanmi/abc/\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		help_script();
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::stringstream map_cmd;
 | 
			
		||||
	bool cleanup;
 | 
			
		||||
 | 
			
		||||
	void clear_flags() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		map_cmd.str("");
 | 
			
		||||
		map_cmd << "abc9_map";
 | 
			
		||||
		cleanup = true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		std::string run_from, run_to;
 | 
			
		||||
		clear_flags();
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++) {
 | 
			
		||||
			std::string arg = args[argidx];
 | 
			
		||||
			if ((arg == "-exe" || arg == "-script" || arg == "-D" ||
 | 
			
		||||
						/* arg == "-S" || */ arg == "-lut" || arg == "-luts" ||
 | 
			
		||||
						arg == "-clk" || arg == "-box" || arg == "-W") &&
 | 
			
		||||
					argidx+1 < args.size()) {
 | 
			
		||||
				map_cmd << " " << arg << " " << args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-fast" || /*arg == "-dff" ||*/ arg == "-keepff"
 | 
			
		||||
					/*|| arg == "-nocleanup"*/ || arg == "-showtmp" || arg == "-markgroups"
 | 
			
		||||
					|| arg == "-nomfs") {
 | 
			
		||||
				map_cmd << " " << arg;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-nocleanup") {
 | 
			
		||||
				cleanup = false;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing ABC9 pass.\n");
 | 
			
		||||
 | 
			
		||||
		run_script(design, run_from, run_to);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void script() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		auto selected_modules = active_design->selected_modules();
 | 
			
		||||
		active_design->selection_stack.emplace_back(false);
 | 
			
		||||
 | 
			
		||||
		for (auto mod : selected_modules) {
 | 
			
		||||
			log_push();
 | 
			
		||||
 | 
			
		||||
			active_design->selection().select(mod);
 | 
			
		||||
 | 
			
		||||
			std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
 | 
			
		||||
			if (!cleanup)
 | 
			
		||||
				tempdir_name[0] = tempdir_name[4] = '_';
 | 
			
		||||
			tempdir_name = make_temp_dir(tempdir_name);
 | 
			
		||||
 | 
			
		||||
			run("scc -set_attr abc9_scc_id {}");
 | 
			
		||||
			run("abc9_ops -break_scc");
 | 
			
		||||
			run("aigmap");
 | 
			
		||||
			run(stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()),
 | 
			
		||||
					"write_xaiger -map <abc-temp-dir>/input.sym <abc-temp-dir>/input.xaig");
 | 
			
		||||
			run(stringf("%s -tempdir %s", map_cmd.str().c_str(), tempdir_name.c_str()),
 | 
			
		||||
					"abc9_map [options] -tempdir <abc-temp-dir>");
 | 
			
		||||
			run("abc9_ops -unbreak_scc");
 | 
			
		||||
 | 
			
		||||
			if (cleanup)
 | 
			
		||||
			{
 | 
			
		||||
				log("Removing temp directory.\n");
 | 
			
		||||
				remove_directory(tempdir_name);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			active_design->selection().selected_modules.clear();
 | 
			
		||||
 | 
			
		||||
			log_pop();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		active_design->selection_stack.pop_back();
 | 
			
		||||
	}
 | 
			
		||||
} Abc9Pass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
| 
						 | 
				
			
			@ -76,58 +76,6 @@ inline std::string remap_name(RTLIL::IdString abc9_name)
 | 
			
		|||
	return stringf("$abc$%d$%s", map_autoidx, abc9_name.c_str()+1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void handle_loops(RTLIL::Design *design)
 | 
			
		||||
{
 | 
			
		||||
	Pass::call(design, "scc -set_attr abc9_scc_id {}");
 | 
			
		||||
 | 
			
		||||
	// For every unique SCC found, (arbitrarily) find the first
 | 
			
		||||
	// cell in the component, and select (and mark) all its output
 | 
			
		||||
	// wires
 | 
			
		||||
	pool<RTLIL::Const> ids_seen;
 | 
			
		||||
	for (auto cell : module->cells()) {
 | 
			
		||||
		auto it = cell->attributes.find(ID(abc9_scc_id));
 | 
			
		||||
		if (it != cell->attributes.end()) {
 | 
			
		||||
			auto r = ids_seen.insert(it->second);
 | 
			
		||||
			if (r.second) {
 | 
			
		||||
				for (auto &c : cell->connections_) {
 | 
			
		||||
					if (c.second.is_fully_const()) continue;
 | 
			
		||||
					if (cell->output(c.first)) {
 | 
			
		||||
						SigBit b = c.second.as_bit();
 | 
			
		||||
						Wire *w = b.wire;
 | 
			
		||||
						if (w->port_input) {
 | 
			
		||||
							// In this case, hopefully the loop break has been already created
 | 
			
		||||
							// Get the non-prefixed wire
 | 
			
		||||
							Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
 | 
			
		||||
							log_assert(wo != nullptr);
 | 
			
		||||
							log_assert(wo->port_output);
 | 
			
		||||
							log_assert(b.offset < GetSize(wo));
 | 
			
		||||
							c.second = RTLIL::SigBit(wo, b.offset);
 | 
			
		||||
						}
 | 
			
		||||
						else {
 | 
			
		||||
							// Create a new output/input loop break
 | 
			
		||||
							w->port_input = true;
 | 
			
		||||
							w = module->wire(stringf("%s.abco", w->name.c_str()));
 | 
			
		||||
							if (!w) {
 | 
			
		||||
								w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
 | 
			
		||||
								w->port_output = true;
 | 
			
		||||
							}
 | 
			
		||||
							else {
 | 
			
		||||
								log_assert(w->port_input);
 | 
			
		||||
								log_assert(b.offset < GetSize(w));
 | 
			
		||||
							}
 | 
			
		||||
							w->set_bool_attribute(ID(abc9_scc_break));
 | 
			
		||||
							c.second = RTLIL::SigBit(w, b.offset);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			cell->attributes.erase(it);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	module->fixup_ports();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string add_echos_to_abc9_cmd(std::string str)
 | 
			
		||||
{
 | 
			
		||||
	std::string new_str, token;
 | 
			
		||||
| 
						 | 
				
			
			@ -254,10 +202,10 @@ struct abc9_output_filter
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
 | 
			
		||||
		bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
 | 
			
		||||
		/*bool cleanup,*/ vector<int> lut_costs, bool dff_mode, std::string clk_str,
 | 
			
		||||
		bool /*keepff*/, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode,
 | 
			
		||||
		bool show_tempdir, std::string box_file, std::string lut_file,
 | 
			
		||||
		std::string wire_delay, const dict<int,IdString> &box_lookup, bool nomfs
 | 
			
		||||
		std::string wire_delay, const dict<int,IdString> &box_lookup, bool nomfs, std::string tempdir_name
 | 
			
		||||
)
 | 
			
		||||
{
 | 
			
		||||
	module = current_module;
 | 
			
		||||
| 
						 | 
				
			
			@ -296,10 +244,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
	if (dff_mode && clk_sig.empty())
 | 
			
		||||
		log_cmd_error("Clock domain %s not found.\n", clk_str.c_str());
 | 
			
		||||
 | 
			
		||||
	std::string tempdir_name = "/tmp/yosys-abc-XXXXXX";
 | 
			
		||||
	if (!cleanup)
 | 
			
		||||
		tempdir_name[0] = tempdir_name[4] = '_';
 | 
			
		||||
	tempdir_name = make_temp_dir(tempdir_name);
 | 
			
		||||
	log_header(design, "Extracting gate netlist of module `%s' to `%s/input.xaig'..\n",
 | 
			
		||||
			module->name.c_str(), replace_tempdir(tempdir_name, tempdir_name, show_tempdir).c_str());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -383,33 +327,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool count_output = false;
 | 
			
		||||
	for (auto port_name : module->ports) {
 | 
			
		||||
		RTLIL::Wire *port_wire = module->wire(port_name);
 | 
			
		||||
		log_assert(port_wire);
 | 
			
		||||
		if (port_wire->port_output) {
 | 
			
		||||
			count_output = true;
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	log_push();
 | 
			
		||||
 | 
			
		||||
	if (count_output)
 | 
			
		||||
	//if (count_output)
 | 
			
		||||
	{
 | 
			
		||||
		design->selection_stack.emplace_back(false);
 | 
			
		||||
		RTLIL::Selection& sel = design->selection_stack.back();
 | 
			
		||||
		sel.select(module);
 | 
			
		||||
 | 
			
		||||
		handle_loops(design);
 | 
			
		||||
 | 
			
		||||
		Pass::call(design, "aigmap");
 | 
			
		||||
 | 
			
		||||
		//log("Extracted %d gates and %d wires to a netlist network with %d inputs and %d outputs.\n",
 | 
			
		||||
		//		count_gates, GetSize(signal_list), count_input, count_output);
 | 
			
		||||
 | 
			
		||||
		Pass::call(design, stringf("write_xaiger -map %s/input.sym %s/input.xaig", tempdir_name.c_str(), tempdir_name.c_str()));
 | 
			
		||||
 | 
			
		||||
		std::string buffer;
 | 
			
		||||
		std::ifstream ifs;
 | 
			
		||||
#if 0
 | 
			
		||||
| 
						 | 
				
			
			@ -428,8 +349,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		design->remove(design->module(ID($__abc9__)));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		design->selection_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing ABC9_MAP.\n");
 | 
			
		||||
 | 
			
		||||
		if (!lut_costs.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -773,41 +692,16 @@ clone_lut:
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Now 'unexpose' those wires by undoing
 | 
			
		||||
		// the expose operation -- remove them from PO/PI
 | 
			
		||||
		// and re-connecting them back together
 | 
			
		||||
		for (auto wire : module->wires()) {
 | 
			
		||||
			auto it = wire->attributes.find(ID(abc9_scc_break));
 | 
			
		||||
			if (it != wire->attributes.end()) {
 | 
			
		||||
				wire->attributes.erase(it);
 | 
			
		||||
				log_assert(wire->port_output);
 | 
			
		||||
				wire->port_output = false;
 | 
			
		||||
				std::string name = wire->name.str();
 | 
			
		||||
				RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
 | 
			
		||||
				log_assert(i_wire);
 | 
			
		||||
				log_assert(i_wire->port_input);
 | 
			
		||||
				i_wire->port_input = false;
 | 
			
		||||
				module->connect(i_wire, wire);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		module->fixup_ports();
 | 
			
		||||
 | 
			
		||||
		//log("ABC RESULTS:        internal signals: %8d\n", int(signal_list.size()) - in_wires - out_wires);
 | 
			
		||||
		log("ABC RESULTS:           input signals: %8d\n", in_wires);
 | 
			
		||||
		log("ABC RESULTS:          output signals: %8d\n", out_wires);
 | 
			
		||||
 | 
			
		||||
		design->remove(mapped_mod);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		log("Don't call ABC as there is nothing to map.\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cleanup)
 | 
			
		||||
	{
 | 
			
		||||
		log("Removing temp directory.\n");
 | 
			
		||||
		remove_directory(tempdir_name);
 | 
			
		||||
	}
 | 
			
		||||
	//else
 | 
			
		||||
	//{
 | 
			
		||||
	//	log("Don't call ABC as there is nothing to map.\n");
 | 
			
		||||
	//}
 | 
			
		||||
 | 
			
		||||
	log_pop();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -894,10 +788,10 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
//		log("        set the \"keep\" attribute on flip-flop output wires. (and thus preserve\n");
 | 
			
		||||
//		log("        them, for example for equivalence checking.)\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
		log("    -nocleanup\n");
 | 
			
		||||
		log("        when this option is used, the temporary files created by this pass\n");
 | 
			
		||||
		log("        are not removed. this is useful for debugging.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
//		log("    -nocleanup\n");
 | 
			
		||||
//		log("        when this option is used, the temporary files created by this pass\n");
 | 
			
		||||
//		log("        are not removed. this is useful for debugging.\n");
 | 
			
		||||
//		log("\n");
 | 
			
		||||
		log("    -showtmp\n");
 | 
			
		||||
		log("        print the temp dir name in log. usually this is suppressed so that the\n");
 | 
			
		||||
		log("        command output is identical across runs.\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -910,6 +804,9 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
		log("    -box <file>\n");
 | 
			
		||||
		log("        pass this file with box library to ABC. Use with -lut.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -tempdir <dir>\n");
 | 
			
		||||
		log("        use this as the temp dir.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("Note that this is a logic optimization pass within Yosys that is calling ABC\n");
 | 
			
		||||
		log("internally. This is not going to \"run ABC on your design\". It will instead run\n");
 | 
			
		||||
		log("ABC on logic snippets extracted from your design. You will not get any useful\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -922,7 +819,7 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n");
 | 
			
		||||
		log_header(design, "Executing ABC9_MAP pass (technology mapping using ABC9).\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
		assign_map.clear();
 | 
			
		||||
| 
						 | 
				
			
			@ -934,7 +831,8 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
#endif
 | 
			
		||||
		std::string script_file, clk_str, box_file, lut_file;
 | 
			
		||||
		std::string delay_target, lutin_shared = "-S 1", wire_delay;
 | 
			
		||||
		bool fast_mode = false, dff_mode = false, keepff = false, cleanup = true;
 | 
			
		||||
		std::string tempdir_name;
 | 
			
		||||
		bool fast_mode = false, dff_mode = false, keepff = false /*, cleanup = true*/;
 | 
			
		||||
		bool show_tempdir = false;
 | 
			
		||||
		bool nomfs = false;
 | 
			
		||||
		vector<int> lut_costs;
 | 
			
		||||
| 
						 | 
				
			
			@ -1038,10 +936,10 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
			//	keepff = true;
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			if (arg == "-nocleanup") {
 | 
			
		||||
				cleanup = false;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			//if (arg == "-nocleanup") {
 | 
			
		||||
			//	cleanup = false;
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			if (arg == "-showtmp") {
 | 
			
		||||
				show_tempdir = true;
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -1062,17 +960,24 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
				nomfs = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-tempdir" && argidx+1 < args.size()) {
 | 
			
		||||
				tempdir_name = args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		// ABC expects a box file for XAIG
 | 
			
		||||
		if (box_file.empty())
 | 
			
		||||
		    box_file = "+/dummy.box";
 | 
			
		||||
			box_file = "+/dummy.box";
 | 
			
		||||
 | 
			
		||||
		rewrite_filename(box_file);
 | 
			
		||||
		if (!box_file.empty() && !is_absolute_path(box_file) && box_file[0] != '+')
 | 
			
		||||
		    box_file = std::string(pwd) + "/" + box_file;
 | 
			
		||||
			box_file = std::string(pwd) + "/" + box_file;
 | 
			
		||||
 | 
			
		||||
		if (tempdir_name.empty())
 | 
			
		||||
			log_cmd_error("abc9_map '-tempdir' option is mandatory.\n");
 | 
			
		||||
 | 
			
		||||
		dict<int,IdString> box_lookup;
 | 
			
		||||
		for (auto m : design->modules()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1148,9 +1053,9 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
			assign_map.set(mod);
 | 
			
		||||
 | 
			
		||||
			if (!dff_mode || !clk_str.empty()) {
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, /*cleanup,*/ lut_costs, dff_mode, clk_str, keepff,
 | 
			
		||||
						delay_target, lutin_shared, fast_mode, show_tempdir,
 | 
			
		||||
						box_file, lut_file, wire_delay, box_lookup, nomfs);
 | 
			
		||||
						box_file, lut_file, wire_delay, box_lookup, nomfs, tempdir_name);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1294,9 +1199,9 @@ struct Abc9TechmapPass : public Pass {
 | 
			
		|||
				clk_sig = assign_map(std::get<1>(it.first));
 | 
			
		||||
				en_polarity = std::get<2>(it.first);
 | 
			
		||||
				en_sig = assign_map(std::get<3>(it.first));
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, /*cleanup,*/ lut_costs, !clk_sig.empty(), "$",
 | 
			
		||||
						keepff, delay_target, lutin_shared, fast_mode, show_tempdir,
 | 
			
		||||
						box_file, lut_file, wire_delay, box_lookup, nomfs);
 | 
			
		||||
						box_file, lut_file, wire_delay, box_lookup, nomfs, tempdir_name);
 | 
			
		||||
				assign_map.set(mod);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
							
								
								
									
										139
									
								
								passes/techmap/abc9_ops.cc
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								passes/techmap/abc9_ops.cc
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *                2019  Eddie Hung <eddie@fpgeh.com>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  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"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
void break_scc(RTLIL::Module *module)
 | 
			
		||||
{
 | 
			
		||||
	// For every unique SCC found, (arbitrarily) find the first
 | 
			
		||||
	//   cell in the component, and convert all wires driven by
 | 
			
		||||
	//   its output ports into a new PO, and drive its previous
 | 
			
		||||
	//   sinks with a new PI
 | 
			
		||||
	pool<RTLIL::Const> ids_seen;
 | 
			
		||||
	for (auto cell : module->selected_cells()) {
 | 
			
		||||
		auto it = cell->attributes.find(ID(abc9_scc_id));
 | 
			
		||||
		if (it == cell->attributes.end())
 | 
			
		||||
			continue;
 | 
			
		||||
		auto r = ids_seen.insert(it->second);
 | 
			
		||||
		cell->attributes.erase(it);
 | 
			
		||||
		if (!r.second)
 | 
			
		||||
			continue;
 | 
			
		||||
		for (auto &c : cell->connections_) {
 | 
			
		||||
			if (c.second.is_fully_const()) continue;
 | 
			
		||||
			if (cell->output(c.first)) {
 | 
			
		||||
				SigBit b = c.second.as_bit();
 | 
			
		||||
				Wire *w = b.wire;
 | 
			
		||||
				if (w->port_input) {
 | 
			
		||||
					// In this case, hopefully the loop break has been already created
 | 
			
		||||
					// Get the non-prefixed wire
 | 
			
		||||
					Wire *wo = module->wire(stringf("%s.abco", b.wire->name.c_str()));
 | 
			
		||||
					log_assert(wo != nullptr);
 | 
			
		||||
					log_assert(wo->port_output);
 | 
			
		||||
					log_assert(b.offset < GetSize(wo));
 | 
			
		||||
					c.second = RTLIL::SigBit(wo, b.offset);
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					// Create a new output/input loop break
 | 
			
		||||
					w->port_input = true;
 | 
			
		||||
					w = module->wire(stringf("%s.abco", w->name.c_str()));
 | 
			
		||||
					if (!w) {
 | 
			
		||||
						w = module->addWire(stringf("%s.abco", b.wire->name.c_str()), GetSize(b.wire));
 | 
			
		||||
						w->port_output = true;
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						log_assert(w->port_input);
 | 
			
		||||
						log_assert(b.offset < GetSize(w));
 | 
			
		||||
					}
 | 
			
		||||
					w->set_bool_attribute(ID(abc9_scc_break));
 | 
			
		||||
					c.second = RTLIL::SigBit(w, b.offset);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	module->fixup_ports();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void unbreak_scc(RTLIL::Module *module) {
 | 
			
		||||
	// Now 'unexpose' those wires by undoing
 | 
			
		||||
	// the expose operation -- remove them from PO/PI
 | 
			
		||||
	// and re-connecting them back together
 | 
			
		||||
	for (auto wire : module->wires()) {
 | 
			
		||||
		auto it = wire->attributes.find(ID(abc9_scc_break));
 | 
			
		||||
		if (it != wire->attributes.end()) {
 | 
			
		||||
			wire->attributes.erase(it);
 | 
			
		||||
			log_assert(wire->port_output);
 | 
			
		||||
			wire->port_output = false;
 | 
			
		||||
			std::string name = wire->name.str();
 | 
			
		||||
			RTLIL::Wire *i_wire = module->wire(name.substr(0, GetSize(name) - 5));
 | 
			
		||||
			log_assert(i_wire);
 | 
			
		||||
			log_assert(i_wire->port_input);
 | 
			
		||||
			i_wire->port_input = false;
 | 
			
		||||
			module->connect(i_wire, wire);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	module->fixup_ports();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct Abc9PrepPass : public Pass {
 | 
			
		||||
	Abc9PrepPass() : Pass("abc9_ops", "helper functions for ABC9") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    abc9_ops [options] [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing ABC9_OPS pass (helper functions for ABC9).\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
		bool break_scc_mode = false;
 | 
			
		||||
		bool unbreak_scc_mode = false;
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++) {
 | 
			
		||||
			std::string arg = args[argidx];
 | 
			
		||||
			if (arg == "-break_scc") {
 | 
			
		||||
				break_scc_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-unbreak_scc") {
 | 
			
		||||
				unbreak_scc_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		for (auto mod : design->selected_modules()) {
 | 
			
		||||
			if (break_scc_mode)
 | 
			
		||||
				break_scc(mod);
 | 
			
		||||
			if (unbreak_scc_mode)
 | 
			
		||||
				unbreak_scc(mod);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} Abc9PrepPass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue