mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 13:29:12 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/master' into xc7dsp
This commit is contained in:
		
						commit
						0157043b97
					
				
					 29 changed files with 405 additions and 228 deletions
				
			
		| 
						 | 
				
			
			@ -78,7 +78,7 @@ Similarily, on Mac OS X MacPorts or Homebrew can be used to install dependencies
 | 
			
		|||
On FreeBSD use the following command to install all prerequisites:
 | 
			
		||||
 | 
			
		||||
	# pkg install bison flex readline gawk libffi\
 | 
			
		||||
		git graphviz pkgconfig python3 python36 tcl-wrapper boost-libs
 | 
			
		||||
		git graphviz pkgconf python3 python36 tcl-wrapper boost-libs
 | 
			
		||||
 | 
			
		||||
On FreeBSD system use gmake instead of make. To run tests use:
 | 
			
		||||
    % MAKE=gmake CC=cc gmake test
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,7 +43,11 @@ if os.name == "posix":
 | 
			
		|||
        if current_rlimit_stack[1] != resource.RLIM_INFINITY:
 | 
			
		||||
            smtio_stacksize = min(smtio_stacksize, current_rlimit_stack[1])
 | 
			
		||||
        if current_rlimit_stack[0] < smtio_stacksize:
 | 
			
		||||
            try:
 | 
			
		||||
                resource.setrlimit(resource.RLIMIT_STACK, (smtio_stacksize, current_rlimit_stack[1]))
 | 
			
		||||
            except ValueError:
 | 
			
		||||
                # couldn't get more stack, just run with what we have
 | 
			
		||||
                pass
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# currently running solvers (so we can kill them)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -189,7 +189,8 @@ void dump_const(std::ostream &f, const RTLIL::Const &data, int width = -1, int o
 | 
			
		|||
	if (width < 0)
 | 
			
		||||
		width = data.bits.size() - offset;
 | 
			
		||||
	if (width == 0) {
 | 
			
		||||
		f << "\"\"";
 | 
			
		||||
		// See IEEE 1364-2005 Clause 5.1.14.
 | 
			
		||||
		f << "{0{1'b0}}";
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	if (nostr)
 | 
			
		||||
| 
						 | 
				
			
			@ -788,7 +789,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cell->type == "$pmux" || cell->type == "$pmux_safe")
 | 
			
		||||
	if (cell->type == "$pmux")
 | 
			
		||||
	{
 | 
			
		||||
		int width = cell->parameters["\\WIDTH"].as_int();
 | 
			
		||||
		int s_width = cell->getPort("\\S").size();
 | 
			
		||||
| 
						 | 
				
			
			@ -800,10 +801,9 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
		f << stringf("%s" "  input [%d:0] s;\n", indent.c_str(), s_width-1);
 | 
			
		||||
 | 
			
		||||
		dump_attributes(f, indent + "  ", cell->attributes);
 | 
			
		||||
		if (cell->type != "$pmux_safe" && !noattr)
 | 
			
		||||
		if (!noattr)
 | 
			
		||||
			f << stringf("%s" "  (* parallel_case *)\n", indent.c_str());
 | 
			
		||||
		f << stringf("%s" "  casez (s)", indent.c_str());
 | 
			
		||||
		if (cell->type != "$pmux_safe")
 | 
			
		||||
		f << stringf(noattr ? " // synopsys parallel_case\n" : "\n");
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < s_width; i++)
 | 
			
		||||
| 
						 | 
				
			
			@ -811,7 +811,7 @@ bool dump_cell_expr(std::ostream &f, std::string indent, RTLIL::Cell *cell)
 | 
			
		|||
			f << stringf("%s" "    %d'b", indent.c_str(), s_width);
 | 
			
		||||
 | 
			
		||||
			for (int j = s_width-1; j >= 0; j--)
 | 
			
		||||
				f << stringf("%c", j == i ? '1' : cell->type == "$pmux_safe" ? '0' : '?');
 | 
			
		||||
				f << stringf("%c", j == i ? '1' : '?');
 | 
			
		||||
 | 
			
		||||
			f << stringf(":\n");
 | 
			
		||||
			f << stringf("%s" "      %s = b[%d:%d];\n", indent.c_str(), func_name.c_str(), (i+1)*width-1, i*width);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -551,7 +551,7 @@ struct LibertyFrontend : public Frontend {
 | 
			
		|||
			if (design->has(cell_name)) {
 | 
			
		||||
				Module *existing_mod = design->module(cell_name);
 | 
			
		||||
				if (!flag_nooverwrite && !flag_overwrite && !existing_mod->get_bool_attribute("\\blackbox")) {
 | 
			
		||||
					log_error("Re-definition of of cell/module %s!\n", log_id(cell_name));
 | 
			
		||||
					log_error("Re-definition of cell/module %s!\n", log_id(cell_name));
 | 
			
		||||
				} else if (flag_nooverwrite) {
 | 
			
		||||
					log("Ignoring re-definition of module %s.\n", log_id(cell_name));
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ int log_force_debug = 0;
 | 
			
		|||
int log_debug_suppressed = 0;
 | 
			
		||||
 | 
			
		||||
vector<int> header_count;
 | 
			
		||||
pool<RTLIL::IdString> log_id_cache;
 | 
			
		||||
vector<char*> log_id_cache;
 | 
			
		||||
vector<shared_str> string_buf;
 | 
			
		||||
int string_buf_index = -1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +69,13 @@ static struct timeval initial_tv = { 0, 0 };
 | 
			
		|||
static bool next_print_log = false;
 | 
			
		||||
static int log_newline_count = 0;
 | 
			
		||||
 | 
			
		||||
static void log_id_cache_clear()
 | 
			
		||||
{
 | 
			
		||||
	for (auto p : log_id_cache)
 | 
			
		||||
		free(p);
 | 
			
		||||
	log_id_cache.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(_WIN32) && !defined(__MINGW32__)
 | 
			
		||||
// this will get time information and return it in timeval, simulating gettimeofday()
 | 
			
		||||
int gettimeofday(struct timeval *tv, struct timezone *tz)
 | 
			
		||||
| 
						 | 
				
			
			@ -414,7 +421,7 @@ void log_push()
 | 
			
		|||
void log_pop()
 | 
			
		||||
{
 | 
			
		||||
	header_count.pop_back();
 | 
			
		||||
	log_id_cache.clear();
 | 
			
		||||
	log_id_cache_clear();
 | 
			
		||||
	string_buf.clear();
 | 
			
		||||
	string_buf_index = -1;
 | 
			
		||||
	log_flush();
 | 
			
		||||
| 
						 | 
				
			
			@ -521,7 +528,7 @@ void log_reset_stack()
 | 
			
		|||
{
 | 
			
		||||
	while (header_count.size() > 1)
 | 
			
		||||
		header_count.pop_back();
 | 
			
		||||
	log_id_cache.clear();
 | 
			
		||||
	log_id_cache_clear();
 | 
			
		||||
	string_buf.clear();
 | 
			
		||||
	string_buf_index = -1;
 | 
			
		||||
	log_flush();
 | 
			
		||||
| 
						 | 
				
			
			@ -580,8 +587,8 @@ const char *log_const(const RTLIL::Const &value, bool autoint)
 | 
			
		|||
 | 
			
		||||
const char *log_id(RTLIL::IdString str)
 | 
			
		||||
{
 | 
			
		||||
	log_id_cache.insert(str);
 | 
			
		||||
	const char *p = str.c_str();
 | 
			
		||||
	log_id_cache.push_back(strdup(str.c_str()));
 | 
			
		||||
	const char *p = log_id_cache.back();
 | 
			
		||||
	if (p[0] != '\\')
 | 
			
		||||
		return p;
 | 
			
		||||
	if (p[1] == '$' || p[1] == '\\' || p[1] == 0)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,10 @@ struct rules_t
 | 
			
		|||
			if (groups != GetSize(transp)) log_error("Bram %s variant %d has %d groups but only %d entries in 'transp'.\n", log_id(name), variant, groups, GetSize(transp));
 | 
			
		||||
			if (groups != GetSize(clocks)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clocks'.\n", log_id(name), variant, groups, GetSize(clocks));
 | 
			
		||||
			if (groups != GetSize(clkpol)) log_error("Bram %s variant %d has %d groups but only %d entries in 'clkpol'.\n", log_id(name), variant, groups, GetSize(clkpol));
 | 
			
		||||
 | 
			
		||||
			int group = 0;
 | 
			
		||||
			for (auto e : enable)
 | 
			
		||||
				if (e > dbits) log_error("Bram %s variant %d group %d has %d enable bits but only %d dbits.\n", log_id(name), variant, group, e, dbits);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		vector<portinfo_t> make_portinfos() const
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ struct OptLutWorker
 | 
			
		|||
				SigSpec lut_input = cell->getPort("\\A");
 | 
			
		||||
				int lut_arity = 0;
 | 
			
		||||
 | 
			
		||||
				log("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
 | 
			
		||||
				log_debug("Found $lut\\WIDTH=%d cell %s.%s.\n", lut_width, log_id(module), log_id(cell));
 | 
			
		||||
				luts.insert(cell);
 | 
			
		||||
 | 
			
		||||
				// First, find all dedicated logic we're connected to. This results in an overapproximation
 | 
			
		||||
| 
						 | 
				
			
			@ -147,15 +147,15 @@ struct OptLutWorker
 | 
			
		|||
					{
 | 
			
		||||
						if (lut_width <= dlogic_conn.first)
 | 
			
		||||
						{
 | 
			
		||||
							log("  LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
							log("    LUT input A[%d] not present.\n", dlogic_conn.first);
 | 
			
		||||
							log_debug("  LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
							log_debug("    LUT input A[%d] not present.\n", dlogic_conn.first);
 | 
			
		||||
							legal = false;
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
						if (sigmap(lut_input[dlogic_conn.first]) != sigmap(lut_dlogic->getPort(dlogic_conn.second)))
 | 
			
		||||
						{
 | 
			
		||||
							log("  LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
							log("    LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
 | 
			
		||||
							log_debug("  LUT has illegal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
							log_debug("    LUT input A[%d] (wire %s) not connected to %s port %s (wire %s).\n", dlogic_conn.first, log_signal(lut_input[dlogic_conn.first]), lut_dlogic->type.c_str(), dlogic_conn.second.c_str(), log_signal(lut_dlogic->getPort(dlogic_conn.second)));
 | 
			
		||||
							legal = false;
 | 
			
		||||
							break;
 | 
			
		||||
						}
 | 
			
		||||
| 
						 | 
				
			
			@ -163,7 +163,7 @@ struct OptLutWorker
 | 
			
		|||
 | 
			
		||||
					if (legal)
 | 
			
		||||
					{
 | 
			
		||||
						log("  LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
						log_debug("  LUT has legal connection to %s cell %s.%s.\n", lut_dlogic->type.c_str(), log_id(module), log_id(lut_dlogic));
 | 
			
		||||
						lut_legal_dlogics.insert(lut_dlogic);
 | 
			
		||||
						for (auto &dlogic_conn : dlogic_map)
 | 
			
		||||
							lut_dlogic_inputs.insert(dlogic_conn.first);
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +179,7 @@ struct OptLutWorker
 | 
			
		|||
						lut_arity++;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				log("  Cell implements a %d-LUT.\n", lut_arity);
 | 
			
		||||
				log_debug("  Cell implements a %d-LUT.\n", lut_arity);
 | 
			
		||||
				luts_arity[cell] = lut_arity;
 | 
			
		||||
				luts_dlogics[cell] = lut_legal_dlogics;
 | 
			
		||||
				luts_dlogic_inputs[cell] = lut_dlogic_inputs;
 | 
			
		||||
| 
						 | 
				
			
			@ -239,28 +239,26 @@ struct OptLutWorker
 | 
			
		|||
 | 
			
		||||
			if (const0_match || const1_match || input_match != -1)
 | 
			
		||||
			{
 | 
			
		||||
				log("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
 | 
			
		||||
				log_debug("Found redundant cell %s.%s.\n", log_id(module), log_id(lut));
 | 
			
		||||
 | 
			
		||||
				SigBit value;
 | 
			
		||||
				if (const0_match)
 | 
			
		||||
				{
 | 
			
		||||
					log("  Cell evaluates constant 0.\n");
 | 
			
		||||
					log_debug("  Cell evaluates constant 0.\n");
 | 
			
		||||
					value = State::S0;
 | 
			
		||||
				}
 | 
			
		||||
				if (const1_match)
 | 
			
		||||
				{
 | 
			
		||||
					log("  Cell evaluates constant 1.\n");
 | 
			
		||||
					log_debug("  Cell evaluates constant 1.\n");
 | 
			
		||||
					value = State::S1;
 | 
			
		||||
				}
 | 
			
		||||
				if (input_match != -1) {
 | 
			
		||||
					log("  Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
 | 
			
		||||
					log_debug("  Cell evaluates signal %s.\n", log_signal(lut_inputs[input_match]));
 | 
			
		||||
					value = lut_inputs[input_match];
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (lut_dlogic_inputs.size())
 | 
			
		||||
				{
 | 
			
		||||
					log("  Not eliminating cell (connected to dedicated logic).\n");
 | 
			
		||||
				}
 | 
			
		||||
					log_debug("  Not eliminating cell (connected to dedicated logic).\n");
 | 
			
		||||
				else
 | 
			
		||||
				{
 | 
			
		||||
					SigSpec lut_output = lut->getPort("\\Y");
 | 
			
		||||
| 
						 | 
				
			
			@ -323,11 +321,11 @@ struct OptLutWorker
 | 
			
		|||
					int lutB_arity = luts_arity[lutB];
 | 
			
		||||
					pool<int> &lutB_dlogic_inputs = luts_dlogic_inputs[lutB];
 | 
			
		||||
 | 
			
		||||
					log("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
 | 
			
		||||
					log_debug("Found %s.%s (cell A) feeding %s.%s (cell B).\n", log_id(module), log_id(lutA), log_id(module), log_id(lutB));
 | 
			
		||||
 | 
			
		||||
					if (index.query_is_output(lutA->getPort("\\Y")))
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs (cascade connection feeds module output).\n");
 | 
			
		||||
						log_debug("  Not combining LUTs (cascade connection feeds module output).\n");
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -353,67 +351,51 @@ struct OptLutWorker
 | 
			
		|||
 | 
			
		||||
					int lutM_arity = lutA_arity + lutB_arity - 1 - common_inputs.size();
 | 
			
		||||
					if (lutA_dlogic_inputs.size())
 | 
			
		||||
						log("  Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
 | 
			
		||||
						log_debug("  Cell A is a %d-LUT with %zu dedicated connections. ", lutA_arity, lutA_dlogic_inputs.size());
 | 
			
		||||
					else
 | 
			
		||||
						log("  Cell A is a %d-LUT. ", lutA_arity);
 | 
			
		||||
						log_debug("  Cell A is a %d-LUT. ", lutA_arity);
 | 
			
		||||
					if (lutB_dlogic_inputs.size())
 | 
			
		||||
						log("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
 | 
			
		||||
						log_debug("Cell B is a %d-LUT with %zu dedicated connections.\n", lutB_arity, lutB_dlogic_inputs.size());
 | 
			
		||||
					else
 | 
			
		||||
						log("Cell B is a %d-LUT.\n", lutB_arity);
 | 
			
		||||
					log("  Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
 | 
			
		||||
						log_debug("Cell B is a %d-LUT.\n", lutB_arity);
 | 
			
		||||
					log_debug("  Cells share %zu input(s) and can be merged into one %d-LUT.\n", common_inputs.size(), lutM_arity);
 | 
			
		||||
 | 
			
		||||
					const int COMBINE_A = 1, COMBINE_B = 2, COMBINE_EITHER = COMBINE_A | COMBINE_B;
 | 
			
		||||
					int combine_mask = 0;
 | 
			
		||||
					if (lutM_arity > lutA_width)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell A (combined LUT wider than cell A).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell A (combined LUT wider than cell A).\n");
 | 
			
		||||
					else if (lutB_dlogic_inputs.size() > 0)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell A (cell B is connected to dedicated logic).\n");
 | 
			
		||||
					else if (lutB->get_bool_attribute("\\lut_keep"))
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell A (cell B has attribute \\lut_keep).\n");
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						combine_mask |= COMBINE_A;
 | 
			
		||||
					}
 | 
			
		||||
					if (lutM_arity > lutB_width)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell B (combined LUT wider than cell B).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell B (combined LUT wider than cell B).\n");
 | 
			
		||||
					else if (lutA_dlogic_inputs.size() > 0)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell B (cell A is connected to dedicated logic).\n");
 | 
			
		||||
					else if (lutA->get_bool_attribute("\\lut_keep"))
 | 
			
		||||
					{
 | 
			
		||||
						log("  Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
 | 
			
		||||
					}
 | 
			
		||||
						log_debug("  Not combining LUTs into cell B (cell A has attribute \\lut_keep).\n");
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						combine_mask |= COMBINE_B;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					int combine = combine_mask;
 | 
			
		||||
					if (combine == COMBINE_EITHER)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Can combine into either cell.\n");
 | 
			
		||||
						log_debug("  Can combine into either cell.\n");
 | 
			
		||||
						if (lutA_arity == 1)
 | 
			
		||||
						{
 | 
			
		||||
							log("    Cell A is a buffer or inverter, combining into cell B.\n");
 | 
			
		||||
							log_debug("    Cell A is a buffer or inverter, combining into cell B.\n");
 | 
			
		||||
							combine = COMBINE_B;
 | 
			
		||||
						}
 | 
			
		||||
						else if (lutB_arity == 1)
 | 
			
		||||
						{
 | 
			
		||||
							log("    Cell B is a buffer or inverter, combining into cell A.\n");
 | 
			
		||||
							log_debug("    Cell B is a buffer or inverter, combining into cell A.\n");
 | 
			
		||||
							combine = COMBINE_A;
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							log("    Arbitrarily combining into cell A.\n");
 | 
			
		||||
							log_debug("    Arbitrarily combining into cell A.\n");
 | 
			
		||||
							combine = COMBINE_A;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -423,7 +405,7 @@ struct OptLutWorker
 | 
			
		|||
					pool<int> lutM_dlogic_inputs;
 | 
			
		||||
					if (combine == COMBINE_A)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Combining LUTs into cell A.\n");
 | 
			
		||||
						log_debug("  Combining LUTs into cell A.\n");
 | 
			
		||||
						lutM = lutA;
 | 
			
		||||
						lutM_inputs = lutA_inputs;
 | 
			
		||||
						lutM_dlogic_inputs = lutA_dlogic_inputs;
 | 
			
		||||
| 
						 | 
				
			
			@ -432,7 +414,7 @@ struct OptLutWorker
 | 
			
		|||
					}
 | 
			
		||||
					else if (combine == COMBINE_B)
 | 
			
		||||
					{
 | 
			
		||||
						log("  Combining LUTs into cell B.\n");
 | 
			
		||||
						log_debug("  Combining LUTs into cell B.\n");
 | 
			
		||||
						lutM = lutB;
 | 
			
		||||
						lutM_inputs = lutB_inputs;
 | 
			
		||||
						lutM_dlogic_inputs = lutB_dlogic_inputs;
 | 
			
		||||
| 
						 | 
				
			
			@ -441,7 +423,7 @@ struct OptLutWorker
 | 
			
		|||
					}
 | 
			
		||||
					else
 | 
			
		||||
					{
 | 
			
		||||
						log("  Cannot combine LUTs.\n");
 | 
			
		||||
						log_debug("  Cannot combine LUTs.\n");
 | 
			
		||||
						continue;
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -466,17 +448,17 @@ struct OptLutWorker
 | 
			
		|||
						if (input_unused && lutR_unique.size())
 | 
			
		||||
						{
 | 
			
		||||
							SigBit new_input = lutR_unique.pop();
 | 
			
		||||
							log("    Connecting input %d as %s.\n", i, log_signal(new_input));
 | 
			
		||||
							log_debug("    Connecting input %d as %s.\n", i, log_signal(new_input));
 | 
			
		||||
							lutM_new_inputs.push_back(new_input);
 | 
			
		||||
						}
 | 
			
		||||
						else if (sigmap(lutM_input[i]) == lutA_output)
 | 
			
		||||
						{
 | 
			
		||||
							log("    Disconnecting cascade input %d.\n", i);
 | 
			
		||||
							log_debug("    Disconnecting cascade input %d.\n", i);
 | 
			
		||||
							lutM_new_inputs.push_back(SigBit());
 | 
			
		||||
						}
 | 
			
		||||
						else
 | 
			
		||||
						{
 | 
			
		||||
							log("    Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
 | 
			
		||||
							log_debug("    Leaving input %d as %s.\n", i, log_signal(lutM_input[i]));
 | 
			
		||||
							lutM_new_inputs.push_back(lutM_input[i]);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
| 
						 | 
				
			
			@ -494,9 +476,9 @@ struct OptLutWorker
 | 
			
		|||
						lutM_new_table[eval] = (RTLIL::State) evaluate_lut(lutB, eval_inputs);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					log("  Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log("  Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log("  Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
 | 
			
		||||
					log_debug("  Cell A truth table: %s.\n", lutA->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log_debug("  Cell B truth table: %s.\n", lutB->getParam("\\LUT").as_string().c_str());
 | 
			
		||||
					log_debug("  Merged truth table: %s.\n", lutM_new_table.as_string().c_str());
 | 
			
		||||
 | 
			
		||||
					lutM->setParam("\\LUT", lutM_new_table);
 | 
			
		||||
					lutM->setPort("\\A", lutM_new_inputs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1172,7 +1172,7 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			else
 | 
			
		||||
				cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
 | 
			
		||||
			if (c->type == "\\_const0_" || c->type == "\\_const1_") {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,12 +24,13 @@
 | 
			
		|||
 | 
			
		||||
#if 0
 | 
			
		||||
// Based on &flow3 - better QoR but more experimental
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &ps -l; "/*"&sweep -v;"*/" &scorr; " \
 | 
			
		||||
						"&st; &if {W}; &save; &st; &syn2; &if {W}; &save; &load; "\
 | 
			
		||||
						"&st; &if -g -K 6; &dch -f; &if {W}; &save; &load; "\
 | 
			
		||||
						"&st; &if -g -K 6; &synch2; &if {W}; &save; &load"
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &ps -l; &sweep -v; &scorr; " \
 | 
			
		||||
						"&st; &if {W}; &save; &st; &syn2; &if {W} -v; &save; &load; "\
 | 
			
		||||
						"&st; &if -g -K 6; &dch -f; &if {W} -v; &save; &load; "\
 | 
			
		||||
						"&st; &if -g -K 6; &synch2; &if {W} -v; &save; &load; "\
 | 
			
		||||
						"&mfs; &ps -l"
 | 
			
		||||
#else
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps -l; &if {W} {D} -v; &mfs; &ps -l"
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &scorr; &sweep; &dc2; &st; &dch -f; &ps; &if {W} {D} -v; &mfs; &ps -l"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +54,7 @@
 | 
			
		|||
#endif
 | 
			
		||||
 | 
			
		||||
#include "frontends/aiger/aigerparse.h"
 | 
			
		||||
#include "kernel/utils.h"
 | 
			
		||||
 | 
			
		||||
#ifdef YOSYS_LINK_ABC
 | 
			
		||||
extern "C" int Abc_RealMain(int argc, char *argv[]);
 | 
			
		||||
| 
						 | 
				
			
			@ -570,13 +572,23 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
				boxes.emplace_back(cell);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		dict<SigBit, pool<IdString>> bit_drivers, bit_users;
 | 
			
		||||
		TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
 | 
			
		||||
		dict<RTLIL::Cell*,RTLIL::Cell*> not2drivers;
 | 
			
		||||
		dict<SigBit, std::vector<RTLIL::Cell*>> bit2sinks;
 | 
			
		||||
 | 
			
		||||
		std::map<std::string, int> cell_stats;
 | 
			
		||||
		for (auto c : mapped_mod->cells())
 | 
			
		||||
		{
 | 
			
		||||
			toposort.node(c->name);
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell *cell = nullptr;
 | 
			
		||||
			if (c->type == "$_NOT_") {
 | 
			
		||||
				RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
 | 
			
		||||
				RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
 | 
			
		||||
				RTLIL::SigBit a_bit = c->getPort("\\A");
 | 
			
		||||
				RTLIL::SigBit y_bit = c->getPort("\\Y");
 | 
			
		||||
				bit_users[a_bit].insert(c->name);
 | 
			
		||||
				bit_drivers[y_bit].insert(c->name);
 | 
			
		||||
 | 
			
		||||
				if (!a_bit.wire) {
 | 
			
		||||
					c->setPort("\\Y", module->addWire(NEW_ID));
 | 
			
		||||
					RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
 | 
			
		||||
| 
						 | 
				
			
			@ -584,11 +596,11 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
					module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1);
 | 
			
		||||
				}
 | 
			
		||||
				else if (!lut_costs.empty() || !lut_file.empty()) {
 | 
			
		||||
					RTLIL::Cell* driving_lut = nullptr;
 | 
			
		||||
					RTLIL::Cell* driver_lut = nullptr;
 | 
			
		||||
					// ABC can return NOT gates that drive POs
 | 
			
		||||
					if (!a_bit.wire->port_input) {
 | 
			
		||||
						// If it's not a NOT gate that that comes from a PI directly,
 | 
			
		||||
						// find the driving LUT and clone that to guarantee that we won't
 | 
			
		||||
						// find the driver LUT and clone that to guarantee that we won't
 | 
			
		||||
						// increase the max logic depth
 | 
			
		||||
						// (TODO: Optimise by not cloning unless will increase depth)
 | 
			
		||||
						RTLIL::IdString driver_name;
 | 
			
		||||
| 
						 | 
				
			
			@ -596,38 +608,25 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
							driver_name = stringf("%s$lut", a_bit.wire->name.c_str());
 | 
			
		||||
						else
 | 
			
		||||
							driver_name = stringf("%s[%d]$lut", a_bit.wire->name.c_str(), a_bit.offset);
 | 
			
		||||
						driving_lut = mapped_mod->cell(driver_name);
 | 
			
		||||
						driver_lut = mapped_mod->cell(driver_name);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (!driving_lut) {
 | 
			
		||||
						// If a driver couldn't be found (could be from PI,
 | 
			
		||||
						// or from a box) then implement using a LUT
 | 
			
		||||
					if (!driver_lut) {
 | 
			
		||||
						// If a driver couldn't be found (could be from PI or box CI)
 | 
			
		||||
						// then implement using a LUT
 | 
			
		||||
						cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
 | 
			
		||||
								RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset),
 | 
			
		||||
								RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
 | 
			
		||||
								1);
 | 
			
		||||
								RTLIL::SigBit(module->wires_.at(remap_name(a_bit.wire->name)), a_bit.offset),
 | 
			
		||||
								RTLIL::SigBit(module->wires_.at(remap_name(y_bit.wire->name)), y_bit.offset),
 | 
			
		||||
								RTLIL::Const::from_string("01"));
 | 
			
		||||
						bit2sinks[cell->getPort("\\A")].push_back(cell);
 | 
			
		||||
						cell_stats["$lut"]++;
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						auto driver_a = driving_lut->getPort("\\A").chunks();
 | 
			
		||||
						for (auto &chunk : driver_a)
 | 
			
		||||
							chunk.wire = module->wires_[remap_name(chunk.wire->name)];
 | 
			
		||||
						RTLIL::Const driver_lut = driving_lut->getParam("\\LUT");
 | 
			
		||||
						for (auto &b : driver_lut.bits) {
 | 
			
		||||
							if (b == RTLIL::State::S0) b = RTLIL::State::S1;
 | 
			
		||||
							else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
 | 
			
		||||
						}
 | 
			
		||||
						cell = module->addLut(remap_name(stringf("%s$lut", c->name.c_str())),
 | 
			
		||||
								driver_a,
 | 
			
		||||
								RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset),
 | 
			
		||||
								driver_lut);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					cell = module->addCell(remap_name(c->name), "$_NOT_");
 | 
			
		||||
					cell->setPort("\\A", RTLIL::SigBit(module->wires_[remap_name(a_bit.wire->name)], a_bit.offset));
 | 
			
		||||
					cell->setPort("\\Y", RTLIL::SigBit(module->wires_[remap_name(y_bit.wire->name)], y_bit.offset));
 | 
			
		||||
					cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
					else
 | 
			
		||||
						not2drivers[c] = driver_lut;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					log_abort();
 | 
			
		||||
				if (cell && markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -635,11 +634,12 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
 | 
			
		||||
			RTLIL::Cell *existing_cell = nullptr;
 | 
			
		||||
			if (c->type == "$lut") {
 | 
			
		||||
				if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
 | 
			
		||||
					SigSpec my_a = module->wires_[remap_name(c->getPort("\\A").as_wire()->name)];
 | 
			
		||||
					SigSpec my_y = module->wires_[remap_name(c->getPort("\\Y").as_wire()->name)];
 | 
			
		||||
				if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT") == RTLIL::Const::from_string("01")) {
 | 
			
		||||
					SigSpec my_a = module->wires_.at(remap_name(c->getPort("\\A").as_wire()->name));
 | 
			
		||||
					SigSpec my_y = module->wires_.at(remap_name(c->getPort("\\Y").as_wire()->name));
 | 
			
		||||
					module->connect(my_y, my_a);
 | 
			
		||||
					if (markgroups) c->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					log_abort();
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				cell = module->addCell(remap_name(c->name), c->type);
 | 
			
		||||
| 
						 | 
				
			
			@ -666,10 +666,20 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
						continue;
 | 
			
		||||
					//log_assert(c.width == 1);
 | 
			
		||||
					if (c.wire)
 | 
			
		||||
						c.wire = module->wires_[remap_name(c.wire->name)];
 | 
			
		||||
						c.wire = module->wires_.at(remap_name(c.wire->name));
 | 
			
		||||
					newsig.append(c);
 | 
			
		||||
				}
 | 
			
		||||
				cell->setPort(conn.first, newsig);
 | 
			
		||||
 | 
			
		||||
				if (cell->input(conn.first)) {
 | 
			
		||||
					for (auto i : newsig)
 | 
			
		||||
						bit2sinks[i].push_back(cell);
 | 
			
		||||
					for (auto i : conn.second)
 | 
			
		||||
						bit_users[i].insert(c->name);
 | 
			
		||||
				}
 | 
			
		||||
				if (cell->output(conn.first))
 | 
			
		||||
					for (auto i : conn.second)
 | 
			
		||||
						bit_drivers[i].insert(c->name);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -681,14 +691,14 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			if (!conn.first.is_fully_const()) {
 | 
			
		||||
				auto chunks = conn.first.chunks();
 | 
			
		||||
				for (auto &c : chunks)
 | 
			
		||||
					c.wire = module->wires_[remap_name(c.wire->name)];
 | 
			
		||||
					c.wire = module->wires_.at(remap_name(c.wire->name));
 | 
			
		||||
				conn.first = std::move(chunks);
 | 
			
		||||
			}
 | 
			
		||||
			if (!conn.second.is_fully_const()) {
 | 
			
		||||
				auto chunks = conn.second.chunks();
 | 
			
		||||
				for (auto &c : chunks)
 | 
			
		||||
					if (c.wire)
 | 
			
		||||
						c.wire = module->wires_[remap_name(c.wire->name)];
 | 
			
		||||
						c.wire = module->wires_.at(remap_name(c.wire->name));
 | 
			
		||||
				conn.second = std::move(chunks);
 | 
			
		||||
			}
 | 
			
		||||
			module->connect(conn);
 | 
			
		||||
| 
						 | 
				
			
			@ -725,6 +735,79 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto &it : bit_users)
 | 
			
		||||
			if (bit_drivers.count(it.first))
 | 
			
		||||
				for (auto driver_cell : bit_drivers.at(it.first))
 | 
			
		||||
				for (auto user_cell : it.second)
 | 
			
		||||
					toposort.edge(driver_cell, user_cell);
 | 
			
		||||
		bool no_loops = toposort.sort();
 | 
			
		||||
		log_assert(no_loops);
 | 
			
		||||
 | 
			
		||||
		for (auto ii = toposort.sorted.rbegin(); ii != toposort.sorted.rend(); ii++) {
 | 
			
		||||
			RTLIL::Cell *not_cell = mapped_mod->cell(*ii);
 | 
			
		||||
			log_assert(not_cell);
 | 
			
		||||
			if (not_cell->type != "$_NOT_")
 | 
			
		||||
				continue;
 | 
			
		||||
			auto it = not2drivers.find(not_cell);
 | 
			
		||||
			if (it == not2drivers.end())
 | 
			
		||||
				continue;
 | 
			
		||||
			RTLIL::Cell *driver_lut = it->second;
 | 
			
		||||
			RTLIL::SigBit a_bit = not_cell->getPort("\\A");
 | 
			
		||||
			RTLIL::SigBit y_bit = not_cell->getPort("\\Y");
 | 
			
		||||
			RTLIL::Const driver_mask;
 | 
			
		||||
 | 
			
		||||
			a_bit.wire = module->wires_.at(remap_name(a_bit.wire->name));
 | 
			
		||||
			y_bit.wire = module->wires_.at(remap_name(y_bit.wire->name));
 | 
			
		||||
 | 
			
		||||
			auto jt = bit2sinks.find(a_bit);
 | 
			
		||||
			if (jt == bit2sinks.end())
 | 
			
		||||
				goto clone_lut;
 | 
			
		||||
 | 
			
		||||
			for (auto sink_cell : jt->second)
 | 
			
		||||
				if (sink_cell->type != "$lut")
 | 
			
		||||
					goto clone_lut;
 | 
			
		||||
 | 
			
		||||
			// Push downstream LUTs past inverter
 | 
			
		||||
			for (auto sink_cell : jt->second) {
 | 
			
		||||
				SigSpec A = sink_cell->getPort("\\A");
 | 
			
		||||
				RTLIL::Const mask = sink_cell->getParam("\\LUT");
 | 
			
		||||
				int index = 0;
 | 
			
		||||
				for (; index < GetSize(A); index++)
 | 
			
		||||
					if (A[index] == a_bit)
 | 
			
		||||
						break;
 | 
			
		||||
				log_assert(index < GetSize(A));
 | 
			
		||||
				int i = 0;
 | 
			
		||||
				while (i < GetSize(mask)) {
 | 
			
		||||
					for (int j = 0; j < (1 << index); j++)
 | 
			
		||||
						std::swap(mask[i+j], mask[i+j+(1 << index)]);
 | 
			
		||||
					i += 1 << (index+1);
 | 
			
		||||
				}
 | 
			
		||||
				A[index] = y_bit;
 | 
			
		||||
				sink_cell->setPort("\\A", A);
 | 
			
		||||
				sink_cell->setParam("\\LUT", mask);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Since we have rewritten all sinks (which we know
 | 
			
		||||
			// to be only LUTs) to be after the inverter, we can
 | 
			
		||||
			// go ahead and clone the LUT with the expectation
 | 
			
		||||
			// that the original driving LUT will become dangling
 | 
			
		||||
			// and get cleaned away
 | 
			
		||||
clone_lut:
 | 
			
		||||
			driver_mask = driver_lut->getParam("\\LUT");
 | 
			
		||||
			for (auto &b : driver_mask.bits) {
 | 
			
		||||
				if (b == RTLIL::State::S0) b = RTLIL::State::S1;
 | 
			
		||||
				else if (b == RTLIL::State::S1) b = RTLIL::State::S0;
 | 
			
		||||
			}
 | 
			
		||||
			auto cell = module->addLut(NEW_ID,
 | 
			
		||||
					driver_lut->getPort("\\A"),
 | 
			
		||||
					y_bit,
 | 
			
		||||
					driver_mask);
 | 
			
		||||
			for (auto &bit : cell->connections_.at("\\A")) {
 | 
			
		||||
				bit.wire = module->wires_.at(remap_name(bit.wire->name));
 | 
			
		||||
				bit2sinks[bit].push_back(cell);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -174,8 +174,10 @@ struct ExtractFaWorker
 | 
			
		|||
 | 
			
		||||
				SigSpec sig = root;
 | 
			
		||||
 | 
			
		||||
				if (!ce.eval(sig))
 | 
			
		||||
					log_abort();
 | 
			
		||||
				if (!ce.eval(sig)) {
 | 
			
		||||
					ce.pop();
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (sig == State::S1)
 | 
			
		||||
					func |= 1 << i;
 | 
			
		||||
| 
						 | 
				
			
			@ -214,8 +216,10 @@ struct ExtractFaWorker
 | 
			
		|||
 | 
			
		||||
				SigSpec sig = root;
 | 
			
		||||
 | 
			
		||||
				if (!ce.eval(sig))
 | 
			
		||||
					log_abort();
 | 
			
		||||
				if (!ce.eval(sig)) {
 | 
			
		||||
					ce.pop();
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (sig == State::S1)
 | 
			
		||||
					func |= 1 << i;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,7 +27,7 @@ parameter _TECHMAP_CONSTVAL_A_ = 0;
 | 
			
		|||
parameter _TECHMAP_CONSTMSK_B_ = 0;
 | 
			
		||||
parameter _TECHMAP_CONSTVAL_B_ = 0;
 | 
			
		||||
 | 
			
		||||
function automatic integer gen_lut;
 | 
			
		||||
function automatic [(1 << `LUT_WIDTH)-1:0] gen_lut;
 | 
			
		||||
	input integer width;
 | 
			
		||||
	input integer operation;
 | 
			
		||||
	input integer swap;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,8 +4,8 @@ OBJS += techlibs/ecp5/synth_ecp5.o techlibs/ecp5/ecp5_ffinit.o
 | 
			
		|||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_sim.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/cells_bb.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/drams_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/dram.txt))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutrams_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/lutram.txt))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/brams_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,10 +71,10 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
		log("        do not use flipflops with CE in output netlist\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -nobram\n");
 | 
			
		||||
		log("        do not use BRAM cells in output netlist\n");
 | 
			
		||||
		log("        do not use block RAM cells in output netlist\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -nodram\n");
 | 
			
		||||
		log("        do not use distributed RAM cells in output netlist\n");
 | 
			
		||||
		log("    -nolutram\n");
 | 
			
		||||
		log("        do not use LUT RAM cells in output netlist\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -nowidelut\n");
 | 
			
		||||
		log("        do not use PFU muxes to implement LUTs larger than LUT4s\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -99,7 +99,7 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	string top_opt, blif_file, edif_file, json_file;
 | 
			
		||||
	bool noccu2, nodffe, nobram, nodram, nowidelut, flatten, retime, abc2, abc9, dsp, vpr;
 | 
			
		||||
	bool noccu2, nodffe, nobram, nolutram, nowidelut, flatten, retime, abc2, abc9, dsp, vpr;
 | 
			
		||||
 | 
			
		||||
	void clear_flags() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +110,7 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
		noccu2 = false;
 | 
			
		||||
		nodffe = false;
 | 
			
		||||
		nobram = false;
 | 
			
		||||
		nodram = false;
 | 
			
		||||
		nolutram = false;
 | 
			
		||||
		nowidelut = false;
 | 
			
		||||
		flatten = true;
 | 
			
		||||
		retime = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -176,11 +176,11 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
				nobram = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-nodram") {
 | 
			
		||||
				nodram = true;
 | 
			
		||||
			if (args[argidx] == "-nolutram" || /*deprecated alias*/ args[argidx] == "-nodram") {
 | 
			
		||||
				nolutram = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-nowidelut" || args[argidx] == "-nomux") {
 | 
			
		||||
			if (args[argidx] == "-nowidelut" || /*deprecated alias*/ args[argidx] == "-nomux") {
 | 
			
		||||
				nowidelut = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -260,23 +260,27 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
			run("opt_clean");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!nobram && check_label("bram", "(skip if -nobram)"))
 | 
			
		||||
		if (!nobram && check_label("map_bram", "(skip if -nobram)"))
 | 
			
		||||
		{
 | 
			
		||||
			run("memory_bram -rules +/ecp5/bram.txt");
 | 
			
		||||
			run("techmap -map +/ecp5/brams_map.v");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!nodram && check_label("dram", "(skip if -nodram)"))
 | 
			
		||||
		if (!nolutram && check_label("map_lutram", "(skip if -nolutram)"))
 | 
			
		||||
		{
 | 
			
		||||
			run("memory_bram -rules +/ecp5/dram.txt");
 | 
			
		||||
			run("techmap -map +/ecp5/drams_map.v");
 | 
			
		||||
			run("memory_bram -rules +/ecp5/lutram.txt");
 | 
			
		||||
			run("techmap -map +/ecp5/lutrams_map.v");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("fine"))
 | 
			
		||||
		if (check_label("map_ffram"))
 | 
			
		||||
		{
 | 
			
		||||
			run("opt -fast -mux_undef -undriven -fine");
 | 
			
		||||
			run("memory_map");
 | 
			
		||||
			run("opt -undriven -fine");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("map_gates"))
 | 
			
		||||
		{
 | 
			
		||||
			if (noccu2)
 | 
			
		||||
				run("techmap");
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,15 +3,11 @@
 | 
			
		|||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
#     (with exceptions for carry in/out)
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 CI
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
# Inputs: A B CI
 | 
			
		||||
# Outputs: O CO
 | 
			
		||||
#   (NB: carry chain input/output must be last
 | 
			
		||||
#        input/output and have been moved there
 | 
			
		||||
#        overriding the alphabetical ordering)
 | 
			
		||||
SB_CARRY 1 1 3 1
 | 
			
		||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
			
		||||
400 379 316
 | 
			
		||||
259 231 126
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 2 1 4 1
 | 
			
		||||
449 400 379 316
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,15 +3,11 @@
 | 
			
		|||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
#     (with exceptions for carry in/out)
 | 
			
		||||
 | 
			
		||||
# Inputs: CI I0 I1
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
# Inputs: A B CI
 | 
			
		||||
# Outputs: O CO
 | 
			
		||||
#   (NB: carry chain input/output must be last
 | 
			
		||||
#        input/output and have been moved there
 | 
			
		||||
#        overriding the alphabetical ordering)
 | 
			
		||||
SB_CARRY 1 1 3 1
 | 
			
		||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
			
		||||
589 558 465
 | 
			
		||||
675 609 186 
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 2 1 4 1
 | 
			
		||||
661 589 558 465
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,15 +3,11 @@
 | 
			
		|||
# NB: Inputs/Outputs must be ordered alphabetically
 | 
			
		||||
#     (with exceptions for carry in/out)
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 CI
 | 
			
		||||
# Outputs: CO
 | 
			
		||||
# Inputs: A B CI
 | 
			
		||||
# Outputs: O CO
 | 
			
		||||
#   (NB: carry chain input/output must be last
 | 
			
		||||
#        input/output and have been moved there
 | 
			
		||||
#        overriding the alphabetical ordering)
 | 
			
		||||
SB_CARRY 1 1 3 1
 | 
			
		||||
$__ICE40_FULL_ADDER 1 1 3 2
 | 
			
		||||
1231 1205 874
 | 
			
		||||
675  609  278
 | 
			
		||||
 | 
			
		||||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 2 1 4 1
 | 
			
		||||
1285 1231 1205 874
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,15 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
 | 
			
		|||
 | 
			
		||||
	genvar i;
 | 
			
		||||
	generate for (i = 0; i < Y_WIDTH; i = i + 1) begin:slice
 | 
			
		||||
`ifdef _ABC
 | 
			
		||||
		\$__ICE40_FULL_ADDER carry (
 | 
			
		||||
			.A(AA[i]),
 | 
			
		||||
			.B(BB[i]),
 | 
			
		||||
			.CI(C[i]),
 | 
			
		||||
			.CO(CO[i]),
 | 
			
		||||
			.O(Y[i])
 | 
			
		||||
		);
 | 
			
		||||
`else
 | 
			
		||||
		SB_CARRY carry (
 | 
			
		||||
			.I0(AA[i]),
 | 
			
		||||
			.I1(BB[i]),
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +72,7 @@ module _80_ice40_alu (A, B, CI, BI, X, Y, CO);
 | 
			
		|||
			.I3(C[i]),
 | 
			
		||||
			.O(Y[i])
 | 
			
		||||
		);
 | 
			
		||||
`endif
 | 
			
		||||
	end endgenerate
 | 
			
		||||
 | 
			
		||||
	assign X = AA ^ BB;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,3 +61,27 @@ module \$lut (A, Y);
 | 
			
		|||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
`endif
 | 
			
		||||
 | 
			
		||||
`ifdef _ABC
 | 
			
		||||
module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
 | 
			
		||||
  SB_CARRY carry (
 | 
			
		||||
    .I0(A),
 | 
			
		||||
    .I1(B),
 | 
			
		||||
    .CI(CI),
 | 
			
		||||
    .CO(CO)
 | 
			
		||||
  );
 | 
			
		||||
  SB_LUT4 #(
 | 
			
		||||
    //         I0: 1010 1010 1010 1010
 | 
			
		||||
    //         I1: 1100 1100 1100 1100
 | 
			
		||||
    //         I2: 1111 0000 1111 0000
 | 
			
		||||
    //         I3: 1111 1111 0000 0000
 | 
			
		||||
    .LUT_INIT(16'b 0110_1001_1001_0110)
 | 
			
		||||
  ) adder (
 | 
			
		||||
    .I0(1'b0),
 | 
			
		||||
    .I1(A),
 | 
			
		||||
    .I2(B),
 | 
			
		||||
    .I3(CI),
 | 
			
		||||
    .O(O)
 | 
			
		||||
  );
 | 
			
		||||
endmodule
 | 
			
		||||
`endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ endmodule
 | 
			
		|||
 | 
			
		||||
// SiliconBlue Logic Cells
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 2, lib_whitebox *)
 | 
			
		||||
(* lib_whitebox *)
 | 
			
		||||
module SB_LUT4 (output O, input I0, I1, I2, I3);
 | 
			
		||||
	parameter [15:0] LUT_INIT = 0;
 | 
			
		||||
	wire [7:0] s3 = I3 ? LUT_INIT[15:8] : LUT_INIT[7:0];
 | 
			
		||||
| 
						 | 
				
			
			@ -136,11 +136,34 @@ module SB_LUT4 (output O, input I0, I1, I2, I3);
 | 
			
		|||
	assign O = I0 ? s1[1] : s1[0];
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
 | 
			
		||||
(* lib_whitebox *)
 | 
			
		||||
module SB_CARRY (output CO, input I0, I1, CI);
 | 
			
		||||
	assign CO = (I0 && I1) || ((I0 || I1) && CI);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 1, abc_carry="CI,CO", lib_whitebox *)
 | 
			
		||||
module \$__ICE40_FULL_ADDER (output CO, O, input A, B, CI);
 | 
			
		||||
	SB_CARRY carry (
 | 
			
		||||
		.I0(A),
 | 
			
		||||
		.I1(B),
 | 
			
		||||
		.CI(CI),
 | 
			
		||||
		.CO(CO)
 | 
			
		||||
	);
 | 
			
		||||
	SB_LUT4 #(
 | 
			
		||||
		//         I0: 1010 1010 1010 1010
 | 
			
		||||
		//         I1: 1100 1100 1100 1100
 | 
			
		||||
		//         I2: 1111 0000 1111 0000
 | 
			
		||||
		//         I3: 1111 1111 0000 0000
 | 
			
		||||
		.LUT_INIT(16'b 0110_1001_1001_0110)
 | 
			
		||||
	) adder (
 | 
			
		||||
		.I0(1'b0),
 | 
			
		||||
		.I1(A),
 | 
			
		||||
		.I2(B),
 | 
			
		||||
		.I3(CI),
 | 
			
		||||
		.O(O)
 | 
			
		||||
	);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
// Positive Edge SiliconBlue FF Cells
 | 
			
		||||
 | 
			
		||||
module SB_DFF (output `SB_DFF_REG, input C, D);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -83,6 +83,51 @@ static void run_ice40_opts(Module *module)
 | 
			
		|||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$__ICE40_FULL_ADDER")
 | 
			
		||||
		{
 | 
			
		||||
			SigSpec non_const_inputs, replacement_output;
 | 
			
		||||
			int count_zeros = 0, count_ones = 0;
 | 
			
		||||
 | 
			
		||||
			SigBit inbit[3] = {
 | 
			
		||||
				cell->getPort("\\A"),
 | 
			
		||||
				cell->getPort("\\B"),
 | 
			
		||||
				cell->getPort("\\CI")
 | 
			
		||||
			};
 | 
			
		||||
			for (int i = 0; i < 3; i++)
 | 
			
		||||
				if (inbit[i].wire == nullptr) {
 | 
			
		||||
					if (inbit[i] == State::S1)
 | 
			
		||||
						count_ones++;
 | 
			
		||||
					else
 | 
			
		||||
						count_zeros++;
 | 
			
		||||
				} else
 | 
			
		||||
					non_const_inputs.append(inbit[i]);
 | 
			
		||||
 | 
			
		||||
			if (count_zeros >= 2)
 | 
			
		||||
				replacement_output = State::S0;
 | 
			
		||||
			else if (count_ones >= 2)
 | 
			
		||||
				replacement_output = State::S1;
 | 
			
		||||
			else if (GetSize(non_const_inputs) == 1)
 | 
			
		||||
				replacement_output = non_const_inputs;
 | 
			
		||||
 | 
			
		||||
			if (GetSize(replacement_output)) {
 | 
			
		||||
				optimized_co.insert(sigmap(cell->getPort("\\CO")[0]));
 | 
			
		||||
				module->connect(cell->getPort("\\CO")[0], replacement_output);
 | 
			
		||||
				module->design->scratchpad_set_bool("opt.did_something", true);
 | 
			
		||||
				log("Optimized $__ICE40_FULL_ADDER cell back to logic (without SB_CARRY) %s.%s: CO=%s\n",
 | 
			
		||||
						log_id(module), log_id(cell), log_signal(replacement_output));
 | 
			
		||||
				cell->type = "$lut";
 | 
			
		||||
				cell->setPort("\\A", { RTLIL::S0, inbit[0], inbit[1], inbit[2] });
 | 
			
		||||
				cell->setPort("\\Y", cell->getPort("\\O"));
 | 
			
		||||
				cell->unsetPort("\\B");
 | 
			
		||||
				cell->unsetPort("\\CI");
 | 
			
		||||
				cell->unsetPort("\\CO");
 | 
			
		||||
				cell->unsetPort("\\O");
 | 
			
		||||
				cell->setParam("\\LUT", RTLIL::Const::from_string("0110100110010110"));
 | 
			
		||||
				cell->setParam("\\WIDTH", 4);
 | 
			
		||||
			}
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (auto cell : sb_lut_cells)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -56,10 +56,10 @@ static void run_ice40_unlut(Module *module)
 | 
			
		|||
			cell->unsetParam("\\LUT_INIT");
 | 
			
		||||
 | 
			
		||||
			cell->setPort("\\A", SigSpec({
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I3")),
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I2")),
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I0")),
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I1")),
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I0"))
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I2")),
 | 
			
		||||
				get_bit_or_zero(cell->getPort("\\I3"))
 | 
			
		||||
			}));
 | 
			
		||||
			cell->setPort("\\Y", cell->getPort("\\O")[0]);
 | 
			
		||||
			cell->unsetPort("\\I0");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -238,7 +238,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
	{
 | 
			
		||||
		if (check_label("begin"))
 | 
			
		||||
		{
 | 
			
		||||
			run("read_verilog -lib -D_ABC +/ice40/cells_sim.v");
 | 
			
		||||
			run("read_verilog -icells -lib -D_ABC +/ice40/cells_sim.v");
 | 
			
		||||
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
 | 
			
		||||
			run("proc");
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -275,14 +275,14 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
			run("opt_clean");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!nobram && check_label("bram", "(skip if -nobram)"))
 | 
			
		||||
		if (!nobram && check_label("map_bram", "(skip if -nobram)"))
 | 
			
		||||
		{
 | 
			
		||||
			run("memory_bram -rules +/ice40/brams.txt");
 | 
			
		||||
			run("techmap -map +/ice40/brams_map.v");
 | 
			
		||||
			run("ice40_braminit");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("map"))
 | 
			
		||||
		if (check_label("map_ffram"))
 | 
			
		||||
		{
 | 
			
		||||
			run("opt -fast -mux_undef -undriven -fine");
 | 
			
		||||
			run("memory_map");
 | 
			
		||||
| 
						 | 
				
			
			@ -294,7 +294,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
			if (nocarry)
 | 
			
		||||
				run("techmap");
 | 
			
		||||
			else
 | 
			
		||||
				run("techmap -map +/techmap.v -map +/ice40/arith_map.v");
 | 
			
		||||
				run("techmap -map +/techmap.v -map +/ice40/arith_map.v" + std::string(abc == "abc9" ? " -D _ABC" : ""));
 | 
			
		||||
			if (retime || help_mode)
 | 
			
		||||
				run(abc + " -dff", "(only if -retime)");
 | 
			
		||||
			run("ice40_opt");
 | 
			
		||||
| 
						 | 
				
			
			@ -338,13 +338,14 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
					else
 | 
			
		||||
						wire_delay = 250;
 | 
			
		||||
					run(abc + stringf(" -W %d -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", wire_delay, device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
 | 
			
		||||
					run("techmap -D NO_LUT -D _ABC -map +/ice40/cells_map.v");
 | 
			
		||||
				}
 | 
			
		||||
				else
 | 
			
		||||
					run(abc + " -dress -lut 4", "(skip if -noabc)");
 | 
			
		||||
			}
 | 
			
		||||
			run("clean");
 | 
			
		||||
			run("ice40_unlut");
 | 
			
		||||
			run("opt_lut -dlogic SB_CARRY:I0=1:I1=2:CI=3");
 | 
			
		||||
			run("opt_lut -dlogic SB_CARRY:I0=2:I1=1:CI=0");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("map_cells"))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,9 +38,9 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
		log("\n");
 | 
			
		||||
		log("    -family < max10 | a10gx | cyclone10 | cyclonev | cycloneiv | cycloneive>\n");
 | 
			
		||||
		log("        generate the synthesis netlist for the specified family.\n");
 | 
			
		||||
		log("        MAX10 is the default target if not family argument specified.\n");
 | 
			
		||||
		log("        MAX10 is the default target if no family argument specified.\n");
 | 
			
		||||
		log("        For Cyclone GX devices, use cycloneiv argument; For Cyclone E, use cycloneive.\n");
 | 
			
		||||
		log("        Cyclone V and Arria 10 GX devices are experimental, use it with a10gx argument.\n");
 | 
			
		||||
		log("        Cyclone V and Arria 10 GX devices are experimental.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -top <module>\n");
 | 
			
		||||
		log("        use the specified module as top module (default='top')\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -62,10 +62,10 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
		log("        synonymous to the end of the command list.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -noiopads\n");
 | 
			
		||||
		log("        do not use altsyncram cells in output netlist\n");
 | 
			
		||||
		log("        do not use IO pad cells in output netlist\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -nobram\n");
 | 
			
		||||
		log("        do not use altsyncram cells in output netlist\n");
 | 
			
		||||
		log("        do not use block RAM cells in output netlist\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -noflatten\n");
 | 
			
		||||
		log("        do not flatten design before synthesis\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -147,9 +147,13 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
 | 
			
		||||
		if (!design->full_selection())
 | 
			
		||||
			log_cmd_error("This command only operates on fully selected designs!\n");
 | 
			
		||||
		if (family_opt != "max10" && family_opt != "a10gx" && family_opt != "cyclonev" && family_opt != "cycloneiv" &&
 | 
			
		||||
		    family_opt != "cycloneive" && family_opt != "cyclone10")
 | 
			
		||||
			log_cmd_error("Invalid or not family specified: '%s'\n", family_opt.c_str());
 | 
			
		||||
		if (family_opt != "max10" &&
 | 
			
		||||
		    family_opt != "a10gx" &&
 | 
			
		||||
		    family_opt != "cyclonev" &&
 | 
			
		||||
		    family_opt != "cycloneiv" &&
 | 
			
		||||
		    family_opt != "cycloneive" &&
 | 
			
		||||
		    family_opt != "cyclone10")
 | 
			
		||||
			log_cmd_error("Invalid or no family specified: '%s'\n", family_opt.c_str());
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SYNTH_INTEL pass.\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
| 
						 | 
				
			
			@ -162,18 +166,9 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
	void script() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		if (check_label("begin")) {
 | 
			
		||||
			if (check_label("family") && family_opt == "max10")
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/max10/cells_sim.v");
 | 
			
		||||
			else if (check_label("family") && family_opt == "a10gx")
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/a10gx/cells_sim.v");
 | 
			
		||||
			else if (check_label("family") && family_opt == "cyclonev")
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/cyclonev/cells_sim.v");
 | 
			
		||||
			else if (check_label("family") && family_opt == "cyclone10")
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/cyclone10/cells_sim.v");
 | 
			
		||||
			else if (check_label("family") && family_opt == "cycloneiv")
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/cycloneiv/cells_sim.v");
 | 
			
		||||
			else
 | 
			
		||||
				run("read_verilog -sv -lib +/intel/cycloneive/cells_sim.v");
 | 
			
		||||
			if (check_label("family"))
 | 
			
		||||
				run(stringf("read_verilog -sv -lib +/intel/%s/cells_sim.v", family_opt.c_str()));
 | 
			
		||||
 | 
			
		||||
			// Misc and common cells
 | 
			
		||||
			run("read_verilog -sv -lib +/intel/common/m9k_bb.v");
 | 
			
		||||
			run("read_verilog -sv -lib +/intel/common/altpll_bb.v");
 | 
			
		||||
| 
						 | 
				
			
			@ -191,12 +186,12 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
			run("synth -run coarse");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!nobram && check_label("bram", "(skip if -nobram)")) {
 | 
			
		||||
		if (!nobram && check_label("map_bram", "(skip if -nobram)")) {
 | 
			
		||||
			run("memory_bram -rules +/intel/common/brams.txt");
 | 
			
		||||
			run("techmap -map +/intel/common/brams_map.v");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("fine")) {
 | 
			
		||||
		if (check_label("map_ffram")) {
 | 
			
		||||
			run("opt -fast -mux_undef -undriven -fine -full");
 | 
			
		||||
			run("memory_map");
 | 
			
		||||
			run("opt -undriven -fine");
 | 
			
		||||
| 
						 | 
				
			
			@ -222,18 +217,8 @@ struct SynthIntelPass : public ScriptPass {
 | 
			
		|||
		if (check_label("map_cells")) {
 | 
			
		||||
			if (!noiopads)
 | 
			
		||||
				run("iopadmap -bits -outpad $__outpad I:O -inpad $__inpad O:I", "(unless -noiopads)");
 | 
			
		||||
			if (family_opt == "max10")
 | 
			
		||||
				run("techmap -map +/intel/max10/cells_map.v");
 | 
			
		||||
			else if (family_opt == "a10gx")
 | 
			
		||||
				run("techmap -map +/intel/a10gx/cells_map.v");
 | 
			
		||||
			else if (family_opt == "cyclonev")
 | 
			
		||||
				run("techmap -map +/intel/cyclonev/cells_map.v");
 | 
			
		||||
			else if (family_opt == "cyclone10")
 | 
			
		||||
				run("techmap -map +/intel/cyclone10/cells_map.v");
 | 
			
		||||
			else if (family_opt == "cycloneiv")
 | 
			
		||||
				run("techmap -map +/intel/cycloneiv/cells_map.v");
 | 
			
		||||
			else
 | 
			
		||||
				run("techmap -map +/intel/cycloneive/cells_map.v");
 | 
			
		||||
                        run(stringf("techmap -map +/intel/%s/cells_map.v", family_opt.c_str()));
 | 
			
		||||
 | 
			
		||||
			run("dffinit -highlow -ff dffeas q power_up");
 | 
			
		||||
			run("clean -purge");
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										7
									
								
								tests/lut/check_map_lut6.ys
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								tests/lut/check_map_lut6.ys
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,7 @@
 | 
			
		|||
chparam -set LUT_WIDTH 6 top
 | 
			
		||||
simplemap
 | 
			
		||||
equiv_opt -assert techmap -D LUT_WIDTH=6 -map +/cmp2lut.v
 | 
			
		||||
design -load postopt
 | 
			
		||||
equiv_opt -assert techmap -D LUT_WIDTH=6 -map +/gate2lut.v
 | 
			
		||||
design -load postopt
 | 
			
		||||
select -assert-count 0 t:* t:$lut %d
 | 
			
		||||
| 
						 | 
				
			
			@ -1,29 +1,30 @@
 | 
			
		|||
module top(...);
 | 
			
		||||
	input [3:0] a;
 | 
			
		||||
	parameter LUT_WIDTH = 4; // Multiples of 2 only
 | 
			
		||||
	input [LUT_WIDTH-1:0] a;
 | 
			
		||||
 | 
			
		||||
	output o1_1 = 4'b1010 <= a;
 | 
			
		||||
	output o1_2 = 4'b1010 <  a;
 | 
			
		||||
	output o1_3 = 4'b1010 >= a;
 | 
			
		||||
	output o1_4 = 4'b1010 >  a;
 | 
			
		||||
	output o1_5 = 4'b1010 == a;
 | 
			
		||||
	output o1_6 = 4'b1010 != a;
 | 
			
		||||
	output o1_1 = {(LUT_WIDTH/2){2'b10}} <= a;
 | 
			
		||||
	output o1_2 = {(LUT_WIDTH/2){2'b10}} <  a;
 | 
			
		||||
	output o1_3 = {(LUT_WIDTH/2){2'b10}} >= a;
 | 
			
		||||
	output o1_4 = {(LUT_WIDTH/2){2'b10}} >  a;
 | 
			
		||||
	output o1_5 = {(LUT_WIDTH/2){2'b10}} == a;
 | 
			
		||||
	output o1_6 = {(LUT_WIDTH/2){2'b10}} != a;
 | 
			
		||||
 | 
			
		||||
	output o2_1 = a <= 4'b1010;
 | 
			
		||||
	output o2_2 = a <  4'b1010;
 | 
			
		||||
	output o2_3 = a >= 4'b1010;
 | 
			
		||||
	output o2_4 = a >  4'b1010;
 | 
			
		||||
	output o2_5 = a == 4'b1010;
 | 
			
		||||
	output o2_6 = a != 4'b1010;
 | 
			
		||||
	output o2_1 = a <= {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
	output o2_2 = a <  {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
	output o2_3 = a >= {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
	output o2_4 = a >  {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
	output o2_5 = a == {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
	output o2_6 = a != {(LUT_WIDTH/2){2'b10}};
 | 
			
		||||
 | 
			
		||||
	output o3_1 = 4'sb0101 <= $signed(a);
 | 
			
		||||
	output o3_2 = 4'sb0101 <  $signed(a);
 | 
			
		||||
	output o3_3 = 4'sb0101 >= $signed(a);
 | 
			
		||||
	output o3_4 = 4'sb0101 >  $signed(a);
 | 
			
		||||
	output o3_5 = 4'sb0101 == $signed(a);
 | 
			
		||||
	output o3_6 = 4'sb0101 != $signed(a);
 | 
			
		||||
	output o3_1 = {(LUT_WIDTH/2){2'sb01}} <= $signed(a);
 | 
			
		||||
	output o3_2 = {(LUT_WIDTH/2){2'sb01}} <  $signed(a);
 | 
			
		||||
	output o3_3 = {(LUT_WIDTH/2){2'sb01}} >= $signed(a);
 | 
			
		||||
	output o3_4 = {(LUT_WIDTH/2){2'sb01}} >  $signed(a);
 | 
			
		||||
	output o3_5 = {(LUT_WIDTH/2){2'sb01}} == $signed(a);
 | 
			
		||||
	output o3_6 = {(LUT_WIDTH/2){2'sb01}} != $signed(a);
 | 
			
		||||
 | 
			
		||||
	output o4_1 = $signed(a) <= 4'sb0000;
 | 
			
		||||
	output o4_2 = $signed(a) <  4'sb0000;
 | 
			
		||||
	output o4_3 = $signed(a) >= 4'sb0000;
 | 
			
		||||
	output o4_4 = $signed(a) >  4'sb0000;
 | 
			
		||||
	output o4_1 = $signed(a) <= {LUT_WIDTH{1'sb0}};
 | 
			
		||||
	output o4_2 = $signed(a) <  {LUT_WIDTH{1'sb0}};
 | 
			
		||||
	output o4_3 = $signed(a) >= {LUT_WIDTH{1'sb0}};
 | 
			
		||||
	output o4_4 = $signed(a) >  {LUT_WIDTH{1'sb0}};
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,3 +4,8 @@ for x in *.v; do
 | 
			
		|||
  echo "Running $x.."
 | 
			
		||||
  ../../yosys -q -s check_map.ys -l ${x%.v}.log $x
 | 
			
		||||
done
 | 
			
		||||
 | 
			
		||||
for x in map_cmp.v; do
 | 
			
		||||
  echo "Running $x.."
 | 
			
		||||
  ../../yosys -q -s check_map_lut6.ys -l ${x%.v}_lut6.log $x
 | 
			
		||||
done
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,6 +19,6 @@ hierarchy -top abc9_test028
 | 
			
		|||
proc
 | 
			
		||||
 | 
			
		||||
abc9 -lut 4
 | 
			
		||||
select -assert-count 1 t:$lut r:LUT=1 r:WIDTH=1 %i %i
 | 
			
		||||
select -assert-count 1 t:$lut r:LUT=2'b01 r:WIDTH=1 %i %i
 | 
			
		||||
select -assert-count 1 t:unknown
 | 
			
		||||
select -assert-none t:$lut t:unknown %% t: %D
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue