mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-03 21:09:12 +00:00 
			
		
		
		
	Merge branch 'xaig' into xc7mux
This commit is contained in:
		
						commit
						691e145cda
					
				
					 37 changed files with 866 additions and 1744 deletions
				
			
		
							
								
								
									
										13
									
								
								.dockerignore
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								.dockerignore
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
.editorconfig
 | 
			
		||||
.gitignore
 | 
			
		||||
.gitmodules
 | 
			
		||||
.github
 | 
			
		||||
.git
 | 
			
		||||
Dockerfile
 | 
			
		||||
README.md
 | 
			
		||||
manual
 | 
			
		||||
CodingReadme
 | 
			
		||||
CodeOfConduct
 | 
			
		||||
.travis
 | 
			
		||||
.travis.yml
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,9 +17,11 @@ Yosys 0.8 .. Yosys 0.8-dev
 | 
			
		|||
    - Added "rename -src"
 | 
			
		||||
    - Added "equiv_opt" pass
 | 
			
		||||
    - Added "read_aiger" frontend
 | 
			
		||||
    - Added "muxpack" pass
 | 
			
		||||
    - Added "abc9" pass for timing-aware techmapping (experimental, FPGA only, no FFs)
 | 
			
		||||
    - Added "synth_xilinx -abc9" (experimental)
 | 
			
		||||
    - Added "synth_ice40 -abc9" (experimental)
 | 
			
		||||
    - Added "synth -abc9" (experimental)
 | 
			
		||||
    - "synth_xilinx" to now infer hard shift registers, using new "shregmap -tech xilinx"
 | 
			
		||||
    - "synth_xilinx" to now infer wide multiplexers
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
Yosys 0.7 .. Yosys 0.8
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										33
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Dockerfile
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,33 @@
 | 
			
		|||
FROM ubuntu:18.04 as builder
 | 
			
		||||
LABEL author="Abdelrahman Hosny <abdelrahman.hosny@hotmail.com>"
 | 
			
		||||
ENV DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
RUN apt-get update && apt-get install -y build-essential \
 | 
			
		||||
    clang \
 | 
			
		||||
    bison \
 | 
			
		||||
    flex \
 | 
			
		||||
    libreadline-dev \
 | 
			
		||||
    gawk \
 | 
			
		||||
    tcl-dev \
 | 
			
		||||
    libffi-dev \
 | 
			
		||||
    git \
 | 
			
		||||
    pkg-config \
 | 
			
		||||
    python3 && \
 | 
			
		||||
    rm -rf /var/lib/apt/lists
 | 
			
		||||
COPY . /
 | 
			
		||||
RUN make && \
 | 
			
		||||
    make install
 | 
			
		||||
 | 
			
		||||
FROM ubuntu:18.04
 | 
			
		||||
ENV DEBIAN_FRONTEND=noninteractive
 | 
			
		||||
RUN apt-get update && apt-get install -y libreadline-dev tcl-dev
 | 
			
		||||
 | 
			
		||||
COPY --from=builder /yosys /build/yosys
 | 
			
		||||
COPY --from=builder /yosys-abc /build/yosys-abc
 | 
			
		||||
COPY --from=builder /yosys-config /build/yosys-config
 | 
			
		||||
COPY --from=builder /yosys-filterlib /build/yosys-filterlib
 | 
			
		||||
COPY --from=builder /yosys-smtbmc /build/yosys-smtbmc
 | 
			
		||||
 | 
			
		||||
ENV PATH /build:$PATH
 | 
			
		||||
RUN useradd -m yosys
 | 
			
		||||
USER yosys
 | 
			
		||||
ENTRYPOINT ["yosys"]
 | 
			
		||||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *  Copyright (C) 2019  Eddie Hung <eddie@fpgeh.com>
 | 
			
		||||
 *                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
 | 
			
		||||
| 
						 | 
				
			
			@ -18,14 +18,32 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// https://stackoverflow.com/a/46137633
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#define __builtin_bswap32 _byteswap_ulong
 | 
			
		||||
#elif defined(__APPLE__)
 | 
			
		||||
#include <libkern/OSByteOrder.h>
 | 
			
		||||
#define __builtin_bswap32 OSSwapInt32
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "kernel/utils.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
inline int32_t to_big_endian(int32_t i32) {
 | 
			
		||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 | 
			
		||||
	return __builtin_bswap32(i32);
 | 
			
		||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 | 
			
		||||
	return i32;
 | 
			
		||||
#else
 | 
			
		||||
#error "Unknown endianness"
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void aiger_encode(std::ostream &f, int x)
 | 
			
		||||
{
 | 
			
		||||
	log_assert(x >= 0);
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +123,7 @@ struct XAigerWriter
 | 
			
		|||
		return aig_map.at(bit);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	XAigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module)
 | 
			
		||||
	XAigerWriter(Module *module, bool zinit_mode, bool holes_mode=false) : module(module), zinit_mode(zinit_mode), sigmap(module)
 | 
			
		||||
	{
 | 
			
		||||
		pool<SigBit> undriven_bits;
 | 
			
		||||
		pool<SigBit> unused_bits;
 | 
			
		||||
| 
						 | 
				
			
			@ -142,17 +160,11 @@ struct XAigerWriter
 | 
			
		|||
				SigBit wirebit(wire, i);
 | 
			
		||||
				SigBit bit = sigmap(wirebit);
 | 
			
		||||
 | 
			
		||||
				if (bit.wire == nullptr) {
 | 
			
		||||
					if (wire->port_output) {
 | 
			
		||||
						aig_map[wirebit] = (bit == State::S1) ? 1 : 0;
 | 
			
		||||
						output_bits.insert(wirebit);
 | 
			
		||||
					}
 | 
			
		||||
					continue;
 | 
			
		||||
				if (bit.wire) {
 | 
			
		||||
					undriven_bits.insert(bit);
 | 
			
		||||
					unused_bits.insert(bit);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				undriven_bits.insert(bit);
 | 
			
		||||
				unused_bits.insert(bit);
 | 
			
		||||
 | 
			
		||||
				if (wire->port_input || keep) {
 | 
			
		||||
					if (bit != wirebit)
 | 
			
		||||
						alias_map[bit] = wirebit;
 | 
			
		||||
| 
						 | 
				
			
			@ -169,57 +181,16 @@ struct XAigerWriter
 | 
			
		|||
 | 
			
		||||
		for (auto bit : input_bits)
 | 
			
		||||
			undriven_bits.erase(sigmap(bit));
 | 
			
		||||
 | 
			
		||||
		for (auto bit : output_bits)
 | 
			
		||||
			if (!bit.wire->port_input)
 | 
			
		||||
				unused_bits.erase(bit);
 | 
			
		||||
 | 
			
		||||
		dict<SigBit, pool<IdString>> bit_drivers, bit_users;
 | 
			
		||||
		TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
 | 
			
		||||
		SigMap topomap;
 | 
			
		||||
		topomap.database = sigmap.database;
 | 
			
		||||
 | 
			
		||||
		bool abc_box_seen = false;
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
			
		||||
			bool builtin_type = yosys_celltypes.cell_known(cell->type);
 | 
			
		||||
			bool abc_type = inst_module && inst_module->attributes.count("\\abc_box_id");
 | 
			
		||||
 | 
			
		||||
			if (!holes_mode) {
 | 
			
		||||
				toposort.node(cell->name);
 | 
			
		||||
				for (const auto &conn : cell->connections()) {
 | 
			
		||||
					if (!builtin_type && !abc_type)
 | 
			
		||||
						continue;
 | 
			
		||||
 | 
			
		||||
					if (!cell->type.in("$_NOT_", "$_AND_")) {
 | 
			
		||||
						if (builtin_type) {
 | 
			
		||||
							if (conn.first.in("\\Q", "\\CTRL_OUT", "\\RD_DATA"))
 | 
			
		||||
								continue;
 | 
			
		||||
							if (cell->type == "$memrd" && conn.first == "\\DATA")
 | 
			
		||||
								continue;
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if (inst_module) {
 | 
			
		||||
							RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
 | 
			
		||||
							log_assert(inst_module_port);
 | 
			
		||||
 | 
			
		||||
							if (inst_module_port->port_output && inst_module_port->attributes.count("\\abc_flop_q"))
 | 
			
		||||
									continue;
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (cell->input(conn.first)) {
 | 
			
		||||
						// Ignore inout for the sake of topographical ordering
 | 
			
		||||
						if (cell->output(conn.first)) continue;
 | 
			
		||||
						for (auto bit : sigmap(conn.second))
 | 
			
		||||
							bit_users[bit].insert(cell->name);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (cell->output(conn.first))
 | 
			
		||||
						for (auto bit : sigmap(conn.second))
 | 
			
		||||
							bit_drivers[bit].insert(cell->name);
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells()) {
 | 
			
		||||
			if (cell->type == "$_NOT_")
 | 
			
		||||
			{
 | 
			
		||||
				SigBit A = sigmap(cell->getPort("\\A").as_bit());
 | 
			
		||||
| 
						 | 
				
			
			@ -227,6 +198,8 @@ struct XAigerWriter
 | 
			
		|||
				unused_bits.erase(A);
 | 
			
		||||
				undriven_bits.erase(Y);
 | 
			
		||||
				not_map[Y] = A;
 | 
			
		||||
				if (!holes_mode)
 | 
			
		||||
					topomap.add(Y, A);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -249,6 +222,10 @@ struct XAigerWriter
 | 
			
		|||
				unused_bits.erase(B);
 | 
			
		||||
				undriven_bits.erase(Y);
 | 
			
		||||
				and_map[Y] = make_pair(A, B);
 | 
			
		||||
				if (!holes_mode) {
 | 
			
		||||
					topomap.add(Y, A);
 | 
			
		||||
					topomap.add(Y, B);
 | 
			
		||||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -260,50 +237,52 @@ struct XAigerWriter
 | 
			
		|||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
 | 
			
		||||
			bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
 | 
			
		||||
			if (inst_flop) {
 | 
			
		||||
				SigBit d, q;
 | 
			
		||||
				for (const auto &c : cell->connections()) {
 | 
			
		||||
					auto is_input = cell->input(c.first);
 | 
			
		||||
					auto is_output = cell->output(c.first);
 | 
			
		||||
					log_assert(is_input || is_output);
 | 
			
		||||
					RTLIL::Wire* port = inst_module->wire(c.first);
 | 
			
		||||
					for (auto b : c.second.bits()) {
 | 
			
		||||
						if (is_input && port->attributes.count("\\abc_flop_d")) {
 | 
			
		||||
							d = b;
 | 
			
		||||
							SigBit I = sigmap(d);
 | 
			
		||||
							if (I != d)
 | 
			
		||||
								alias_map[I] = d;
 | 
			
		||||
							unused_bits.erase(d);
 | 
			
		||||
						}
 | 
			
		||||
						if (is_output && port->attributes.count("\\abc_flop_q")) {
 | 
			
		||||
							q = b;
 | 
			
		||||
							SigBit O = sigmap(q);
 | 
			
		||||
							if (O != q)
 | 
			
		||||
								alias_map[O] = q;
 | 
			
		||||
							undriven_bits.erase(O);
 | 
			
		||||
						}
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				if (!abc_box_seen)
 | 
			
		||||
					abc_box_seen = inst_module->attributes.count("\\abc_box_id");
 | 
			
		||||
			RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
			
		||||
			//bool inst_flop = inst_module ? inst_module->attributes.count("\\abc_flop") : false;
 | 
			
		||||
			//if (inst_flop) {
 | 
			
		||||
			//	SigBit d, q;
 | 
			
		||||
			//	for (const auto &c : cell->connections()) {
 | 
			
		||||
			//		auto is_input = cell->input(c.first);
 | 
			
		||||
			//		auto is_output = cell->output(c.first);
 | 
			
		||||
			//		log_assert(is_input || is_output);
 | 
			
		||||
			//		RTLIL::Wire* port = inst_module->wire(c.first);
 | 
			
		||||
			//		for (auto b : c.second.bits()) {
 | 
			
		||||
			//			if (is_input && port->attributes.count("\\abc_flop_d")) {
 | 
			
		||||
			//				d = b;
 | 
			
		||||
			//				SigBit I = sigmap(d);
 | 
			
		||||
			//				if (I != d)
 | 
			
		||||
			//					alias_map[I] = d;
 | 
			
		||||
			//				unused_bits.erase(d);
 | 
			
		||||
			//			}
 | 
			
		||||
			//			if (is_output && port->attributes.count("\\abc_flop_q")) {
 | 
			
		||||
			//				q = b;
 | 
			
		||||
			//				SigBit O = sigmap(q);
 | 
			
		||||
			//				if (O != q)
 | 
			
		||||
			//					alias_map[O] = q;
 | 
			
		||||
			//				undriven_bits.erase(O);
 | 
			
		||||
			//			}
 | 
			
		||||
			//		}
 | 
			
		||||
			//	}
 | 
			
		||||
			//	if (!abc_box_seen)
 | 
			
		||||
			//		abc_box_seen = inst_module->attributes.count("\\abc_box_id");
 | 
			
		||||
 | 
			
		||||
				ff_bits.emplace_back(d, q);
 | 
			
		||||
			}
 | 
			
		||||
			else if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
 | 
			
		||||
			//	ff_bits.emplace_back(d, q);
 | 
			
		||||
			//}
 | 
			
		||||
			/*else*/ if (inst_module && inst_module->attributes.count("\\abc_box_id")) {
 | 
			
		||||
				abc_box_seen = true;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				for (const auto &c : cell->connections()) {
 | 
			
		||||
					if (c.second.is_fully_const()) continue;
 | 
			
		||||
					for (auto b : c.second.bits()) {
 | 
			
		||||
						Wire *w = b.wire;
 | 
			
		||||
						if (!w) continue;
 | 
			
		||||
						auto is_input = cell->input(c.first);
 | 
			
		||||
						auto is_output = cell->output(c.first);
 | 
			
		||||
						log_assert(is_input || is_output);
 | 
			
		||||
						if (is_input) {
 | 
			
		||||
							if (!w->port_input) {
 | 
			
		||||
					auto is_input = cell->input(c.first);
 | 
			
		||||
					auto is_output = cell->output(c.first);
 | 
			
		||||
					log_assert(is_input || is_output);
 | 
			
		||||
 | 
			
		||||
					if (is_input) {
 | 
			
		||||
						for (auto b : c.second.bits()) {
 | 
			
		||||
							Wire *w = b.wire;
 | 
			
		||||
							if (!w) continue;
 | 
			
		||||
							if (!w->port_output) {
 | 
			
		||||
								SigBit I = sigmap(b);
 | 
			
		||||
								if (I != b)
 | 
			
		||||
									alias_map[b] = I;
 | 
			
		||||
| 
						 | 
				
			
			@ -311,7 +290,11 @@ struct XAigerWriter
 | 
			
		|||
								unused_bits.erase(b);
 | 
			
		||||
							}
 | 
			
		||||
						}
 | 
			
		||||
						if (is_output) {
 | 
			
		||||
					}
 | 
			
		||||
					if (is_output) {
 | 
			
		||||
						for (auto b : c.second.bits()) {
 | 
			
		||||
							Wire *w = b.wire;
 | 
			
		||||
							if (!w) continue;
 | 
			
		||||
							input_bits.insert(b);
 | 
			
		||||
							SigBit O = sigmap(b);
 | 
			
		||||
							if (O != b)
 | 
			
		||||
| 
						 | 
				
			
			@ -325,20 +308,46 @@ struct XAigerWriter
 | 
			
		|||
			//log_warning("Unsupported cell type: %s (%s)\n", log_id(cell->type), log_id(cell));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (abc_box_seen) {
 | 
			
		||||
		if (abc_box_seen && !holes_mode) {
 | 
			
		||||
			TopoSort<IdString, RTLIL::sort_by_id_str> toposort;
 | 
			
		||||
			dict<SigBit, pool<IdString>> bit_drivers, bit_users;
 | 
			
		||||
 | 
			
		||||
			for (auto cell : module->cells()) {
 | 
			
		||||
				RTLIL::Module* inst_module = module->design->module(cell->type);
 | 
			
		||||
				if (!inst_module || !inst_module->attributes.count("\\abc_box_id"))
 | 
			
		||||
					continue;
 | 
			
		||||
				toposort.node(cell->name);
 | 
			
		||||
				for (const auto &conn : cell->connections()) {
 | 
			
		||||
					if (cell->input(conn.first)) {
 | 
			
		||||
						// Ignore inout for the sake of topographical ordering
 | 
			
		||||
						if (cell->output(conn.first)) continue;
 | 
			
		||||
						for (auto bit : topomap(conn.second))
 | 
			
		||||
							if (bit.wire)
 | 
			
		||||
								bit_users[bit].insert(cell->name);
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (cell->output(conn.first)) {
 | 
			
		||||
						RTLIL::Wire* inst_module_port = inst_module->wire(conn.first);
 | 
			
		||||
						log_assert(inst_module_port);
 | 
			
		||||
						//if (inst_module_port->attributes.count("\\abc_flop_q"))
 | 
			
		||||
						//	continue;
 | 
			
		||||
						for (auto bit : topomap(conn.second))
 | 
			
		||||
							bit_drivers[bit].insert(cell->name);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			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);
 | 
			
		||||
						for (auto user_cell : it.second)
 | 
			
		||||
							toposort.edge(driver_cell, user_cell);
 | 
			
		||||
 | 
			
		||||
			pool<RTLIL::Module*> abc_carry_modules;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
#if 1
 | 
			
		||||
			toposort.analyze_loops = true;
 | 
			
		||||
#endif
 | 
			
		||||
			bool no_loops = toposort.sort();
 | 
			
		||||
#if 0
 | 
			
		||||
#if 1
 | 
			
		||||
			unsigned i = 0;
 | 
			
		||||
			for (auto &it : toposort.loops) {
 | 
			
		||||
				log("  loop %d", i++);
 | 
			
		||||
| 
						 | 
				
			
			@ -349,13 +358,14 @@ struct XAigerWriter
 | 
			
		|||
#endif
 | 
			
		||||
			log_assert(no_loops);
 | 
			
		||||
 | 
			
		||||
			pool<RTLIL::Module*> abc_carry_modules;
 | 
			
		||||
			for (auto cell_name : toposort.sorted) {
 | 
			
		||||
				RTLIL::Cell *cell = module->cell(cell_name);
 | 
			
		||||
				RTLIL::Module* box_module = module->design->module(cell->type);
 | 
			
		||||
				if (!box_module || !box_module->attributes.count("\\abc_box_id"))
 | 
			
		||||
					continue;
 | 
			
		||||
				log_assert(box_module);
 | 
			
		||||
				log_assert(box_module->attributes.count("\\abc_box_id"));
 | 
			
		||||
 | 
			
		||||
				if (box_module->attributes.count("\\abc_carry") && !abc_carry_modules.count(box_module)) {
 | 
			
		||||
				if (!abc_carry_modules.count(box_module) && box_module->attributes.count("\\abc_carry")) {
 | 
			
		||||
					RTLIL::Wire* carry_in = nullptr, *carry_out = nullptr;
 | 
			
		||||
					RTLIL::Wire* last_in = nullptr, *last_out = nullptr;
 | 
			
		||||
					for (const auto &port_name : box_module->ports) {
 | 
			
		||||
| 
						 | 
				
			
			@ -451,8 +461,6 @@ struct XAigerWriter
 | 
			
		|||
				}
 | 
			
		||||
				box_list.emplace_back(cell);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// TODO: Free memory from toposort, bit_drivers, bit_users
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto bit : input_bits) {
 | 
			
		||||
| 
						 | 
				
			
			@ -483,10 +491,6 @@ struct XAigerWriter
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Erase all POs that are undriven
 | 
			
		||||
		if (!holes_mode)
 | 
			
		||||
			for (auto bit : undriven_bits)
 | 
			
		||||
				output_bits.erase(bit);
 | 
			
		||||
		for (auto bit : unused_bits)
 | 
			
		||||
			undriven_bits.erase(bit);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -543,10 +547,6 @@ struct XAigerWriter
 | 
			
		|||
				ff_aig_map[bit] = 2*aig_m;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (imode && input_bits.empty()) {
 | 
			
		||||
			aig_m++, aig_i++;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		//if (zinit_mode)
 | 
			
		||||
		//{
 | 
			
		||||
		//	for (auto it : ff_map) {
 | 
			
		||||
| 
						 | 
				
			
			@ -620,18 +620,9 @@ struct XAigerWriter
 | 
			
		|||
			aig_outputs.push_back(ff_aig_map.at(bit));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (omode && output_bits.empty()) {
 | 
			
		||||
			aig_o++;
 | 
			
		||||
			aig_outputs.push_back(0);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (bmode) {
 | 
			
		||||
			//aig_b++;
 | 
			
		||||
			aig_outputs.push_back(0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_aiger(std::ostream &f, bool ascii_mode, bool miter_mode, bool symbols_mode, bool omode)
 | 
			
		||||
	void write_aiger(std::ostream &f, bool ascii_mode)
 | 
			
		||||
	{
 | 
			
		||||
		int aig_obc = aig_o;
 | 
			
		||||
		int aig_obcj = aig_obc;
 | 
			
		||||
| 
						 | 
				
			
			@ -708,98 +699,25 @@ struct XAigerWriter
 | 
			
		|||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (symbols_mode)
 | 
			
		||||
		{
 | 
			
		||||
			dict<string, vector<string>> symbols;
 | 
			
		||||
 | 
			
		||||
			bool output_seen = false;
 | 
			
		||||
			for (auto wire : module->wires())
 | 
			
		||||
			{
 | 
			
		||||
				//if (wire->name[0] == '$')
 | 
			
		||||
				//	continue;
 | 
			
		||||
 | 
			
		||||
				SigSpec sig = sigmap(wire);
 | 
			
		||||
 | 
			
		||||
				for (int i = 0; i < GetSize(wire); i++)
 | 
			
		||||
				{
 | 
			
		||||
					RTLIL::SigBit b(wire, i);
 | 
			
		||||
					if (input_bits.count(b)) {
 | 
			
		||||
						int a = aig_map.at(sig[i]);
 | 
			
		||||
						log_assert((a & 1) == 0);
 | 
			
		||||
						if (GetSize(wire) != 1)
 | 
			
		||||
							symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s[%d]", log_id(wire), i));
 | 
			
		||||
						else
 | 
			
		||||
							symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("%s", log_id(wire)));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					if (output_bits.count(b)) {
 | 
			
		||||
						int o = ordered_outputs.at(b);
 | 
			
		||||
						output_seen = !miter_mode;
 | 
			
		||||
						if (GetSize(wire) != 1)
 | 
			
		||||
							symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s[%d]", log_id(wire), i));
 | 
			
		||||
						else
 | 
			
		||||
							symbols[stringf("%c%d", miter_mode ? 'b' : 'o', o)].push_back(stringf("%s", log_id(wire)));
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					//if (init_inputs.count(sig[i])) {
 | 
			
		||||
					//	int a = init_inputs.at(sig[i]);
 | 
			
		||||
					//	log_assert((a & 1) == 0);
 | 
			
		||||
					//	if (GetSize(wire) != 1)
 | 
			
		||||
					//		symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s[%d]", log_id(wire), i));
 | 
			
		||||
					//	else
 | 
			
		||||
					//		symbols[stringf("i%d", (a >> 1)-1)].push_back(stringf("init:%s", log_id(wire)));
 | 
			
		||||
					//}
 | 
			
		||||
 | 
			
		||||
					if (ordered_latches.count(sig[i])) {
 | 
			
		||||
						int l = ordered_latches.at(sig[i]);
 | 
			
		||||
						const char *p = (zinit_mode && (aig_latchinit.at(l) == 1)) ? "!" : "";
 | 
			
		||||
						if (GetSize(wire) != 1)
 | 
			
		||||
							symbols[stringf("l%d", l)].push_back(stringf("%s%s[%d]", p, log_id(wire), i));
 | 
			
		||||
						else
 | 
			
		||||
							symbols[stringf("l%d", l)].push_back(stringf("%s%s", p, log_id(wire)));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (omode && !output_seen)
 | 
			
		||||
				symbols["o0"].push_back("__dummy_o__");
 | 
			
		||||
 | 
			
		||||
			symbols.sort();
 | 
			
		||||
 | 
			
		||||
			for (auto &sym : symbols) {
 | 
			
		||||
				f << sym.first;
 | 
			
		||||
				std::sort(sym.second.begin(), sym.second.end());
 | 
			
		||||
				for (auto &s : sym.second)
 | 
			
		||||
					f << " " << s;
 | 
			
		||||
				f << std::endl;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		f << "c";
 | 
			
		||||
 | 
			
		||||
		if (!box_list.empty() || !ff_bits.empty()) {
 | 
			
		||||
			std::stringstream h_buffer;
 | 
			
		||||
			auto write_h_buffer = [&h_buffer](int i32) {
 | 
			
		||||
				// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
				int i32_be = _byteswap_ulong(i32);
 | 
			
		||||
#else
 | 
			
		||||
				int i32_be = __builtin_bswap32(i32);
 | 
			
		||||
#endif
 | 
			
		||||
				h_buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
 | 
			
		||||
			auto write_buffer = [](std::stringstream &buffer, int i32) {
 | 
			
		||||
				int32_t i32_be = to_big_endian(i32);
 | 
			
		||||
				buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
 | 
			
		||||
			};
 | 
			
		||||
			int num_outputs = output_bits.size();
 | 
			
		||||
			if (omode && num_outputs == 0)
 | 
			
		||||
				num_outputs = 1;
 | 
			
		||||
 | 
			
		||||
			std::stringstream h_buffer;
 | 
			
		||||
			auto write_h_buffer = std::bind(write_buffer, std::ref(h_buffer), std::placeholders::_1);
 | 
			
		||||
			write_h_buffer(1);
 | 
			
		||||
			log_debug("ciNum = %zu\n", input_bits.size() + ff_bits.size() + ci_bits.size());
 | 
			
		||||
			write_h_buffer(input_bits.size() + ff_bits.size() + ci_bits.size());
 | 
			
		||||
			log_debug("coNum = %zu\n", num_outputs + ff_bits.size() + co_bits.size());
 | 
			
		||||
			write_h_buffer(num_outputs + ff_bits.size()+ co_bits.size());
 | 
			
		||||
			log_debug("coNum = %zu\n", output_bits.size() + ff_bits.size() + co_bits.size());
 | 
			
		||||
			write_h_buffer(output_bits.size() + ff_bits.size()+ co_bits.size());
 | 
			
		||||
			log_debug("piNum = %zu\n", input_bits.size() + ff_bits.size());
 | 
			
		||||
			write_h_buffer(input_bits.size()+ ff_bits.size());
 | 
			
		||||
			log_debug("poNum = %zu\n", num_outputs + ff_bits.size());
 | 
			
		||||
			write_h_buffer(num_outputs + ff_bits.size());
 | 
			
		||||
			log_debug("poNum = %zu\n", output_bits.size() + ff_bits.size());
 | 
			
		||||
			write_h_buffer(output_bits.size() + ff_bits.size());
 | 
			
		||||
			log_debug("boxNum = %zu\n", box_list.size());
 | 
			
		||||
			write_h_buffer(box_list.size());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -869,40 +787,22 @@ struct XAigerWriter
 | 
			
		|||
 | 
			
		||||
			f << "h";
 | 
			
		||||
			std::string buffer_str = h_buffer.str();
 | 
			
		||||
			// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
			int buffer_size_be = _byteswap_ulong(buffer_str.size());
 | 
			
		||||
#else
 | 
			
		||||
			int buffer_size_be = __builtin_bswap32(buffer_str.size());
 | 
			
		||||
#endif
 | 
			
		||||
			int32_t buffer_size_be = to_big_endian(buffer_str.size());
 | 
			
		||||
			f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
 | 
			
		||||
			f.write(buffer_str.data(), buffer_str.size());
 | 
			
		||||
 | 
			
		||||
			/*if (!ff_bits.empty())*/ {
 | 
			
		||||
				std::stringstream r_buffer;
 | 
			
		||||
				auto write_r_buffer = [&r_buffer](int i32) {
 | 
			
		||||
					// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
					int i32_be = _byteswap_ulong(i32);
 | 
			
		||||
#else
 | 
			
		||||
					int i32_be = __builtin_bswap32(i32);
 | 
			
		||||
#endif
 | 
			
		||||
					r_buffer.write(reinterpret_cast<const char*>(&i32_be), sizeof(i32_be));
 | 
			
		||||
				};
 | 
			
		||||
				auto write_r_buffer = std::bind(write_buffer, std::ref(r_buffer), std::placeholders::_1);
 | 
			
		||||
				log_debug("flopNum = %zu\n", ff_bits.size());
 | 
			
		||||
				write_r_buffer(ff_bits.size());
 | 
			
		||||
				int mergeability_class = 1;
 | 
			
		||||
				for (auto cell : ff_bits)
 | 
			
		||||
					write_r_buffer(mergeability_class++);
 | 
			
		||||
				//int mergeability_class = 1;
 | 
			
		||||
				//for (auto cell : ff_bits)
 | 
			
		||||
				//	write_r_buffer(mergeability_class++);
 | 
			
		||||
 | 
			
		||||
				f << "r";
 | 
			
		||||
				std::string buffer_str = r_buffer.str();
 | 
			
		||||
				// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
				int buffer_size_be = _byteswap_ulong(buffer_str.size());
 | 
			
		||||
#else
 | 
			
		||||
				int buffer_size_be = __builtin_bswap32(buffer_str.size());
 | 
			
		||||
#endif
 | 
			
		||||
				int32_t buffer_size_be = to_big_endian(buffer_str.size());
 | 
			
		||||
				f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
 | 
			
		||||
				f.write(buffer_str.data(), buffer_str.size());
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -923,25 +823,19 @@ struct XAigerWriter
 | 
			
		|||
				Pass::call(holes_module->design, "flatten -wb");
 | 
			
		||||
 | 
			
		||||
				// TODO: Should techmap all lib_whitebox-es once
 | 
			
		||||
				//Pass::call(holes_module->design, "techmap");
 | 
			
		||||
 | 
			
		||||
				Pass::call(holes_module->design, "techmap");
 | 
			
		||||
				Pass::call(holes_module->design, "aigmap");
 | 
			
		||||
				Pass::call(holes_module->design, "clean -purge");
 | 
			
		||||
 | 
			
		||||
				holes_module->design->selection_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
				std::stringstream a_buffer;
 | 
			
		||||
				XAigerWriter writer(holes_module, false /*zinit_mode*/, false /*imode*/, false /*omode*/, false /*bmode*/, true /* holes_mode */);
 | 
			
		||||
				writer.write_aiger(a_buffer, false /*ascii_mode*/, false /*miter_mode*/, false /*symbols_mode*/, false /*omode*/);
 | 
			
		||||
				XAigerWriter writer(holes_module, false /*zinit_mode*/, true /* holes_mode */);
 | 
			
		||||
				writer.write_aiger(a_buffer, false /*ascii_mode*/);
 | 
			
		||||
 | 
			
		||||
				f << "a";
 | 
			
		||||
				std::string buffer_str = a_buffer.str();
 | 
			
		||||
				// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
				int buffer_size_be = _byteswap_ulong(buffer_str.size());
 | 
			
		||||
#else
 | 
			
		||||
				int buffer_size_be = __builtin_bswap32(buffer_str.size());
 | 
			
		||||
#endif
 | 
			
		||||
				int32_t buffer_size_be = to_big_endian(buffer_str.size());
 | 
			
		||||
				f.write(reinterpret_cast<const char*>(&buffer_size_be), sizeof(buffer_size_be));
 | 
			
		||||
				f.write(buffer_str.data(), buffer_str.size());
 | 
			
		||||
				holes_module->design->remove(holes_module);
 | 
			
		||||
| 
						 | 
				
			
			@ -951,7 +845,7 @@ struct XAigerWriter
 | 
			
		|||
		f << stringf("Generated by %s\n", yosys_version_str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void write_map(std::ostream &f, bool verbose_map, bool omode)
 | 
			
		||||
	void write_map(std::ostream &f, bool verbose_map)
 | 
			
		||||
	{
 | 
			
		||||
		dict<int, string> input_lines;
 | 
			
		||||
		dict<int, string> init_lines;
 | 
			
		||||
| 
						 | 
				
			
			@ -1024,8 +918,6 @@ struct XAigerWriter
 | 
			
		|||
		for (auto &it : output_lines)
 | 
			
		||||
			f << it.second;
 | 
			
		||||
		log_assert(output_lines.size() == output_bits.size());
 | 
			
		||||
		if (omode && output_bits.empty())
 | 
			
		||||
			f << "output " << output_lines.size() << " 0 __dummy_o__\n";
 | 
			
		||||
 | 
			
		||||
		latch_lines.sort();
 | 
			
		||||
		for (auto &it : latch_lines)
 | 
			
		||||
| 
						 | 
				
			
			@ -1055,31 +947,18 @@ struct XAigerBackend : public Backend {
 | 
			
		|||
		log("        convert FFs to zero-initialized FFs, adding additional inputs for\n");
 | 
			
		||||
		log("        uninitialized FFs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -symbols\n");
 | 
			
		||||
		log("        include a symbol table in the generated AIGER file\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -map <filename>\n");
 | 
			
		||||
		log("        write an extra file with port and latch symbols\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -vmap <filename>\n");
 | 
			
		||||
		log("        like -map, but more verbose\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -I, -O, -B\n");
 | 
			
		||||
		log("        If the design contains no input/output/assert then create one\n");
 | 
			
		||||
		log("        dummy input/output/bad_state pin to make the tools reading the\n");
 | 
			
		||||
		log("        AIGER file happy.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::ostream *&f, std::string filename, std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		bool ascii_mode = false;
 | 
			
		||||
		bool zinit_mode = false;
 | 
			
		||||
		bool miter_mode = false;
 | 
			
		||||
		bool symbols_mode = false;
 | 
			
		||||
		bool verbose_map = false;
 | 
			
		||||
		bool imode = false;
 | 
			
		||||
		bool omode = false;
 | 
			
		||||
		bool bmode = false;
 | 
			
		||||
		std::string map_filename;
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing XAIGER backend.\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1095,10 +974,6 @@ struct XAigerBackend : public Backend {
 | 
			
		|||
				zinit_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-symbols") {
 | 
			
		||||
				symbols_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) {
 | 
			
		||||
				map_filename = args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -1108,18 +983,6 @@ struct XAigerBackend : public Backend {
 | 
			
		|||
				verbose_map = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-I") {
 | 
			
		||||
				imode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-O") {
 | 
			
		||||
				omode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-B") {
 | 
			
		||||
				bmode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(f, filename, args, argidx);
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,15 +992,15 @@ struct XAigerBackend : public Backend {
 | 
			
		|||
		if (top_module == nullptr)
 | 
			
		||||
			log_error("Can't find top module in current design!\n");
 | 
			
		||||
 | 
			
		||||
		XAigerWriter writer(top_module, zinit_mode, imode, omode, bmode);
 | 
			
		||||
		writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode, omode);
 | 
			
		||||
		XAigerWriter writer(top_module, zinit_mode);
 | 
			
		||||
		writer.write_aiger(*f, ascii_mode);
 | 
			
		||||
 | 
			
		||||
		if (!map_filename.empty()) {
 | 
			
		||||
			std::ofstream mapf;
 | 
			
		||||
			mapf.open(map_filename.c_str(), std::ofstream::trunc);
 | 
			
		||||
			if (mapf.fail())
 | 
			
		||||
				log_error("Can't open file `%s' for writing: %s\n", map_filename.c_str(), strerror(errno));
 | 
			
		||||
			writer.write_map(mapf, verbose_map, omode);
 | 
			
		||||
			writer.write_map(mapf, verbose_map);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} XAigerBackend;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *  Copyright (C) 2019  Eddie Hung <eddie@fpgeh.com>
 | 
			
		||||
 *                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
 | 
			
		||||
| 
						 | 
				
			
			@ -24,17 +24,179 @@
 | 
			
		|||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#include <libgen.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <array>
 | 
			
		||||
// https://stackoverflow.com/a/46137633
 | 
			
		||||
#ifdef _MSC_VER
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#define __builtin_bswap32 _byteswap_ulong
 | 
			
		||||
#elif defined(__APPLE__)
 | 
			
		||||
#include <libkern/OSByteOrder.h>
 | 
			
		||||
#define __builtin_bswap32 OSSwapInt32
 | 
			
		||||
#endif
 | 
			
		||||
#include <inttypes.h>
 | 
			
		||||
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
#include "kernel/consteval.h"
 | 
			
		||||
#include "kernel/celltypes.h"
 | 
			
		||||
#include "aigerparse.h"
 | 
			
		||||
 | 
			
		||||
YOSYS_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
inline int32_t from_big_endian(int32_t i32) {
 | 
			
		||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 | 
			
		||||
	return __builtin_bswap32(i32);
 | 
			
		||||
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 | 
			
		||||
	return i32;
 | 
			
		||||
#else
 | 
			
		||||
#error "Unknown endianness"
 | 
			
		||||
#endif
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct ConstEvalAig
 | 
			
		||||
{
 | 
			
		||||
	RTLIL::Module *module;
 | 
			
		||||
	dict<RTLIL::SigBit, RTLIL::State> values_map;
 | 
			
		||||
	dict<RTLIL::SigBit, RTLIL::Cell*> sig2driver;
 | 
			
		||||
	dict<SigBit, pool<RTLIL::SigBit>> sig2deps;
 | 
			
		||||
 | 
			
		||||
	ConstEvalAig(RTLIL::Module *module) : module(module)
 | 
			
		||||
	{
 | 
			
		||||
		for (auto &it : module->cells_) {
 | 
			
		||||
			if (!yosys_celltypes.cell_known(it.second->type))
 | 
			
		||||
				continue;
 | 
			
		||||
			for (auto &it2 : it.second->connections())
 | 
			
		||||
				if (yosys_celltypes.cell_output(it.second->type, it2.first)) {
 | 
			
		||||
					auto r = sig2driver.insert(std::make_pair(it2.second, it.second));
 | 
			
		||||
					log_assert(r.second);
 | 
			
		||||
				}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void clear()
 | 
			
		||||
	{
 | 
			
		||||
		values_map.clear();
 | 
			
		||||
		sig2deps.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void set(RTLIL::SigBit sig, RTLIL::State value)
 | 
			
		||||
	{
 | 
			
		||||
		auto it = values_map.find(sig);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
		if (it != values_map.end()) {
 | 
			
		||||
			RTLIL::State current_val = it->second;
 | 
			
		||||
			log_assert(current_val == value);
 | 
			
		||||
		}
 | 
			
		||||
#endif
 | 
			
		||||
		if (it != values_map.end())
 | 
			
		||||
			it->second = value;
 | 
			
		||||
		else
 | 
			
		||||
			values_map[sig] = value;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void set_incremental(RTLIL::SigSpec sig, RTLIL::Const value)
 | 
			
		||||
	{
 | 
			
		||||
		log_assert(GetSize(sig) == GetSize(value));
 | 
			
		||||
 | 
			
		||||
		for (int i = 0; i < GetSize(sig); i++) {
 | 
			
		||||
			auto it = values_map.find(sig[i]);
 | 
			
		||||
			if (it != values_map.end()) {
 | 
			
		||||
				RTLIL::State current_val = it->second;
 | 
			
		||||
				if (current_val != value[i])
 | 
			
		||||
					for (auto dep : sig2deps[sig[i]])
 | 
			
		||||
						values_map.erase(dep);
 | 
			
		||||
				it->second = value[i];
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
				values_map[sig[i]] = value[i];
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void compute_deps(RTLIL::SigBit output, const pool<RTLIL::SigBit> &inputs)
 | 
			
		||||
	{
 | 
			
		||||
		sig2deps[output].insert(output);
 | 
			
		||||
 | 
			
		||||
		RTLIL::Cell *cell = sig2driver.at(output);
 | 
			
		||||
		RTLIL::SigBit sig_a = cell->getPort("\\A");
 | 
			
		||||
		sig2deps[sig_a].insert(sig2deps[output].begin(), sig2deps[output].end());
 | 
			
		||||
		if (!inputs.count(sig_a))
 | 
			
		||||
			compute_deps(sig_a, inputs);
 | 
			
		||||
 | 
			
		||||
		if (cell->type == "$_AND_") {
 | 
			
		||||
			RTLIL::SigSpec sig_b = cell->getPort("\\B");
 | 
			
		||||
			sig2deps[sig_b].insert(sig2deps[output].begin(), sig2deps[output].end());
 | 
			
		||||
			if (!inputs.count(sig_b))
 | 
			
		||||
				compute_deps(sig_b, inputs);
 | 
			
		||||
		}
 | 
			
		||||
		else if (cell->type == "$_NOT_") {
 | 
			
		||||
		}
 | 
			
		||||
		else log_abort();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool eval(RTLIL::Cell *cell)
 | 
			
		||||
	{
 | 
			
		||||
		RTLIL::SigBit sig_y = cell->getPort("\\Y");
 | 
			
		||||
		if (values_map.count(sig_y))
 | 
			
		||||
			return true;
 | 
			
		||||
 | 
			
		||||
		RTLIL::SigBit sig_a = cell->getPort("\\A");
 | 
			
		||||
		if (!eval(sig_a))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		RTLIL::State eval_ret = RTLIL::Sx;
 | 
			
		||||
		if (cell->type == "$_NOT_") {
 | 
			
		||||
			if (sig_a == RTLIL::S0) eval_ret = RTLIL::S1;
 | 
			
		||||
			else if (sig_a == RTLIL::S1) eval_ret = RTLIL::S0;
 | 
			
		||||
		}
 | 
			
		||||
		else if (cell->type == "$_AND_") {
 | 
			
		||||
			if (sig_a == RTLIL::S0) {
 | 
			
		||||
				eval_ret = RTLIL::S0;
 | 
			
		||||
				goto eval_end;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				RTLIL::SigBit sig_b = cell->getPort("\\B");
 | 
			
		||||
				if (!eval(sig_b))
 | 
			
		||||
					return false;
 | 
			
		||||
				if (sig_b == RTLIL::S0) {
 | 
			
		||||
					eval_ret = RTLIL::S0;
 | 
			
		||||
					goto eval_end;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (sig_a != RTLIL::S1 || sig_b != RTLIL::S1)
 | 
			
		||||
					goto eval_end;
 | 
			
		||||
 | 
			
		||||
				eval_ret = RTLIL::S1;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else log_abort();
 | 
			
		||||
 | 
			
		||||
eval_end:
 | 
			
		||||
		set(sig_y, eval_ret);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	bool eval(RTLIL::SigBit &sig)
 | 
			
		||||
	{
 | 
			
		||||
		auto it = values_map.find(sig);
 | 
			
		||||
		if (it != values_map.end()) {
 | 
			
		||||
			sig = it->second;
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		RTLIL::Cell *cell = sig2driver.at(sig);
 | 
			
		||||
		if (!eval(cell))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		it = values_map.find(sig);
 | 
			
		||||
		if (it != values_map.end()) {
 | 
			
		||||
			sig = it->second;
 | 
			
		||||
			return true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
AigerReader::AigerReader(RTLIL::Design *design, std::istream &f, RTLIL::IdString module_name, RTLIL::IdString clk_name, std::string map_filename, bool wideports)
 | 
			
		||||
	: design(design), f(f), clk_name(clk_name), map_filename(map_filename), wideports(wideports)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -132,20 +294,15 @@ static uint32_t parse_xaiger_literal(std::istream &f)
 | 
			
		|||
	uint32_t l;
 | 
			
		||||
	f.read(reinterpret_cast<char*>(&l), sizeof(l));
 | 
			
		||||
	if (f.gcount() != sizeof(l))
 | 
			
		||||
		log_error("Offset %ld: unable to read literal!\n", static_cast<int64_t>(f.tellg()));
 | 
			
		||||
	// TODO: Don't assume we're on little endian
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
	return _byteswap_ulong(l);
 | 
			
		||||
#else
 | 
			
		||||
	return __builtin_bswap32(l);
 | 
			
		||||
#endif
 | 
			
		||||
		log_error("Offset %" PRId64 ": unable to read literal!\n", static_cast<int64_t>(f.tellg()));
 | 
			
		||||
	return from_big_endian(l);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned literal)
 | 
			
		||||
{
 | 
			
		||||
	const unsigned variable = literal >> 1;
 | 
			
		||||
	const bool invert = literal & 1;
 | 
			
		||||
	RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : "")); // FIXME: is "b" the right suffix?
 | 
			
		||||
	RTLIL::IdString wire_name(stringf("\\__%d%s__", variable, invert ? "b" : ""));
 | 
			
		||||
	RTLIL::Wire *wire = module->wire(wire_name);
 | 
			
		||||
	if (wire) return wire;
 | 
			
		||||
	log_debug("Creating %s\n", wire_name.c_str());
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +321,7 @@ static RTLIL::Wire* createWireIfNotExists(RTLIL::Module *module, unsigned litera
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	log_debug("Creating %s = ~%s\n", wire_name.c_str(), wire_inv_name.c_str());
 | 
			
		||||
	module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire); // FIXME: is "$not" the right suffix?
 | 
			
		||||
	module->addNotGate(stringf("\\__%d__$not", variable), wire_inv, wire);
 | 
			
		||||
 | 
			
		||||
	return wire;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -210,7 +367,8 @@ void AigerReader::parse_xaiger()
 | 
			
		|||
		auto it = m->attributes.find("\\abc_box_id");
 | 
			
		||||
		if (it == m->attributes.end())
 | 
			
		||||
			continue;
 | 
			
		||||
		if (m->name[0] == '$') continue;
 | 
			
		||||
		if (m->name.begins_with("$paramod"))
 | 
			
		||||
			continue;
 | 
			
		||||
		auto r = box_lookup.insert(std::make_pair(it->second.as_int(), m->name));
 | 
			
		||||
		log_assert(r.second);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +392,7 @@ void AigerReader::parse_xaiger()
 | 
			
		|||
				uint32_t lutNum = parse_xaiger_literal(f);
 | 
			
		||||
				uint32_t lutSize = parse_xaiger_literal(f);
 | 
			
		||||
				log_debug("m: dataSize=%u lutNum=%u lutSize=%u\n", dataSize, lutNum, lutSize);
 | 
			
		||||
				ConstEval ce(module);
 | 
			
		||||
				ConstEvalAig ce(module);
 | 
			
		||||
				for (unsigned i = 0; i < lutNum; ++i) {
 | 
			
		||||
					uint32_t rootNodeID = parse_xaiger_literal(f);
 | 
			
		||||
					uint32_t cutLeavesM = parse_xaiger_literal(f);
 | 
			
		||||
| 
						 | 
				
			
			@ -249,14 +407,18 @@ void AigerReader::parse_xaiger()
 | 
			
		|||
						log_assert(wire);
 | 
			
		||||
						input_sig.append(wire);
 | 
			
		||||
					}
 | 
			
		||||
					// TODO: Compute LUT mask from AIG in less than O(2 ** input_sig.size())
 | 
			
		||||
					ce.clear();
 | 
			
		||||
					ce.compute_deps(output_sig, input_sig.to_sigbit_pool());
 | 
			
		||||
					RTLIL::Const lut_mask(RTLIL::State::Sx, 1 << input_sig.size());
 | 
			
		||||
					for (int j = 0; j < (1 << cutLeavesM); ++j) {
 | 
			
		||||
						ce.push();
 | 
			
		||||
						ce.set(input_sig, RTLIL::Const{j, static_cast<int>(cutLeavesM)});
 | 
			
		||||
						RTLIL::SigSpec o(output_sig);
 | 
			
		||||
						ce.eval(o);
 | 
			
		||||
						lut_mask[j] = o.as_const()[0];
 | 
			
		||||
						ce.pop();
 | 
			
		||||
						int gray = j ^ (j >> 1);
 | 
			
		||||
						ce.set_incremental(input_sig, RTLIL::Const{gray, static_cast<int>(cutLeavesM)});
 | 
			
		||||
						RTLIL::SigBit o(output_sig);
 | 
			
		||||
						bool success = ce.eval(o);
 | 
			
		||||
						log_assert(success);
 | 
			
		||||
						log_assert(o.wire == nullptr);
 | 
			
		||||
						lut_mask[gray] = o.data;
 | 
			
		||||
					}
 | 
			
		||||
					RTLIL::Cell *output_cell = module->cell(stringf("\\__%d__$and", rootNodeID));
 | 
			
		||||
					log_assert(output_cell);
 | 
			
		||||
| 
						 | 
				
			
			@ -346,7 +508,7 @@ void AigerReader::parse_aiger_ascii()
 | 
			
		|||
		if (!(f >> l1 >> l2))
 | 
			
		||||
			log_error("Line %u cannot be interpreted as a latch!\n", line_count);
 | 
			
		||||
		log_debug("%d %d is a latch\n", l1, l2);
 | 
			
		||||
		log_assert(!(l1 & 1)); // TODO: Latch outputs can't be inverted?
 | 
			
		||||
		log_assert(!(l1 & 1));
 | 
			
		||||
		RTLIL::Wire *q_wire = createWireIfNotExists(module, l1);
 | 
			
		||||
		RTLIL::Wire *d_wire = createWireIfNotExists(module, l2);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -696,10 +858,6 @@ void AigerReader::post_process()
 | 
			
		|||
				RTLIL::Wire* wire = outputs[variable + co_count];
 | 
			
		||||
				log_assert(wire);
 | 
			
		||||
				log_assert(wire->port_output);
 | 
			
		||||
				if (escaped_s.in("\\__dummy_o__", "\\__const0__", "\\__const1__")) {
 | 
			
		||||
					wire->port_output = false;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (index == 0) {
 | 
			
		||||
					// Cope with the fact that a CO might be identical
 | 
			
		||||
| 
						 | 
				
			
			@ -797,8 +955,6 @@ void AigerReader::post_process()
 | 
			
		|||
				port_output = port_output || other_wire->port_output;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if ((port_input && port_output) || (!port_input && !port_output))
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		wire = module->addWire(name, width);
 | 
			
		||||
		wire->port_input = port_input;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *                      Eddie Hung <eddie@fpgeh.com>
 | 
			
		||||
 *                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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -276,6 +276,12 @@ namespace RTLIL
 | 
			
		|||
				return std::string(c_str() + pos, len);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool begins_with(const char* prefix) const {
 | 
			
		||||
			size_t len = strlen(prefix);
 | 
			
		||||
			if (size() < len) return false;
 | 
			
		||||
			return substr(0, len) == prefix;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		bool ends_with(const char* suffix) const {
 | 
			
		||||
			size_t len = strlen(suffix);
 | 
			
		||||
			if (size() < len) return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -339,9 +339,6 @@ struct StatPass : public Pass {
 | 
			
		|||
				if (mod->get_bool_attribute("\\top"))
 | 
			
		||||
					top_mod = mod;
 | 
			
		||||
 | 
			
		||||
			if (mod->attributes.count("\\abc_box_id"))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			statdata_t data(design, mod, width_mode, cell_area, techname);
 | 
			
		||||
			mod_stat[mod->name] = data;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,6 +14,5 @@ OBJS += passes/opt/opt_demorgan.o
 | 
			
		|||
OBJS += passes/opt/rmports.o
 | 
			
		||||
OBJS += passes/opt/opt_lut.o
 | 
			
		||||
OBJS += passes/opt/pmux2shiftx.o
 | 
			
		||||
OBJS += passes/opt/muxpack.o
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,270 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  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/yosys.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
struct MuxpackWorker
 | 
			
		||||
{
 | 
			
		||||
	Module *module;
 | 
			
		||||
	SigMap sigmap;
 | 
			
		||||
 | 
			
		||||
	int mux_count, pmux_count;
 | 
			
		||||
 | 
			
		||||
	pool<Cell*> remove_cells;
 | 
			
		||||
 | 
			
		||||
	dict<SigSpec, Cell*> sig_chain_next;
 | 
			
		||||
	dict<SigSpec, Cell*> sig_chain_prev;
 | 
			
		||||
	pool<SigBit> sigbit_with_non_chain_users;
 | 
			
		||||
	pool<Cell*> chain_start_cells;
 | 
			
		||||
	pool<Cell*> candidate_cells;
 | 
			
		||||
 | 
			
		||||
	void make_sig_chain_next_prev()
 | 
			
		||||
	{
 | 
			
		||||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
				for (auto bit : sigmap(wire))
 | 
			
		||||
					sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for (auto cell : module->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type.in("$mux", "$pmux") && !cell->get_bool_attribute("\\keep"))
 | 
			
		||||
			{
 | 
			
		||||
				SigSpec a_sig = sigmap(cell->getPort("\\A"));
 | 
			
		||||
				SigSpec b_sig;
 | 
			
		||||
				if (cell->type == "$mux")
 | 
			
		||||
					b_sig = sigmap(cell->getPort("\\B"));
 | 
			
		||||
				SigSpec y_sig = sigmap(cell->getPort("\\Y"));
 | 
			
		||||
   
 | 
			
		||||
				if (sig_chain_next.count(a_sig))
 | 
			
		||||
					for (auto a_bit : a_sig.bits())
 | 
			
		||||
						sigbit_with_non_chain_users.insert(a_bit);
 | 
			
		||||
				else {
 | 
			
		||||
					sig_chain_next[a_sig] = cell;
 | 
			
		||||
					candidate_cells.insert(cell);
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if (!b_sig.empty()) {
 | 
			
		||||
					if (sig_chain_next.count(b_sig))
 | 
			
		||||
						for (auto b_bit : b_sig.bits())
 | 
			
		||||
							sigbit_with_non_chain_users.insert(b_bit);
 | 
			
		||||
					else {
 | 
			
		||||
						sig_chain_next[b_sig] = cell;
 | 
			
		||||
						candidate_cells.insert(cell);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				sig_chain_prev[y_sig] = cell;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			for (auto conn : cell->connections())
 | 
			
		||||
				if (cell->input(conn.first))
 | 
			
		||||
					for (auto bit : sigmap(conn.second))
 | 
			
		||||
						sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void find_chain_start_cells()
 | 
			
		||||
	{
 | 
			
		||||
		for (auto cell : candidate_cells)
 | 
			
		||||
		{
 | 
			
		||||
			log_debug("Considering %s (%s)\n", log_id(cell), log_id(cell->type));
 | 
			
		||||
 | 
			
		||||
			SigSpec a_sig = cell->getPort("\\A");
 | 
			
		||||
			if (cell->type == "$mux") {
 | 
			
		||||
				SigSpec b_sig = cell->getPort("\\B");
 | 
			
		||||
				if (sig_chain_prev.count(a_sig) + sig_chain_prev.count(b_sig) != 1)
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
 | 
			
		||||
				if (!sig_chain_prev.count(a_sig))
 | 
			
		||||
					a_sig = b_sig;
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$pmux") {
 | 
			
		||||
				if (!sig_chain_prev.count(a_sig))
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
			}
 | 
			
		||||
			else log_abort();
 | 
			
		||||
 | 
			
		||||
			{
 | 
			
		||||
				for (auto bit : a_sig.bits())
 | 
			
		||||
					if (sigbit_with_non_chain_users.count(bit))
 | 
			
		||||
						goto start_cell;
 | 
			
		||||
 | 
			
		||||
				Cell *c1 = sig_chain_prev.at(a_sig);
 | 
			
		||||
				Cell *c2 = cell;
 | 
			
		||||
 | 
			
		||||
				if (c1->getParam("\\WIDTH") != c2->getParam("\\WIDTH"))
 | 
			
		||||
					goto start_cell;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			continue;
 | 
			
		||||
 | 
			
		||||
		start_cell:
 | 
			
		||||
			chain_start_cells.insert(cell);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	vector<Cell*> create_chain(Cell *start_cell)
 | 
			
		||||
	{
 | 
			
		||||
		vector<Cell*> chain;
 | 
			
		||||
 | 
			
		||||
		Cell *c = start_cell;
 | 
			
		||||
		while (c != nullptr)
 | 
			
		||||
		{
 | 
			
		||||
			chain.push_back(c);
 | 
			
		||||
 | 
			
		||||
			SigSpec y_sig = sigmap(c->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			if (sig_chain_next.count(y_sig) == 0)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			c = sig_chain_next.at(y_sig);
 | 
			
		||||
			if (chain_start_cells.count(c) != 0)
 | 
			
		||||
				break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return chain;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void process_chain(vector<Cell*> &chain)
 | 
			
		||||
	{
 | 
			
		||||
		if (GetSize(chain) < 2)
 | 
			
		||||
			return;
 | 
			
		||||
 | 
			
		||||
		int cursor = 0;
 | 
			
		||||
		while (cursor < GetSize(chain))
 | 
			
		||||
		{
 | 
			
		||||
			int cases = GetSize(chain) - cursor;
 | 
			
		||||
 | 
			
		||||
			Cell *first_cell = chain[cursor];
 | 
			
		||||
			dict<int, SigBit> taps_dict;
 | 
			
		||||
 | 
			
		||||
			if (cases < 2) {
 | 
			
		||||
				cursor++;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			Cell *last_cell = chain[cursor+cases-1];
 | 
			
		||||
 | 
			
		||||
			log("Converting %s.%s ... %s.%s to a pmux with %d cases.\n",
 | 
			
		||||
				log_id(module), log_id(first_cell), log_id(module), log_id(last_cell), cases);
 | 
			
		||||
 | 
			
		||||
			mux_count += cases;
 | 
			
		||||
			pmux_count += 1;
 | 
			
		||||
 | 
			
		||||
			first_cell->type = "$pmux";
 | 
			
		||||
			SigSpec b_sig = first_cell->getPort("\\B");
 | 
			
		||||
			SigSpec s_sig = first_cell->getPort("\\S");
 | 
			
		||||
 | 
			
		||||
			for (int i = 1; i < cases; i++) {
 | 
			
		||||
				Cell* prev_cell = chain[cursor+i-1];
 | 
			
		||||
				Cell* cursor_cell = chain[cursor+i];
 | 
			
		||||
				if (sigmap(prev_cell->getPort("\\Y")) == sigmap(cursor_cell->getPort("\\A"))) {
 | 
			
		||||
					b_sig.append(cursor_cell->getPort("\\B"));
 | 
			
		||||
					s_sig.append(cursor_cell->getPort("\\S"));
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					b_sig.append(cursor_cell->getPort("\\A"));
 | 
			
		||||
					s_sig.append(module->LogicNot(NEW_ID, cursor_cell->getPort("\\S")));
 | 
			
		||||
				}
 | 
			
		||||
				remove_cells.insert(cursor_cell);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			first_cell->setPort("\\B", b_sig);
 | 
			
		||||
			first_cell->setPort("\\S", s_sig);
 | 
			
		||||
			first_cell->setParam("\\S_WIDTH", GetSize(s_sig));
 | 
			
		||||
			first_cell->setPort("\\Y", last_cell->getPort("\\Y"));
 | 
			
		||||
 | 
			
		||||
			cursor += cases;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void cleanup()
 | 
			
		||||
	{
 | 
			
		||||
		for (auto cell : remove_cells)
 | 
			
		||||
			module->remove(cell);
 | 
			
		||||
 | 
			
		||||
		remove_cells.clear();
 | 
			
		||||
		sig_chain_next.clear();
 | 
			
		||||
		sig_chain_prev.clear();
 | 
			
		||||
		chain_start_cells.clear();
 | 
			
		||||
		candidate_cells.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	MuxpackWorker(Module *module) :
 | 
			
		||||
			module(module), sigmap(module), mux_count(0), pmux_count(0)
 | 
			
		||||
	{
 | 
			
		||||
		make_sig_chain_next_prev();
 | 
			
		||||
		find_chain_start_cells();
 | 
			
		||||
 | 
			
		||||
		for (auto c : chain_start_cells) {
 | 
			
		||||
			vector<Cell*> chain = create_chain(c);
 | 
			
		||||
			process_chain(chain);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		cleanup();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct MuxpackPass : public Pass {
 | 
			
		||||
	MuxpackPass() : Pass("muxpack", "$mux/$pmux cascades to $pmux") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    muxpack [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("This pass converts cascaded chains of $pmux cells (e.g. those create from case\n");
 | 
			
		||||
		log("constructs) and $mux cells (e.g. those created by if-else constructs) into \n");
 | 
			
		||||
		log("into $pmux cells.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing MUXPACK pass ($mux cell cascades to $pmux).\n");
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++)
 | 
			
		||||
		{
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		int mux_count = 0;
 | 
			
		||||
		int pmux_count = 0;
 | 
			
		||||
 | 
			
		||||
		for (auto module : design->selected_modules()) {
 | 
			
		||||
			MuxpackWorker worker(module);
 | 
			
		||||
			mux_count += worker.mux_count;
 | 
			
		||||
			pmux_count += worker.pmux_count;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		log("Converted %d (p)mux cells into %d pmux cells.\n", mux_count, pmux_count);
 | 
			
		||||
	}
 | 
			
		||||
} MuxpackPass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
| 
						 | 
				
			
			@ -1453,7 +1453,7 @@ struct AbcPass : public Pass {
 | 
			
		|||
		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 the load that into ABC externally if\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");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,7 @@
 | 
			
		|||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *  Copyright (C) 2019  Eddie Hung <eddie@fpgeh.com>
 | 
			
		||||
 *                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
 | 
			
		||||
| 
						 | 
				
			
			@ -22,18 +22,18 @@
 | 
			
		|||
// Berkeley Logic Synthesis and Verification Group, ABC: A System for Sequential Synthesis and Verification
 | 
			
		||||
// http://www.eecs.berkeley.edu/~alanmi/abc/
 | 
			
		||||
 | 
			
		||||
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
 | 
			
		||||
//#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; strash; dch -f; if; mfs2"
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; */"&retime; &dch -f; &ps -l; &if {W} -v; &ps -l"
 | 
			
		||||
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; strash; dch -f; cover {I} {P}"
 | 
			
		||||
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
#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"
 | 
			
		||||
#else
 | 
			
		||||
#define ABC_COMMAND_LUT "&st; &sweep; &scorr; "/*"&dc2; "*/"&retime; &dch -f; &ps -l; &if {W} {D} -v; "/*"&mfs; "*/"&ps -l"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define ABC_FAST_COMMAND_LIB "strash; dretime; map {D}"
 | 
			
		||||
#define ABC_FAST_COMMAND_CTR "strash; dretime; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
 | 
			
		||||
#define ABC_FAST_COMMAND_LUT "&st; &retime; &if"
 | 
			
		||||
#define ABC_FAST_COMMAND_SOP "strash; dretime; cover -I {I} -P {P}"
 | 
			
		||||
#define ABC_FAST_COMMAND_DFL "strash; dretime; map"
 | 
			
		||||
 | 
			
		||||
#define ABC_FAST_COMMAND_LUT "&st; &retime; &if {W}"
 | 
			
		||||
 | 
			
		||||
#include "kernel/register.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -61,17 +61,12 @@ extern "C" int Abc_RealMain(int argc, char *argv[]);
 | 
			
		|||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
bool map_mux4;
 | 
			
		||||
bool map_mux8;
 | 
			
		||||
bool map_mux16;
 | 
			
		||||
 | 
			
		||||
bool markgroups;
 | 
			
		||||
int map_autoidx;
 | 
			
		||||
SigMap assign_map;
 | 
			
		||||
RTLIL::Module *module;
 | 
			
		||||
std::map<RTLIL::SigBit, int> signal_map;
 | 
			
		||||
std::map<RTLIL::SigBit, RTLIL::State> signal_init;
 | 
			
		||||
pool<std::string> enabled_gates;
 | 
			
		||||
bool recover_init;
 | 
			
		||||
 | 
			
		||||
bool clk_polarity, en_polarity;
 | 
			
		||||
| 
						 | 
				
			
			@ -246,32 +241,9 @@ struct abc_output_filter
 | 
			
		|||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static std::pair<RTLIL::IdString, int> wideports_split(std::string name)
 | 
			
		||||
{
 | 
			
		||||
	int pos = -1;
 | 
			
		||||
 | 
			
		||||
	if (name.empty() || name.back() != ']')
 | 
			
		||||
		goto failed;
 | 
			
		||||
 | 
			
		||||
	for (int i = 0; i+1 < GetSize(name); i++) {
 | 
			
		||||
		if (name[i] == '[')
 | 
			
		||||
			pos = i;
 | 
			
		||||
		else if (name[i] < '0' || name[i] > '9')
 | 
			
		||||
			pos = -1;
 | 
			
		||||
		else if (i == pos+1 && name[i] == '0' && name[i+1] != ']')
 | 
			
		||||
			pos = -1;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (pos >= 0)
 | 
			
		||||
		return std::pair<RTLIL::IdString, int>(RTLIL::escape_id(name.substr(0, pos)), atoi(name.c_str() + pos+1));
 | 
			
		||||
 | 
			
		||||
failed:
 | 
			
		||||
	return std::pair<RTLIL::IdString, int>(name, 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::string script_file, std::string exe_file,
 | 
			
		||||
		std::string liberty_file, std::string constr_file, bool cleanup, vector<int> lut_costs, bool dff_mode, std::string clk_str,
 | 
			
		||||
		bool keepff, std::string delay_target, std::string sop_inputs, std::string sop_products, std::string lutin_shared, bool fast_mode,
 | 
			
		||||
		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,
 | 
			
		||||
		const std::vector<RTLIL::Cell*> &cells, bool show_tempdir, bool sop_mode, std::string box_file, std::string lut_file,
 | 
			
		||||
		std::string wire_delay)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -325,11 +297,6 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
 | 
			
		||||
	std::string abc_script;
 | 
			
		||||
 | 
			
		||||
	if (!liberty_file.empty()) {
 | 
			
		||||
		abc_script += stringf("read_lib -w %s; ", liberty_file.c_str());
 | 
			
		||||
		if (!constr_file.empty())
 | 
			
		||||
			abc_script += stringf("read_constr -v %s; ", constr_file.c_str());
 | 
			
		||||
	} else
 | 
			
		||||
	if (!lut_costs.empty()) {
 | 
			
		||||
		abc_script += stringf("read_lut %s/lutdefs.txt; ", tempdir_name.c_str());
 | 
			
		||||
		if (!box_file.empty())
 | 
			
		||||
| 
						 | 
				
			
			@ -342,7 +309,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			abc_script += stringf("read_box -v %s; ", box_file.c_str());
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		abc_script += stringf("read_library %s/stdcells.genlib; ", tempdir_name.c_str());
 | 
			
		||||
		log_abort();
 | 
			
		||||
 | 
			
		||||
	abc_script += stringf("&read %s/input.xaig; &ps; ", tempdir_name.c_str());
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -365,28 +332,18 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		abc_script += fast_mode ? ABC_FAST_COMMAND_LUT : ABC_COMMAND_LUT;
 | 
			
		||||
		//if (all_luts_cost_same && !fast_mode)
 | 
			
		||||
		//	abc_script += "; lutpack {S}";
 | 
			
		||||
	} else if (!liberty_file.empty())
 | 
			
		||||
		abc_script += constr_file.empty() ? (fast_mode ? ABC_FAST_COMMAND_LIB : ABC_COMMAND_LIB) : (fast_mode ? ABC_FAST_COMMAND_CTR : ABC_COMMAND_CTR);
 | 
			
		||||
	else if (sop_mode)
 | 
			
		||||
		abc_script += fast_mode ? ABC_FAST_COMMAND_SOP : ABC_COMMAND_SOP;
 | 
			
		||||
	else
 | 
			
		||||
		abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
 | 
			
		||||
	} else
 | 
			
		||||
		log_abort();
 | 
			
		||||
 | 
			
		||||
	if (script_file.empty() && !delay_target.empty())
 | 
			
		||||
		for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
 | 
			
		||||
			abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
 | 
			
		||||
	//if (script_file.empty() && !delay_target.empty())
 | 
			
		||||
	//	for (size_t pos = abc_script.find("dretime;"); pos != std::string::npos; pos = abc_script.find("dretime;", pos+1))
 | 
			
		||||
	//		abc_script = abc_script.substr(0, pos) + "dretime; retime -o {D};" + abc_script.substr(pos+8);
 | 
			
		||||
 | 
			
		||||
	for (size_t pos = abc_script.find("{D}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
 | 
			
		||||
		abc_script = abc_script.substr(0, pos) + delay_target + abc_script.substr(pos+3);
 | 
			
		||||
 | 
			
		||||
	for (size_t pos = abc_script.find("{I}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
 | 
			
		||||
		abc_script = abc_script.substr(0, pos) + sop_inputs + abc_script.substr(pos+3);
 | 
			
		||||
 | 
			
		||||
	for (size_t pos = abc_script.find("{P}"); pos != std::string::npos; pos = abc_script.find("{D}", pos))
 | 
			
		||||
		abc_script = abc_script.substr(0, pos) + sop_products + abc_script.substr(pos+3);
 | 
			
		||||
 | 
			
		||||
	for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
 | 
			
		||||
		abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
 | 
			
		||||
	//for (size_t pos = abc_script.find("{S}"); pos != std::string::npos; pos = abc_script.find("{S}", pos))
 | 
			
		||||
	//	abc_script = abc_script.substr(0, pos) + lutin_shared + abc_script.substr(pos+3);
 | 
			
		||||
 | 
			
		||||
	for (size_t pos = abc_script.find("{W}"); pos != std::string::npos; pos = abc_script.find("{W}", pos))
 | 
			
		||||
		abc_script = abc_script.substr(0, pos) + wire_delay + abc_script.substr(pos+3);
 | 
			
		||||
| 
						 | 
				
			
			@ -414,64 +371,77 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	design->selection_stack.emplace_back(false);
 | 
			
		||||
	RTLIL::Selection& sel = design->selection_stack.back();
 | 
			
		||||
	sel.select(module);
 | 
			
		||||
 | 
			
		||||
	// Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
 | 
			
		||||
	Pass::call(design, "setundef -zero");
 | 
			
		||||
 | 
			
		||||
	Pass::call(design, "aigmap");
 | 
			
		||||
 | 
			
		||||
	handle_loops(design);
 | 
			
		||||
 | 
			
		||||
	Pass::call(design, stringf("write_xaiger -O -map %s/input.sym %s/input.xaig; ", tempdir_name.c_str(), tempdir_name.c_str()));
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
	std::string buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
 | 
			
		||||
	std::ifstream ifs;
 | 
			
		||||
	ifs.open(buffer);
 | 
			
		||||
	if (ifs.fail())
 | 
			
		||||
		log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 | 
			
		||||
	buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
 | 
			
		||||
	log_assert(!design->module("$__abc9__"));
 | 
			
		||||
	AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
 | 
			
		||||
	reader.parse_xaiger();
 | 
			
		||||
	ifs.close();
 | 
			
		||||
	Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
 | 
			
		||||
	design->remove(design->module("$__abc9__"));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
	design->selection_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
	// 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("\\abc_scc_break");
 | 
			
		||||
		if (it != wire->attributes.end()) {
 | 
			
		||||
			wire->attributes.erase(it);
 | 
			
		||||
			log_assert(wire->port_output);
 | 
			
		||||
			wire->port_output = false;
 | 
			
		||||
			RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
 | 
			
		||||
			log_assert(i_wire);
 | 
			
		||||
			log_assert(i_wire->port_input);
 | 
			
		||||
			i_wire->port_input = false;
 | 
			
		||||
			module->connect(i_wire, wire);
 | 
			
		||||
	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;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	module->fixup_ports();
 | 
			
		||||
 | 
			
		||||
	//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);
 | 
			
		||||
 | 
			
		||||
	log_push();
 | 
			
		||||
 | 
			
		||||
	//if (count_output > 0)
 | 
			
		||||
	if (count_output)
 | 
			
		||||
	{
 | 
			
		||||
		design->selection_stack.emplace_back(false);
 | 
			
		||||
		RTLIL::Selection& sel = design->selection_stack.back();
 | 
			
		||||
		sel.select(module);
 | 
			
		||||
 | 
			
		||||
		// Behave as for "abc" where BLIF writer implicitly outputs all undef as zero
 | 
			
		||||
		Pass::call(design, "setundef -zero");
 | 
			
		||||
 | 
			
		||||
		Pass::call(design, "aigmap");
 | 
			
		||||
 | 
			
		||||
		handle_loops(design);
 | 
			
		||||
 | 
			
		||||
		//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
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.xaig");
 | 
			
		||||
		ifs.open(buffer);
 | 
			
		||||
		if (ifs.fail())
 | 
			
		||||
			log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
 | 
			
		||||
		log_assert(!design->module("$__abc9__"));
 | 
			
		||||
		{
 | 
			
		||||
			AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
			reader.parse_xaiger();
 | 
			
		||||
		}
 | 
			
		||||
		ifs.close();
 | 
			
		||||
		Pass::call(design, stringf("write_verilog -noexpr -norename %s/%s", tempdir_name.c_str(), "input.v"));
 | 
			
		||||
		design->remove(design->module("$__abc9__"));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		design->selection_stack.pop_back();
 | 
			
		||||
 | 
			
		||||
		// 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("\\abc_scc_break");
 | 
			
		||||
			if (it != wire->attributes.end()) {
 | 
			
		||||
				wire->attributes.erase(it);
 | 
			
		||||
				log_assert(wire->port_output);
 | 
			
		||||
				wire->port_output = false;
 | 
			
		||||
				RTLIL::Wire *i_wire = module->wire(wire->name.str() + ".abci");
 | 
			
		||||
				log_assert(i_wire);
 | 
			
		||||
				log_assert(i_wire->port_input);
 | 
			
		||||
				i_wire->port_input = false;
 | 
			
		||||
				module->connect(i_wire, wire);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		module->fixup_ports();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing ABC9.\n");
 | 
			
		||||
 | 
			
		||||
        std::string buffer;
 | 
			
		||||
		if (!lut_costs.empty()) {
 | 
			
		||||
			buffer = stringf("%s/lutdefs.txt", tempdir_name.c_str());
 | 
			
		||||
			f = fopen(buffer.c_str(), "wt");
 | 
			
		||||
| 
						 | 
				
			
			@ -507,16 +477,13 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			log_error("ABC: execution of command \"%s\" failed: return code %d.\n", buffer.c_str(), ret);
 | 
			
		||||
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "output.aig");
 | 
			
		||||
		std::ifstream ifs;
 | 
			
		||||
		ifs.open(buffer);
 | 
			
		||||
		if (ifs.fail())
 | 
			
		||||
			log_error("Can't open ABC output file `%s'.\n", buffer.c_str());
 | 
			
		||||
 | 
			
		||||
		bool builtin_lib = liberty_file.empty();
 | 
			
		||||
		//parse_blif(mapped_design, ifs, builtin_lib ? "\\DFF" : "\\_dff_", false, sop_mode);
 | 
			
		||||
		buffer = stringf("%s/%s", tempdir_name.c_str(), "input.sym");
 | 
			
		||||
		log_assert(!design->module("$__abc9__"));
 | 
			
		||||
		AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, false /* wideports */);
 | 
			
		||||
		AigerReader reader(design, ifs, "$__abc9__", "" /* clk_name */, buffer.c_str() /* map_filename */, true /* wideports */);
 | 
			
		||||
		reader.parse_xaiger();
 | 
			
		||||
		ifs.close();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -536,21 +503,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			if (markgroups) remap_wire->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
			if (w->port_output) {
 | 
			
		||||
				RTLIL::Wire *wire = module->wire(w->name);
 | 
			
		||||
				if (wire) {
 | 
			
		||||
					for (int i = 0; i < GetSize(wire); i++)
 | 
			
		||||
						output_bits.insert({wire, i});
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					// Attempt another wideports_split here because there
 | 
			
		||||
					// exists the possibility that different bits of a port
 | 
			
		||||
					// could be an input and output, therefore parse_xaiger()
 | 
			
		||||
					// could not combine it into a wideport
 | 
			
		||||
					auto r = wideports_split(w->name.str());
 | 
			
		||||
					wire = module->wire(r.first);
 | 
			
		||||
					log_assert(wire);
 | 
			
		||||
					int i = r.second;
 | 
			
		||||
				log_assert(wire);
 | 
			
		||||
				for (int i = 0; i < GetSize(wire); i++)
 | 
			
		||||
					output_bits.insert({wire, i});
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -584,66 +539,65 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
		std::map<std::string, int> cell_stats;
 | 
			
		||||
		for (auto c : mapped_mod->cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (builtin_lib)
 | 
			
		||||
			{
 | 
			
		||||
				if (c->type == "$_NOT_") {
 | 
			
		||||
					RTLIL::Cell *cell;
 | 
			
		||||
					RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
 | 
			
		||||
					RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
 | 
			
		||||
					if (!a_bit.wire) {
 | 
			
		||||
						c->setPort("\\Y", module->addWire(NEW_ID));
 | 
			
		||||
						module->connect(module->wires_[remap_name(y_bit.wire->name)], RTLIL::S1);
 | 
			
		||||
			if (c->type == "$_NOT_") {
 | 
			
		||||
				RTLIL::Cell *cell;
 | 
			
		||||
				RTLIL::SigBit a_bit = c->getPort("\\A").as_bit();
 | 
			
		||||
				RTLIL::SigBit y_bit = c->getPort("\\Y").as_bit();
 | 
			
		||||
				if (!a_bit.wire) {
 | 
			
		||||
					c->setPort("\\Y", module->addWire(NEW_ID));
 | 
			
		||||
					RTLIL::Wire *wire = module->wire(remap_name(y_bit.wire->name));
 | 
			
		||||
					log_assert(wire);
 | 
			
		||||
					module->connect(RTLIL::SigBit(wire, y_bit.offset), RTLIL::S1);
 | 
			
		||||
				}
 | 
			
		||||
				else if (!lut_costs.empty() || !lut_file.empty()) {
 | 
			
		||||
					RTLIL::Cell* driving_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
 | 
			
		||||
						// increase the max logic depth
 | 
			
		||||
						// (TODO: Optimise by not cloning unless will increase depth)
 | 
			
		||||
						RTLIL::IdString driver_name;
 | 
			
		||||
						if (GetSize(a_bit.wire) == 1)
 | 
			
		||||
							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);
 | 
			
		||||
					}
 | 
			
		||||
					else if (!lut_costs.empty() || !lut_file.empty()) {
 | 
			
		||||
						RTLIL::Cell* driving_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
 | 
			
		||||
							// increase the max logic depth
 | 
			
		||||
							// (TODO: Optimise by not cloning unless will increase depth)
 | 
			
		||||
							RTLIL::IdString driver_name;
 | 
			
		||||
							if (GetSize(a_bit.wire) == 1)
 | 
			
		||||
								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);
 | 
			
		||||
						}
 | 
			
		||||
 | 
			
		||||
						if (!driving_lut) {
 | 
			
		||||
							// If a driver couldn't be found (could be from PI,
 | 
			
		||||
							// or from a box) 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);
 | 
			
		||||
						}
 | 
			
		||||
						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);
 | 
			
		||||
						}
 | 
			
		||||
					if (!driving_lut) {
 | 
			
		||||
						// If a driver couldn't be found (could be from PI,
 | 
			
		||||
						// or from a box) 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);
 | 
			
		||||
					}
 | 
			
		||||
					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)]++;
 | 
			
		||||
						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);
 | 
			
		||||
					}
 | 
			
		||||
					if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
					continue;
 | 
			
		||||
				}
 | 
			
		||||
				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)]++;
 | 
			
		||||
				}
 | 
			
		||||
				if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
            cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
			cell_stats[RTLIL::unescape_id(c->type)]++;
 | 
			
		||||
 | 
			
		||||
			if (c->type == "$lut") {
 | 
			
		||||
				if (GetSize(c->getPort("\\A")) == 1 && c->getParam("\\LUT").as_int() == 2) {
 | 
			
		||||
| 
						 | 
				
			
			@ -654,10 +608,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
                auto it = erased_boxes.find(c->name);
 | 
			
		||||
                log_assert(it != erased_boxes.end());
 | 
			
		||||
                c->parameters = std::move(it->second);
 | 
			
		||||
            }
 | 
			
		||||
				auto it = erased_boxes.find(c->name);
 | 
			
		||||
				log_assert(it != erased_boxes.end());
 | 
			
		||||
				c->parameters = std::move(it->second);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			RTLIL::Cell* cell = module->addCell(remap_name(c->name), c->type);
 | 
			
		||||
			if (markgroups) cell->attributes["\\abcgroup"] = map_autoidx;
 | 
			
		||||
| 
						 | 
				
			
			@ -713,22 +667,9 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
			if (!w->port_input && !w->port_output)
 | 
			
		||||
				continue;
 | 
			
		||||
			RTLIL::Wire *wire = module->wire(w->name);
 | 
			
		||||
			log_assert(wire);
 | 
			
		||||
			RTLIL::Wire *remap_wire = module->wire(remap_name(w->name));
 | 
			
		||||
			RTLIL::SigSpec signal;
 | 
			
		||||
			if (wire) {
 | 
			
		||||
				signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				// Attempt another wideports_split here because there
 | 
			
		||||
				// exists the possibility that different bits of a port
 | 
			
		||||
				// could be an input and output, therefore parse_xaiger()
 | 
			
		||||
				// could not combine it into a wideport
 | 
			
		||||
				auto r = wideports_split(w->name.str());
 | 
			
		||||
				wire = module->wire(r.first);
 | 
			
		||||
				log_assert(wire);
 | 
			
		||||
				int i = r.second;
 | 
			
		||||
				signal = RTLIL::SigSpec(wire, i);
 | 
			
		||||
			}
 | 
			
		||||
			RTLIL::SigSpec signal = RTLIL::SigSpec(wire, 0, GetSize(remap_wire));
 | 
			
		||||
			log_assert(GetSize(signal) >= GetSize(remap_wire));
 | 
			
		||||
 | 
			
		||||
			log_assert(w->port_input || w->port_output);
 | 
			
		||||
| 
						 | 
				
			
			@ -753,10 +694,10 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
 | 
			
		||||
		design->remove(mapped_mod);
 | 
			
		||||
	}
 | 
			
		||||
	//else
 | 
			
		||||
	//{
 | 
			
		||||
	//	log("Don't call ABC as there is nothing to map.\n");
 | 
			
		||||
	//}
 | 
			
		||||
	else
 | 
			
		||||
	{
 | 
			
		||||
		log("Don't call ABC as there is nothing to map.\n");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (cleanup)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -768,7 +709,7 @@ void abc9_module(RTLIL::Design *design, RTLIL::Module *current_module, std::stri
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
struct Abc9Pass : public Pass {
 | 
			
		||||
	Abc9Pass() : Pass("abc9", "use ABC for technology mapping") { }
 | 
			
		||||
	Abc9Pass() : Pass("abc9", "use ABC9 for technology mapping") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
| 
						 | 
				
			
			@ -796,76 +737,30 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
		log("\n");
 | 
			
		||||
		log("        if no -script parameter is given, the following scripts are used:\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -liberty without -constr:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_LIB).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -liberty with -constr:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_CTR).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts (only one LUT size):\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT "; lutpack {S}").c_str());
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT /*"; lutpack {S}"*/).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts (different LUT sizes):\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_LUT).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -sop:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_SOP).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        otherwise:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_COMMAND_DFL).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 -liberty without -constr:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LIB).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -liberty with -constr:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_CTR).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -lut/-luts:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_LUT).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        for -sop:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_SOP).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        otherwise:\n");
 | 
			
		||||
		log("%s\n", fold_abc_cmd(ABC_FAST_COMMAND_DFL).c_str());
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -liberty <file>\n");
 | 
			
		||||
		log("        generate netlists for the specified cell library (using the liberty\n");
 | 
			
		||||
		log("        file format).\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -constr <file>\n");
 | 
			
		||||
		log("        pass this file with timing constraints to ABC. Use with -liberty.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        a constr file contains two lines:\n");
 | 
			
		||||
		log("            set_driving_cell <cell_name>\n");
 | 
			
		||||
		log("            set_load <floating_point_number>\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        the set_driving_cell statement defines which cell type is assumed to\n");
 | 
			
		||||
		log("        drive the primary inputs and the set_load statement sets the load in\n");
 | 
			
		||||
		log("        femtofarads for each primary output.\n");
 | 
			
		||||
		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("        this also replaces 'dretime' with 'dretime; retime -o {D}' in the\n");
 | 
			
		||||
		log("        default scripts above.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -I <num>\n");
 | 
			
		||||
		log("        maximum number of SOP inputs.\n");
 | 
			
		||||
		log("        (replaces {I} in the default scripts above)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -P <num>\n");
 | 
			
		||||
		log("        maximum number of SOP products.\n");
 | 
			
		||||
		log("        (replaces {P} in the 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("        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");
 | 
			
		||||
| 
						 | 
				
			
			@ -882,42 +777,19 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
		log("        generate netlist using luts. Use the specified costs for luts with 1,\n");
 | 
			
		||||
		log("        2, 3, .. inputs.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -sop\n");
 | 
			
		||||
		log("        map to sum-of-product cells and inverters\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		// log("    -mux4, -mux8, -mux16\n");
 | 
			
		||||
		// log("        try to extract 4-input, 8-input, and/or 16-input muxes\n");
 | 
			
		||||
		// log("        (ignored when used with -liberty or -lut)\n");
 | 
			
		||||
		// log("\n");
 | 
			
		||||
		log("    -g type1,type2,...\n");
 | 
			
		||||
		log("        Map to the specified list of gate types. Supported gates types are:\n");
 | 
			
		||||
		log("        AND, NAND, OR, NOR, XOR, XNOR, ANDNOT, ORNOT, MUX, AOI3, OAI3, AOI4, OAI4.\n");
 | 
			
		||||
		log("        (The NOT gate is always added to this list automatically.)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        The following aliases can be used to reference common sets of gate types:\n");
 | 
			
		||||
		log("          simple: AND OR XOR MUX\n");
 | 
			
		||||
		log("          cmos2: NAND NOR\n");
 | 
			
		||||
		log("          cmos3: NAND NOR AOI3 OAI3\n");
 | 
			
		||||
		log("          cmos4: NAND NOR AOI3 OAI3 AOI4 OAI4\n");
 | 
			
		||||
		log("          gates: AND NAND OR NOR XOR XNOR ANDNOT ORNOT\n");
 | 
			
		||||
		log("          aig: AND NAND OR NOR ANDNOT ORNOT\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("        Prefix a gate type with a '-' to remove it from the list. For example\n");
 | 
			
		||||
		log("        the arguments 'AND,OR,XOR' and 'simple,-MUX' are equivalent.\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("    -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");
 | 
			
		||||
| 
						 | 
				
			
			@ -934,14 +806,11 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
		log("    -box <file>\n");
 | 
			
		||||
		log("        pass this file with box library to ABC. Use with -lut.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("When neither -liberty nor -lut is used, the Yosys standard cell library is\n");
 | 
			
		||||
		log("loaded into ABC before the ABC script is executed.\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 the load that into ABC externally if\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");
 | 
			
		||||
| 
						 | 
				
			
			@ -949,7 +818,7 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing ABC9 pass (technology mapping using ABC).\n");
 | 
			
		||||
		log_header(design, "Executing ABC9 pass (technology mapping using ABC9).\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
		assign_map.clear();
 | 
			
		||||
| 
						 | 
				
			
			@ -963,8 +832,8 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
#else
 | 
			
		||||
		std::string exe_file = proc_self_dirname() + "yosys-abc";
 | 
			
		||||
#endif
 | 
			
		||||
		std::string script_file, liberty_file, constr_file, clk_str, box_file, lut_file;
 | 
			
		||||
		std::string delay_target, sop_inputs, sop_products, lutin_shared = "-S 1", wire_delay;
 | 
			
		||||
		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;
 | 
			
		||||
		bool show_tempdir = false, sop_mode = false;
 | 
			
		||||
		vector<int> lut_costs;
 | 
			
		||||
| 
						 | 
				
			
			@ -975,11 +844,6 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
		show_tempdir = true;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
		map_mux4 = false;
 | 
			
		||||
		map_mux8 = false;
 | 
			
		||||
		map_mux16 = false;
 | 
			
		||||
		enabled_gates.clear();
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#ifndef ABCEXTERNAL
 | 
			
		||||
		if (!check_file_exists(exe_file + ".exe") && check_file_exists(proc_self_dirname() + "..\\yosys-abc.exe"))
 | 
			
		||||
| 
						 | 
				
			
			@ -1006,36 +870,14 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
					script_file = std::string(pwd) + "/" + script_file;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-liberty" && argidx+1 < args.size()) {
 | 
			
		||||
				liberty_file = args[++argidx];
 | 
			
		||||
				rewrite_filename(liberty_file);
 | 
			
		||||
				if (!liberty_file.empty() && !is_absolute_path(liberty_file))
 | 
			
		||||
					liberty_file = std::string(pwd) + "/" + liberty_file;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-constr" && argidx+1 < args.size()) {
 | 
			
		||||
				constr_file = args[++argidx];
 | 
			
		||||
				rewrite_filename(constr_file);
 | 
			
		||||
				if (!constr_file.empty() && !is_absolute_path(constr_file))
 | 
			
		||||
					constr_file = std::string(pwd) + "/" + constr_file;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-D" && argidx+1 < args.size()) {
 | 
			
		||||
				delay_target = "-D " + args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-I" && argidx+1 < args.size()) {
 | 
			
		||||
				sop_inputs = "-I " + args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-P" && argidx+1 < args.size()) {
 | 
			
		||||
				sop_products = "-P " + args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-S" && argidx+1 < args.size()) {
 | 
			
		||||
				lutin_shared = "-S " + args[++argidx];
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			//if (arg == "-S" && argidx+1 < args.size()) {
 | 
			
		||||
			//	lutin_shared = "-S " + args[++argidx];
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			if (arg == "-lut" && argidx+1 < args.size()) {
 | 
			
		||||
				string arg = args[++argidx];
 | 
			
		||||
				size_t pos = arg.find_first_of(':');
 | 
			
		||||
| 
						 | 
				
			
			@ -1079,126 +921,23 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-sop") {
 | 
			
		||||
				sop_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-mux4") {
 | 
			
		||||
				map_mux4 = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-mux8") {
 | 
			
		||||
				map_mux8 = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-mux16") {
 | 
			
		||||
				map_mux16 = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-dress") {
 | 
			
		||||
				// TODO
 | 
			
		||||
				//abc_dress = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-g" && argidx+1 < args.size()) {
 | 
			
		||||
				for (auto g : split_tokens(args[++argidx], ",")) {
 | 
			
		||||
					vector<string> gate_list;
 | 
			
		||||
					bool remove_gates = false;
 | 
			
		||||
					if (GetSize(g) > 0 && g[0] == '-') {
 | 
			
		||||
						remove_gates = true;
 | 
			
		||||
						g = g.substr(1);
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "AND") goto ok_gate;
 | 
			
		||||
					if (g == "NAND") goto ok_gate;
 | 
			
		||||
					if (g == "OR") goto ok_gate;
 | 
			
		||||
					if (g == "NOR") goto ok_gate;
 | 
			
		||||
					if (g == "XOR") goto ok_gate;
 | 
			
		||||
					if (g == "XNOR") goto ok_gate;
 | 
			
		||||
					if (g == "ANDNOT") goto ok_gate;
 | 
			
		||||
					if (g == "ORNOT") goto ok_gate;
 | 
			
		||||
					if (g == "MUX") goto ok_gate;
 | 
			
		||||
					if (g == "AOI3") goto ok_gate;
 | 
			
		||||
					if (g == "OAI3") goto ok_gate;
 | 
			
		||||
					if (g == "AOI4") goto ok_gate;
 | 
			
		||||
					if (g == "OAI4") goto ok_gate;
 | 
			
		||||
					if (g == "simple") {
 | 
			
		||||
						gate_list.push_back("AND");
 | 
			
		||||
						gate_list.push_back("OR");
 | 
			
		||||
						gate_list.push_back("XOR");
 | 
			
		||||
						gate_list.push_back("MUX");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "cmos2") {
 | 
			
		||||
						gate_list.push_back("NAND");
 | 
			
		||||
						gate_list.push_back("NOR");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "cmos3") {
 | 
			
		||||
						gate_list.push_back("NAND");
 | 
			
		||||
						gate_list.push_back("NOR");
 | 
			
		||||
						gate_list.push_back("AOI3");
 | 
			
		||||
						gate_list.push_back("OAI3");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "cmos4") {
 | 
			
		||||
						gate_list.push_back("NAND");
 | 
			
		||||
						gate_list.push_back("NOR");
 | 
			
		||||
						gate_list.push_back("AOI3");
 | 
			
		||||
						gate_list.push_back("OAI3");
 | 
			
		||||
						gate_list.push_back("AOI4");
 | 
			
		||||
						gate_list.push_back("OAI4");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "gates") {
 | 
			
		||||
						gate_list.push_back("AND");
 | 
			
		||||
						gate_list.push_back("NAND");
 | 
			
		||||
						gate_list.push_back("OR");
 | 
			
		||||
						gate_list.push_back("NOR");
 | 
			
		||||
						gate_list.push_back("XOR");
 | 
			
		||||
						gate_list.push_back("XNOR");
 | 
			
		||||
						gate_list.push_back("ANDNOT");
 | 
			
		||||
						gate_list.push_back("ORNOT");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					if (g == "aig") {
 | 
			
		||||
						gate_list.push_back("AND");
 | 
			
		||||
						gate_list.push_back("NAND");
 | 
			
		||||
						gate_list.push_back("OR");
 | 
			
		||||
						gate_list.push_back("NOR");
 | 
			
		||||
						gate_list.push_back("ANDNOT");
 | 
			
		||||
						gate_list.push_back("ORNOT");
 | 
			
		||||
						goto ok_alias;
 | 
			
		||||
					}
 | 
			
		||||
					cmd_error(args, argidx, stringf("Unsupported gate type: %s", g.c_str()));
 | 
			
		||||
				ok_gate:
 | 
			
		||||
					gate_list.push_back(g);
 | 
			
		||||
				ok_alias:
 | 
			
		||||
					for (auto gate : gate_list) {
 | 
			
		||||
						if (remove_gates)
 | 
			
		||||
							enabled_gates.erase(gate);
 | 
			
		||||
						else
 | 
			
		||||
							enabled_gates.insert(gate);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-fast") {
 | 
			
		||||
				fast_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-dff") {
 | 
			
		||||
				dff_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-clk" && argidx+1 < args.size()) {
 | 
			
		||||
				clk_str = args[++argidx];
 | 
			
		||||
				dff_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (arg == "-keepff") {
 | 
			
		||||
				keepff = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			//if (arg == "-dff") {
 | 
			
		||||
			//	dff_mode = true;
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			//if (arg == "-clk" && argidx+1 < args.size()) {
 | 
			
		||||
			//	clk_str = args[++argidx];
 | 
			
		||||
			//	dff_mode = true;
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			//if (arg == "-keepff") {
 | 
			
		||||
			//	keepff = true;
 | 
			
		||||
			//	continue;
 | 
			
		||||
			//}
 | 
			
		||||
			if (arg == "-nocleanup") {
 | 
			
		||||
				cleanup = false;
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -1226,11 +965,6 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		if ((!lut_costs.empty() || !lut_file.empty()) && !liberty_file.empty())
 | 
			
		||||
			log_cmd_error("Got -lut and -liberty! This two options are exclusive.\n");
 | 
			
		||||
		if (!constr_file.empty() && liberty_file.empty())
 | 
			
		||||
			log_cmd_error("Got -constr but no -liberty!\n");
 | 
			
		||||
 | 
			
		||||
		for (auto mod : design->selected_modules())
 | 
			
		||||
		{
 | 
			
		||||
			if (mod->attributes.count("\\abc_box_id"))
 | 
			
		||||
| 
						 | 
				
			
			@ -1262,8 +996,8 @@ struct Abc9Pass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
 | 
			
		||||
			if (!dff_mode || !clk_str.empty()) {
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, liberty_file, constr_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
 | 
			
		||||
						delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, dff_mode, clk_str, keepff,
 | 
			
		||||
						delay_target, lutin_shared, fast_mode, mod->selected_cells(), show_tempdir, sop_mode,
 | 
			
		||||
						box_file, lut_file, wire_delay);
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -1408,8 +1142,8 @@ struct Abc9Pass : 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, liberty_file, constr_file, cleanup, lut_costs, !clk_sig.empty(), "$",
 | 
			
		||||
						keepff, delay_target, sop_inputs, sop_products, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
 | 
			
		||||
				abc9_module(design, mod, script_file, exe_file, cleanup, lut_costs, !clk_sig.empty(), "$",
 | 
			
		||||
						keepff, delay_target, lutin_shared, fast_mode, it.second, show_tempdir, sop_mode,
 | 
			
		||||
						box_file, lut_file, wire_delay);
 | 
			
		||||
				assign_map.set(mod);
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -293,13 +293,10 @@ struct ShregmapWorker
 | 
			
		|||
 | 
			
		||||
				if (opts.init || sigbit_init.count(q_bit) == 0)
 | 
			
		||||
				{
 | 
			
		||||
					auto r = sigbit_chain_next.insert(std::make_pair(d_bit, cell));
 | 
			
		||||
					if (!r.second) {
 | 
			
		||||
					if (sigbit_chain_next.count(d_bit)) {
 | 
			
		||||
						sigbit_with_non_chain_users.insert(d_bit);
 | 
			
		||||
						Wire *wire = module->addWire(NEW_ID);
 | 
			
		||||
						module->connect(wire, d_bit);
 | 
			
		||||
						sigbit_chain_next.insert(std::make_pair(wire, cell));
 | 
			
		||||
					}
 | 
			
		||||
					} else
 | 
			
		||||
						sigbit_chain_next[d_bit] = cell;
 | 
			
		||||
 | 
			
		||||
					sigbit_chain_prev[q_bit] = cell;
 | 
			
		||||
					continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,7 +76,7 @@ struct SynthPass : public ScriptPass
 | 
			
		|||
		log("        synonymous to the end of the command list.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -abc9\n");
 | 
			
		||||
		log("        use abc9 instead of abc\n");
 | 
			
		||||
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("The following commands are executed by this synthesis command:\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -174,6 +174,9 @@ struct SynthPass : public ScriptPass
 | 
			
		|||
		if (!design->full_selection())
 | 
			
		||||
			log_cmd_error("This command only operates on fully selected designs!\n");
 | 
			
		||||
 | 
			
		||||
		if (abc == "abc9" && !lut)
 | 
			
		||||
			log_cmd_error("ABC9 flow only supported for FPGA synthesis (using '-lut' option)");
 | 
			
		||||
 | 
			
		||||
		log_header(design, "Executing SYNTH pass.\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,6 +11,9 @@ $(eval $(call add_share_file,share/ecp5,techlibs/ecp5/bram.txt))
 | 
			
		|||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/arith_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/latches_map.v))
 | 
			
		||||
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.box))
 | 
			
		||||
$(eval $(call add_share_file,share/ecp5,techlibs/ecp5/abc_5g.lut))
 | 
			
		||||
 | 
			
		||||
EXTRA_OBJS += techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
 | 
			
		||||
.SECONDARY: techlibs/ecp5/brams_init.mk techlibs/ecp5/brams_connect.mk
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										36
									
								
								techlibs/ecp5/abc_5g.box
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								techlibs/ecp5/abc_5g.box
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,36 @@
 | 
			
		|||
# Box 1 : CCU2C (2xCARRY + 2xLUT4)
 | 
			
		||||
# Outputs: S0, S1, COUT
 | 
			
		||||
# name  ID   w/b   ins    outs
 | 
			
		||||
CCU2C   1      1   9      3
 | 
			
		||||
 | 
			
		||||
#A0   A1   B0   B1   C0    C1  D0   D1   CIN
 | 
			
		||||
379  -    379  -    275   -    141  -    257
 | 
			
		||||
630  379  630  379  526   275  392  141  273
 | 
			
		||||
516  516  516  516  412   412  278  278  43
 | 
			
		||||
 | 
			
		||||
# Box 2 : TRELLIS_DPR16X4 (16x4 dist ram)
 | 
			
		||||
# Outputs: DO0, DO1, DO2, DO3, DO4
 | 
			
		||||
# name            ID  w/b   ins   outs
 | 
			
		||||
TRELLIS_DPR16X4   2     0   14    4
 | 
			
		||||
 | 
			
		||||
#DI0   DI1   DI2   DI3   RAD0   RAD1   RAD2   RAD3   WAD0    WAD1   WAD2   WAD3  WCK   WRE
 | 
			
		||||
-      -     -     -     141    379    275    379    -       -      -      -     -     -
 | 
			
		||||
-      -     -     -     141    379    275    379    -       -      -      -     -     -
 | 
			
		||||
-      -     -     -     141    379    275    379    -       -      -      -     -     -
 | 
			
		||||
-      -     -     -     141    379    275    379    -       -      -      -     -     -
 | 
			
		||||
 | 
			
		||||
# Box 3 : PFUMX (MUX2)
 | 
			
		||||
# Outputs: Z
 | 
			
		||||
# name  ID   w/b   ins    outs
 | 
			
		||||
PFUMX   3    1     3      1
 | 
			
		||||
 | 
			
		||||
#ALUT  BLUT  C0
 | 
			
		||||
98     98    151
 | 
			
		||||
 | 
			
		||||
# Box 4 : L6MUX21 (MUX2)
 | 
			
		||||
# Outputs: Z
 | 
			
		||||
# name   ID   w/b   ins    outs
 | 
			
		||||
L6MUX21  4    1     3      1
 | 
			
		||||
 | 
			
		||||
#D0    D1    SD
 | 
			
		||||
140    141   148
 | 
			
		||||
							
								
								
									
										25
									
								
								techlibs/ecp5/abc_5g.lut
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								techlibs/ecp5/abc_5g.lut
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
# ECP5-5G LUT library for ABC
 | 
			
		||||
# Note that ECP5 architecture assigns difference
 | 
			
		||||
# in LUT input delay to interconnect, so this is
 | 
			
		||||
# considered too
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Simple LUTs
 | 
			
		||||
#  area  D    C    B    A
 | 
			
		||||
1  1     141
 | 
			
		||||
2  1     141  275
 | 
			
		||||
3  1     141  275  379
 | 
			
		||||
4  1     141  275  379  379
 | 
			
		||||
 | 
			
		||||
# LUT5 = 2x LUT4 + PFUMX
 | 
			
		||||
#  area  M0   D    C    B    A
 | 
			
		||||
5  2     151  239  373  477  477
 | 
			
		||||
 | 
			
		||||
# LUT6 = 2x LUT5 + MUX2
 | 
			
		||||
#  area  M1   M0   D    C    B    A
 | 
			
		||||
6  4     148  292  380  514  618  618
 | 
			
		||||
 | 
			
		||||
# LUT7 = 2x LUT6 + MUX2
 | 
			
		||||
#  area  M2   M1   M0   D    C    B    A
 | 
			
		||||
7  8     148  289  433  521  655  759  759
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -70,80 +70,107 @@ module \$lut (A, Y);
 | 
			
		|||
    parameter WIDTH = 0;
 | 
			
		||||
    parameter LUT = 0;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // Need to swap input ordering, and fix init accordingly,
 | 
			
		||||
    // to match ABC's expectation of LUT inputs in non-decreasing
 | 
			
		||||
    // delay order
 | 
			
		||||
    localparam P_WIDTH = WIDTH < 4 ? 4 : WIDTH;
 | 
			
		||||
    function [P_WIDTH-1:0] permute_index;
 | 
			
		||||
        input [P_WIDTH-1:0] i;
 | 
			
		||||
        integer j;
 | 
			
		||||
        begin
 | 
			
		||||
            permute_index = 0;
 | 
			
		||||
            for (j = 0; j < P_WIDTH; j = j + 1)
 | 
			
		||||
                permute_index[P_WIDTH-1 - j] = i[j];
 | 
			
		||||
        end
 | 
			
		||||
    endfunction
 | 
			
		||||
 | 
			
		||||
    function [2**P_WIDTH-1:0] permute_init;
 | 
			
		||||
        input [2**P_WIDTH-1:0] orig;
 | 
			
		||||
        integer i;
 | 
			
		||||
        begin
 | 
			
		||||
            permute_init = 0;
 | 
			
		||||
            for (i = 0; i < 2**P_WIDTH; i = i + 1)
 | 
			
		||||
                permute_init[i] = orig[permute_index(i)];
 | 
			
		||||
        end
 | 
			
		||||
    endfunction
 | 
			
		||||
 | 
			
		||||
    parameter [2**P_WIDTH-1:0] P_LUT = permute_init(LUT);
 | 
			
		||||
 | 
			
		||||
    input [WIDTH-1:0] A;
 | 
			
		||||
    output Y;
 | 
			
		||||
 | 
			
		||||
    generate
 | 
			
		||||
        if (WIDTH == 1) begin
 | 
			
		||||
            LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(A[0]), .B(1'b0), .C(1'b0), .D(1'b0));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(1'b0), .B(1'b0), .C(1'b0), .D(A[0]));
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 2) begin
 | 
			
		||||
            LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(1'b0), .D(1'b0));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(1'b0), .B(1'b0), .C(A[1]), .D(A[0]));
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 3) begin
 | 
			
		||||
            LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(1'b0));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(1'b0), .B(A[2]), .C(A[1]), .D(A[0]));
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 4) begin
 | 
			
		||||
            LUT4 #(.INIT(LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT)) _TECHMAP_REPLACE_ (.Z(Y),
 | 
			
		||||
                .A(A[3]), .B(A[2]), .C(A[1]), .D(A[0]));
 | 
			
		||||
        `ifndef NO_PFUMUX
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 5) begin
 | 
			
		||||
            wire f0, f1;
 | 
			
		||||
            LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(Y));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[4]), .B(A[3]), .C(A[2]), .D(A[1]));
 | 
			
		||||
            PFUMX mux5(.ALUT(f1), .BLUT(f0), .C0(A[0]), .Z(Y));
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 6) begin
 | 
			
		||||
            wire f0, f1, f2, f3, g0, g1;
 | 
			
		||||
            LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
 | 
			
		||||
 | 
			
		||||
            LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2),
 | 
			
		||||
                .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3),
 | 
			
		||||
                .A(A[5]), .B(A[4]), .C(A[3]), .D(A[2]));
 | 
			
		||||
 | 
			
		||||
            PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
 | 
			
		||||
            PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
 | 
			
		||||
            L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[5]), .Z(Y));
 | 
			
		||||
            PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[1]), .Z(g0));
 | 
			
		||||
            PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[1]), .Z(g1));
 | 
			
		||||
            L6MUX21 mux6 (.D0(g0), .D1(g1), .SD(A[0]), .Z(Y));
 | 
			
		||||
        end else
 | 
			
		||||
        if (WIDTH == 7) begin
 | 
			
		||||
            wire f0, f1, f2, f3, f4, f5, f6, f7, g0, g1, g2, g3, h0, h1;
 | 
			
		||||
            LUT4 #(.INIT(LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[15: 0])) lut0 (.Z(f0),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[31:16])) lut1 (.Z(f1),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
 | 
			
		||||
            LUT4 #(.INIT(LUT[47:32])) lut2 (.Z(f2),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[63:48])) lut3 (.Z(f3),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[47:32])) lut2 (.Z(f2),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[63:48])) lut3 (.Z(f3),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
 | 
			
		||||
            LUT4 #(.INIT(LUT[79:64])) lut4 (.Z(f4),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[95:80])) lut5 (.Z(f5),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[79:64])) lut4 (.Z(f4),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[95:80])) lut5 (.Z(f5),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
 | 
			
		||||
            LUT4 #(.INIT(LUT[111: 96])) lut6 (.Z(f6),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(LUT[127:112])) lut7 (.Z(f7),
 | 
			
		||||
                .A(A[0]), .B(A[1]), .C(A[2]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[111: 96])) lut6 (.Z(f6),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
            LUT4 #(.INIT(P_LUT[127:112])) lut7 (.Z(f7),
 | 
			
		||||
                .A(A[6]), .B(A[5]), .C(A[4]), .D(A[3]));
 | 
			
		||||
 | 
			
		||||
            PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[4]), .Z(g0));
 | 
			
		||||
            PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[4]), .Z(g1));
 | 
			
		||||
            PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[4]), .Z(g2));
 | 
			
		||||
            PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[4]), .Z(g3));
 | 
			
		||||
            L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[5]), .Z(h0));
 | 
			
		||||
            L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[5]), .Z(h1));
 | 
			
		||||
            L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[6]), .Z(Y));
 | 
			
		||||
            PFUMX mux50(.ALUT(f1), .BLUT(f0), .C0(A[2]), .Z(g0));
 | 
			
		||||
            PFUMX mux51(.ALUT(f3), .BLUT(f2), .C0(A[2]), .Z(g1));
 | 
			
		||||
            PFUMX mux52(.ALUT(f5), .BLUT(f4), .C0(A[2]), .Z(g2));
 | 
			
		||||
            PFUMX mux53(.ALUT(f7), .BLUT(f6), .C0(A[2]), .Z(g3));
 | 
			
		||||
            L6MUX21 mux60 (.D0(g0), .D1(g1), .SD(A[1]), .Z(h0));
 | 
			
		||||
            L6MUX21 mux61 (.D0(g2), .D1(g3), .SD(A[1]), .Z(h1));
 | 
			
		||||
            L6MUX21 mux7  (.D0(h0), .D1(h1), .SD(A[0]), .Z(Y));
 | 
			
		||||
        `endif
 | 
			
		||||
        end else begin
 | 
			
		||||
            wire _TECHMAP_FAIL_ = 1;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,15 +9,17 @@ module LUT4(input A, B, C, D, output Z);
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------
 | 
			
		||||
 | 
			
		||||
(* abc_box_id=4, lib_whitebox *)
 | 
			
		||||
module L6MUX21 (input D0, D1, SD, output Z);
 | 
			
		||||
	assign Z = SD ? D1 : D0;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------
 | 
			
		||||
 | 
			
		||||
module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
 | 
			
		||||
	           output S0, S1, COUT);
 | 
			
		||||
(* abc_box_id=1, abc_carry, lib_whitebox *)
 | 
			
		||||
module CCU2C((* abc_carry_in *) input CIN,
 | 
			
		||||
			   input A0, B0, C0, D0, A1, B1, C1, D1,
 | 
			
		||||
	           output S0, S1,
 | 
			
		||||
	         (* abc_carry_out *) output COUT);
 | 
			
		||||
 | 
			
		||||
	parameter [15:0] INIT0 = 16'h0000;
 | 
			
		||||
	parameter [15:0] INIT1 = 16'h0000;
 | 
			
		||||
| 
						 | 
				
			
			@ -26,9 +28,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
 | 
			
		|||
 | 
			
		||||
	// First half
 | 
			
		||||
	wire LUT4_0, LUT2_0;
 | 
			
		||||
`ifdef _ABC
 | 
			
		||||
	assign LUT4_0 = INIT0[{D0, C0, B0, A0}];
 | 
			
		||||
	assign LUT2_0 = INIT0[{2'b00, B0, A0}];
 | 
			
		||||
`else
 | 
			
		||||
	LUT4 #(.INIT(INIT0)) lut4_0(.A(A0), .B(B0), .C(C0), .D(D0), .Z(LUT4_0));
 | 
			
		||||
	LUT2 #(.INIT(INIT0[3:0])) lut2_0(.A(A0), .B(B0), .Z(LUT2_0));
 | 
			
		||||
 | 
			
		||||
`endif
 | 
			
		||||
	wire gated_cin_0 = (INJECT1_0 == "YES") ? 1'b0 : CIN;
 | 
			
		||||
	assign S0 = LUT4_0 ^ gated_cin_0;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -37,9 +43,13 @@ module CCU2C(input CIN, A0, B0, C0, D0, A1, B1, C1, D1,
 | 
			
		|||
 | 
			
		||||
	// Second half
 | 
			
		||||
	wire LUT4_1, LUT2_1;
 | 
			
		||||
`ifdef _ABC
 | 
			
		||||
	assign LUT4_1 = INIT1[{D1, C1, B1, A1}];
 | 
			
		||||
	assign LUT2_1 = INIT1[{2'b00, B1, A1}];
 | 
			
		||||
`else
 | 
			
		||||
	LUT4 #(.INIT(INIT1)) lut4_1(.A(A1), .B(B1), .C(C1), .D(D1), .Z(LUT4_1));
 | 
			
		||||
	LUT2 #(.INIT(INIT1[3:0])) lut2_1(.A(A1), .B(B1), .Z(LUT2_1));
 | 
			
		||||
 | 
			
		||||
`endif
 | 
			
		||||
	wire gated_cin_1 = (INJECT1_1 == "YES") ? 1'b0 : cout_0;
 | 
			
		||||
	assign S1 = LUT4_1 ^ gated_cin_1;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -90,13 +100,13 @@ module TRELLIS_RAM16X2 (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------
 | 
			
		||||
 | 
			
		||||
(* abc_box_id=3, lib_whitebox *)
 | 
			
		||||
module PFUMX (input ALUT, BLUT, C0, output Z);
 | 
			
		||||
	assign Z = C0 ? ALUT : BLUT;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
// ---------------------------------------
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id=2 *)
 | 
			
		||||
module TRELLIS_DPR16X4 (
 | 
			
		||||
	input [3:0] DI,
 | 
			
		||||
	input [3:0] WAD,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,6 +82,9 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
		log("    -abc2\n");
 | 
			
		||||
		log("        run two passes of 'abc' for slightly improved logic density\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -abc9\n");
 | 
			
		||||
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -vpr\n");
 | 
			
		||||
		log("        generate an output netlist (and BLIF file) suitable for VPR\n");
 | 
			
		||||
		log("        (this feature is experimental and incomplete)\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +96,7 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	string top_opt, blif_file, edif_file, json_file;
 | 
			
		||||
	bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, vpr;
 | 
			
		||||
	bool noccu2, nodffe, nobram, nodram, nomux, flatten, retime, abc2, abc9, vpr;
 | 
			
		||||
 | 
			
		||||
	void clear_flags() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -110,6 +113,7 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
		retime = false;
 | 
			
		||||
		abc2 = false;
 | 
			
		||||
		vpr = false;
 | 
			
		||||
		abc9 = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +188,10 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
				vpr = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-abc9") {
 | 
			
		||||
				abc9 = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +211,7 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
	{
 | 
			
		||||
		if (check_label("begin"))
 | 
			
		||||
		{
 | 
			
		||||
			run("read_verilog -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
 | 
			
		||||
			run("read_verilog -D_ABC -lib +/ecp5/cells_sim.v +/ecp5/cells_bb.v");
 | 
			
		||||
			run(stringf("hierarchy -check %s", help_mode ? "-top <top>" : top_opt.c_str()));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -264,10 +272,15 @@ struct SynthEcp5Pass : public ScriptPass
 | 
			
		|||
				run("abc", "      (only if -abc2)");
 | 
			
		||||
			}
 | 
			
		||||
			run("techmap -map +/ecp5/latches_map.v");
 | 
			
		||||
			if (nomux)
 | 
			
		||||
				run("abc -lut 4 -dress");
 | 
			
		||||
			else
 | 
			
		||||
				run("abc -lut 4:7 -dress");
 | 
			
		||||
			if (abc9) {
 | 
			
		||||
				run("abc9 -lut +/ecp5/abc_5g.lut -box +/ecp5/abc_5g.box -W 200");
 | 
			
		||||
			} else {
 | 
			
		||||
				if (nomux)
 | 
			
		||||
					run("abc -lut 4 -dress");
 | 
			
		||||
				else
 | 
			
		||||
					run("abc -lut 4:7 -dress");
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			run("clean");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -110,4 +110,4 @@ SB_CARRY 21 1 3 1
 | 
			
		|||
# Inputs: I0 I1 I2 I3
 | 
			
		||||
# Outputs: O
 | 
			
		||||
SB_LUT4 22 1 4 1
 | 
			
		||||
465 558 589 661
 | 
			
		||||
661 589 558 465
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,8 +143,7 @@ endmodule
 | 
			
		|||
 | 
			
		||||
// Positive Edge SiliconBlue FF Cells
 | 
			
		||||
 | 
			
		||||
(* abc_box_id = 1, abc_flop, lib_whitebox *)
 | 
			
		||||
module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFF (output `SB_DFF_REG, input C, D);
 | 
			
		||||
`ifndef _ABC
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		Q <= D;
 | 
			
		||||
| 
						 | 
				
			
			@ -153,15 +152,13 @@ module SB_DFF ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) in
 | 
			
		|||
`endif
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 2, abc_flop *)
 | 
			
		||||
module SB_DFFE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFE (output `SB_DFF_REG, input C, E, D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E)
 | 
			
		||||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 3, abc_flop *)
 | 
			
		||||
module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -169,8 +166,7 @@ module SB_DFFSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 4, abc_flop *)
 | 
			
		||||
module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
	always @(posedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -178,8 +174,7 @@ module SB_DFFR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 5, abc_flop *)
 | 
			
		||||
module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -187,8 +182,7 @@ module SB_DFFSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 6, abc_flop *)
 | 
			
		||||
module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
	always @(posedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -196,8 +190,7 @@ module SB_DFFS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 7, abc_flop *)
 | 
			
		||||
module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (R)
 | 
			
		||||
| 
						 | 
				
			
			@ -207,8 +200,7 @@ module SB_DFFESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flo
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 8, abc_flop *)
 | 
			
		||||
module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
	always @(posedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -216,8 +208,7 @@ module SB_DFFER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 9, abc_flop *)
 | 
			
		||||
module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
	always @(posedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (S)
 | 
			
		||||
| 
						 | 
				
			
			@ -227,8 +218,7 @@ module SB_DFFESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flo
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 10, abc_flop *)
 | 
			
		||||
module SB_DFFES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFES (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
	always @(posedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -238,21 +228,18 @@ endmodule
 | 
			
		|||
 | 
			
		||||
// Negative Edge SiliconBlue FF Cells
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 11, abc_flop *)
 | 
			
		||||
module SB_DFFN ((* abc_flop_q *) output `SB_DFF_REG, input C, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFN (output `SB_DFF_REG, input C, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 12, abc_flop *)
 | 
			
		||||
module SB_DFFNE ((* abc_flop_q *) output `SB_DFF_REG, input C, E, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNE (output `SB_DFF_REG, input C, E, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E)
 | 
			
		||||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 13, abc_flop *)
 | 
			
		||||
module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNSR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -260,8 +247,7 @@ module SB_DFFNSR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 14, abc_flop *)
 | 
			
		||||
module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNR (output `SB_DFF_REG, input C, R, D);
 | 
			
		||||
	always @(negedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -269,8 +255,7 @@ module SB_DFFNR ((* abc_flop_q *) output `SB_DFF_REG, input C, R, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 15, abc_flop *)
 | 
			
		||||
module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNSS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -278,8 +263,7 @@ module SB_DFFNSS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 16, abc_flop *)
 | 
			
		||||
module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNS (output `SB_DFF_REG, input C, S, D);
 | 
			
		||||
	always @(negedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -287,8 +271,7 @@ module SB_DFFNS ((* abc_flop_q *) output `SB_DFF_REG, input C, S, (* abc_flop_d
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 17, abc_flop *)
 | 
			
		||||
module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNESR (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (R)
 | 
			
		||||
| 
						 | 
				
			
			@ -298,8 +281,7 @@ module SB_DFFNESR ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_fl
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 18, abc_flop *)
 | 
			
		||||
module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNER (output `SB_DFF_REG, input C, E, R, D);
 | 
			
		||||
	always @(negedge C, posedge R)
 | 
			
		||||
		if (R)
 | 
			
		||||
			Q <= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -307,8 +289,7 @@ module SB_DFFNER ((* abc_flop_q *) output `SB_DFF_REG, input C, E, R, (* abc_flo
 | 
			
		|||
			Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 19, abc_flop *)
 | 
			
		||||
module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNESS (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
	always @(negedge C)
 | 
			
		||||
		if (E) begin
 | 
			
		||||
			if (S)
 | 
			
		||||
| 
						 | 
				
			
			@ -318,8 +299,7 @@ module SB_DFFNESS ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_fl
 | 
			
		|||
		end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
//(* abc_box_id = 20, abc_flop *)
 | 
			
		||||
module SB_DFFNES ((* abc_flop_q *) output `SB_DFF_REG, input C, E, S, (* abc_flop_d *) input D);
 | 
			
		||||
module SB_DFFNES (output `SB_DFF_REG, input C, E, S, D);
 | 
			
		||||
	always @(negedge C, posedge S)
 | 
			
		||||
		if (S)
 | 
			
		||||
			Q <= 1;
 | 
			
		||||
| 
						 | 
				
			
			@ -330,7 +310,7 @@ endmodule
 | 
			
		|||
// SiliconBlue RAM Cells
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4K (
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	input         RCLK, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLK, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -498,7 +478,7 @@ module SB_RAM40_4K (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNR (
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	input         RCLKN, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLK, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -563,7 +543,7 @@ module SB_RAM40_4KNR (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNW (
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	input         RCLK, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLKN, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -628,7 +608,7 @@ module SB_RAM40_4KNW (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SB_RAM40_4KNRNW (
 | 
			
		||||
	(* abc_flop_q *) output [15:0] RDATA,
 | 
			
		||||
	output [15:0] RDATA,
 | 
			
		||||
	input         RCLKN, RCLKE, RE,
 | 
			
		||||
	input  [10:0] RADDR,
 | 
			
		||||
	input         WCLKN, WCLKE, WE,
 | 
			
		||||
| 
						 | 
				
			
			@ -922,7 +902,7 @@ module SB_SPRAM256KA (
 | 
			
		|||
	input [15:0] DATAIN,
 | 
			
		||||
	input [3:0] MASKWREN,
 | 
			
		||||
	input WREN, CHIPSELECT, CLOCK, STANDBY, SLEEP, POWEROFF,
 | 
			
		||||
	(* abc_flop_q *) output reg [15:0] DATAOUT
 | 
			
		||||
	output reg [15:0] DATAOUT
 | 
			
		||||
);
 | 
			
		||||
`ifndef BLACKBOX
 | 
			
		||||
`ifndef EQUIV
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -97,7 +97,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
		log("        (this feature is experimental and incomplete)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -abc9\n");
 | 
			
		||||
		log("        use abc9 instead of abc\n");
 | 
			
		||||
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("The following commands are executed by this synthesis command:\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -332,7 +332,7 @@ struct SynthIce40Pass : public ScriptPass
 | 
			
		|||
			}
 | 
			
		||||
			if (!noabc) {
 | 
			
		||||
				if (abc == "abc9")
 | 
			
		||||
					run(abc + stringf(" -dress -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
 | 
			
		||||
					run(abc + stringf(" -lut +/ice40/abc_%s.lut -box +/ice40/abc_%s.box", device_opt.c_str(), device_opt.c_str()), "(skip if -noabc)");
 | 
			
		||||
				else
 | 
			
		||||
					run(abc + " -dress -lut 4", "(skip if -noabc)");
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,9 +30,8 @@ $(eval $(call add_share_file,share/xilinx,techlibs/xilinx/drams_map.v))
 | 
			
		|||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/arith_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/ff_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/lut_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/mux_map.v))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.box))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc.lut))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.box))
 | 
			
		||||
$(eval $(call add_share_file,share/xilinx,techlibs/xilinx/abc_xc7.lut))
 | 
			
		||||
 | 
			
		||||
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_36.vh))
 | 
			
		||||
$(eval $(call add_gen_share_file,share/xilinx,techlibs/xilinx/brams_init_32.vh))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,14 +0,0 @@
 | 
			
		|||
# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/34ea6eb08a63d21ec16264ad37a0a7b142ff6031/artix7/timings/CLBLL_L.sdf
 | 
			
		||||
 | 
			
		||||
# K	area	delay
 | 
			
		||||
1 	1	124
 | 
			
		||||
2	2	124 235
 | 
			
		||||
3	3	124 235 399
 | 
			
		||||
4	3	124 235 399 490
 | 
			
		||||
5	3	124 235 399 490 620
 | 
			
		||||
6	5	124 235 399 490 620 632
 | 
			
		||||
                # F7BMUX
 | 
			
		||||
7	10	296 420 531 695 756 916 928
 | 
			
		||||
                # F8MUX
 | 
			
		||||
                    # F8MUX+F7BMUX
 | 
			
		||||
8	20	273 569 693 804 968 1029 1189 1201
 | 
			
		||||
| 
						 | 
				
			
			@ -54,9 +54,9 @@ FDSE 7 0 4 1
 | 
			
		|||
# Inputs: C CE CLR D
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
FDCE 8 0 4 1
 | 
			
		||||
- - 404 -
 | 
			
		||||
- - - -
 | 
			
		||||
 | 
			
		||||
# Inputs: C CE D PRE
 | 
			
		||||
# Outputs: Q
 | 
			
		||||
FDPE 9 0 4 1
 | 
			
		||||
- - - 404
 | 
			
		||||
- - - -
 | 
			
		||||
							
								
								
									
										15
									
								
								techlibs/xilinx/abc_xc7.lut
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								techlibs/xilinx/abc_xc7.lut
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,15 @@
 | 
			
		|||
# Max delays from https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/timings/CLBLL_L.sdf
 | 
			
		||||
#            and  https://github.com/SymbiFlow/prjxray-db/blob/82bf5f158cd8e9a11ac4d04f1aeef48ed1a528a5/artix7/tile_type_CLBLL_L.json
 | 
			
		||||
 | 
			
		||||
# K	area	delay
 | 
			
		||||
1 	1	127
 | 
			
		||||
2	2	127 238
 | 
			
		||||
3	3	127 238 407
 | 
			
		||||
4	3	127 238 407 472
 | 
			
		||||
5	3	127 238 407 472 631
 | 
			
		||||
6	5	127 238 407 472 631 642
 | 
			
		||||
        # F7AMUX + F7BMUX / 2
 | 
			
		||||
7	10	286 413 524 693 758 917 928
 | 
			
		||||
        # F8MUX
 | 
			
		||||
            # F8MUX+F7MUX
 | 
			
		||||
8	20	273 559 686 797 966 1031 1190 1201
 | 
			
		||||
| 
						 | 
				
			
			@ -19,10 +19,10 @@ module RAMB18E1 (
 | 
			
		|||
	input [1:0] WEA,
 | 
			
		||||
	input [3:0] WEBWE,
 | 
			
		||||
 | 
			
		||||
	(* abc_flop_q *) output [15:0] DOADO,
 | 
			
		||||
	(* abc_flop_q *) output [15:0] DOBDO,
 | 
			
		||||
	(* abc_flop_q *) output [1:0] DOPADOP,
 | 
			
		||||
	(* abc_flop_q *) output [1:0] DOPBDOP
 | 
			
		||||
	output [15:0] DOADO,
 | 
			
		||||
	output [15:0] DOBDO,
 | 
			
		||||
	output [1:0] DOPADOP,
 | 
			
		||||
	output [1:0] DOPBDOP
 | 
			
		||||
);
 | 
			
		||||
	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
 | 
			
		||||
	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
 | 
			
		||||
| 
						 | 
				
			
			@ -143,10 +143,10 @@ module RAMB36E1 (
 | 
			
		|||
	input [3:0] WEA,
 | 
			
		||||
	input [7:0] WEBWE,
 | 
			
		||||
 | 
			
		||||
	(* abc_flop_q *) output [31:0] DOADO,
 | 
			
		||||
	(* abc_flop_q *) output [31:0] DOBDO,
 | 
			
		||||
	(* abc_flop_q *) output [3:0] DOPADOP,
 | 
			
		||||
	(* abc_flop_q *) output [3:0] DOPBDOP
 | 
			
		||||
	output [31:0] DOADO,
 | 
			
		||||
	output [31:0] DOBDO,
 | 
			
		||||
	output [3:0] DOPADOP,
 | 
			
		||||
	output [3:0] DOPBDOP
 | 
			
		||||
);
 | 
			
		||||
	parameter INITP_00 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
 | 
			
		||||
	parameter INITP_01 = 256'h0000000000000000000000000000000000000000000000000000000000000000;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,18 @@
 | 
			
		|||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Convert negative-polarity reset to positive-polarity
 | 
			
		||||
(* techmap_celltype = "$_DFF_NN0_" *)
 | 
			
		||||
module _90_dff_nn0_to_np0(input D, C, R, output Q); \$_DFF_NP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
 | 
			
		||||
(* techmap_celltype = "$_DFF_PN0_" *)
 | 
			
		||||
module _90_dff_pn0_to_pp0(input D, C, R, output Q); \$_DFF_PP0_  _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
 | 
			
		||||
 | 
			
		||||
(* techmap_celltype = "$_DFF_NN1_" *)
 | 
			
		||||
module _90_dff_nn1_to_np1 (input D, C, R, output Q); \$_DFF_NP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
 | 
			
		||||
(* techmap_celltype = "$_DFF_PN1_" *)
 | 
			
		||||
module _90_dff_pn1_to_pp1 (input D, C, R, output Q); \$_DFF_PP1   _TECHMAP_REPLACE_ (.D(D), .Q(Q), .C(C), .R(~R)); endmodule
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
module \$__SHREG_ (input C, input D, input E, output Q);
 | 
			
		||||
  parameter DEPTH = 0;
 | 
			
		||||
  parameter [DEPTH-1:0] INIT = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -142,123 +154,3 @@ module \$__XILINX_SHREG_ (input C, input D, input [31:0] L, input E, output Q, o
 | 
			
		|||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module \$__XILINX_SHIFTX (A, B, Y);
 | 
			
		||||
  parameter A_SIGNED = 0;
 | 
			
		||||
  parameter B_SIGNED = 0;
 | 
			
		||||
  parameter A_WIDTH = 1;
 | 
			
		||||
  parameter B_WIDTH = 1;
 | 
			
		||||
  parameter Y_WIDTH = 1;
 | 
			
		||||
 | 
			
		||||
  input [A_WIDTH-1:0] A;
 | 
			
		||||
  input [B_WIDTH-1:0] B;
 | 
			
		||||
  output [Y_WIDTH-1:0] Y;
 | 
			
		||||
 | 
			
		||||
  parameter [A_WIDTH-1:0] _TECHMAP_CONSTMSK_A_ = 0;
 | 
			
		||||
  parameter [A_WIDTH-1:0] _TECHMAP_CONSTVAL_A_ = 0;
 | 
			
		||||
  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
 | 
			
		||||
  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
 | 
			
		||||
 | 
			
		||||
  function integer compute_num_leading_X_in_A;
 | 
			
		||||
    integer i, c;
 | 
			
		||||
  begin
 | 
			
		||||
    compute_num_leading_X_in_A = 0;
 | 
			
		||||
    c = 1;
 | 
			
		||||
    for (i = A_WIDTH-1; i >= 0; i=i-1) begin
 | 
			
		||||
      if (!_TECHMAP_CONSTMSK_A_[i] || _TECHMAP_CONSTVAL_A_[i] !== 1'bx)
 | 
			
		||||
        c = 0;
 | 
			
		||||
      compute_num_leading_X_in_A = compute_num_leading_X_in_A + c;
 | 
			
		||||
    end
 | 
			
		||||
  end
 | 
			
		||||
  endfunction
 | 
			
		||||
  localparam num_leading_X_in_A = compute_num_leading_X_in_A();
 | 
			
		||||
 | 
			
		||||
  generate
 | 
			
		||||
    genvar i, j;
 | 
			
		||||
    // Bit-blast
 | 
			
		||||
    if (Y_WIDTH > 1) begin
 | 
			
		||||
      for (i = 0; i < Y_WIDTH; i++)
 | 
			
		||||
        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH-Y_WIDTH+1), .B_WIDTH(B_WIDTH), .Y_WIDTH(1'd1)) bitblast (.A(A[A_WIDTH-Y_WIDTH+i:i]), .B(B), .Y(Y[i]));
 | 
			
		||||
    end
 | 
			
		||||
    // If the LSB of B is constant zero (and Y_WIDTH is 1) then
 | 
			
		||||
    //   we can optimise by removing every other entry from A
 | 
			
		||||
    //   and popping the constant zero from B
 | 
			
		||||
    else if (_TECHMAP_CONSTMSK_B_[0] && !_TECHMAP_CONSTVAL_B_[0]) begin
 | 
			
		||||
      wire [(A_WIDTH+1)/2-1:0] A_i;
 | 
			
		||||
      for (i = 0; i < (A_WIDTH+1)/2; i++)
 | 
			
		||||
        assign A_i[i] = A[i*2];
 | 
			
		||||
      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH((A_WIDTH+1'd1)/2'd2), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A_i), .B(B[B_WIDTH-1:1]), .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
    // Trim off any leading 1'bx -es in A, and resize B accordingly
 | 
			
		||||
    else if (num_leading_X_in_A > 0) begin
 | 
			
		||||
      localparam A_WIDTH_new = A_WIDTH - num_leading_X_in_A;
 | 
			
		||||
      localparam B_WIDTH_new = $clog2(A_WIDTH_new);
 | 
			
		||||
      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH_new), .B_WIDTH(B_WIDTH_new), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A[A_WIDTH_new-1:0]), .B(B[B_WIDTH_new-1:0]), .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
    else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
 | 
			
		||||
      \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
    else if (B_WIDTH == 3) begin
 | 
			
		||||
      localparam a_width0 = 2 ** 2;
 | 
			
		||||
      localparam a_widthN = A_WIDTH - a_width0;
 | 
			
		||||
      wire T0, T1;
 | 
			
		||||
      \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[a_width0-1:0]),       .B(B[2-1:0]),                .Y(T0));
 | 
			
		||||
      if (a_widthN > 1)
 | 
			
		||||
        \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T1));
 | 
			
		||||
      else
 | 
			
		||||
        assign T1 = A[A_WIDTH-1];
 | 
			
		||||
      MUXF7 fpga_hard_mux (.I0(T0), .I1(T1), .S(B[B_WIDTH-1]), .O(Y));
 | 
			
		||||
    end
 | 
			
		||||
    else if (B_WIDTH == 4) begin
 | 
			
		||||
      localparam a_width0 = 2 ** 2;
 | 
			
		||||
      localparam num_mux8 = A_WIDTH / a_width0;
 | 
			
		||||
      localparam a_widthN = A_WIDTH - num_mux8*a_width0;
 | 
			
		||||
      wire [4-1:0] T;
 | 
			
		||||
      wire T0, T1;
 | 
			
		||||
      for (i = 0; i < 4; i++)
 | 
			
		||||
        if (i < num_mux8)
 | 
			
		||||
          \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(2),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[i*a_width0+:a_width0]), .B(B[2-1:0]),                .Y(T[i]));
 | 
			
		||||
        else if (i == num_mux8 && a_widthN > 0) begin
 | 
			
		||||
          if (a_widthN > 1)
 | 
			
		||||
            \$shiftx  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
 | 
			
		||||
          else
 | 
			
		||||
            assign T[i] = A[A_WIDTH-1];
 | 
			
		||||
        end
 | 
			
		||||
        else
 | 
			
		||||
          assign T[i] = 1'bx;
 | 
			
		||||
      MUXF7 fpga_hard_mux_0 (.I0(T[0]), .I1(T[1]), .S(B[2]), .O(T0));
 | 
			
		||||
      MUXF7 fpga_hard_mux_1 (.I0(T[2]), .I1(T[3]), .S(B[2]), .O(T1));
 | 
			
		||||
      MUXF8 fpga_hard_mux_2 (.I0(T0),   .I1(T1),   .S(B[3]), .O(Y));
 | 
			
		||||
    end
 | 
			
		||||
    else begin
 | 
			
		||||
      localparam a_width0 = 2 ** 4;
 | 
			
		||||
      localparam num_mux16 = A_WIDTH / a_width0;
 | 
			
		||||
      localparam a_widthN = A_WIDTH - num_mux16*a_width0;
 | 
			
		||||
      wire [(2**(B_WIDTH-4))-1:0] T;
 | 
			
		||||
      for (i = 0; i < 2 ** (B_WIDTH-4); i++)
 | 
			
		||||
        if (i < num_mux16)
 | 
			
		||||
          \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_width0), .B_WIDTH(4),                .Y_WIDTH(Y_WIDTH)) fpga_soft_mux      (.A(A[i*a_width0+:a_width0]), .B(B[4-1:0]),                .Y(T[i]));
 | 
			
		||||
        else if (i == num_mux16 && a_widthN > 0) begin
 | 
			
		||||
          if (a_widthN > 1)
 | 
			
		||||
            \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(a_widthN), .B_WIDTH($clog2(a_widthN)), .Y_WIDTH(Y_WIDTH)) fpga_soft_mux_last (.A(A[A_WIDTH-1:i*a_width0]), .B(B[$clog2(a_widthN)-1:0]), .Y(T[i]));
 | 
			
		||||
          else
 | 
			
		||||
            assign T[i] = A[A_WIDTH-1];
 | 
			
		||||
        end
 | 
			
		||||
        else
 | 
			
		||||
          assign T[i] = 1'bx;
 | 
			
		||||
      \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(2**(B_WIDTH-4)), .B_WIDTH(B_WIDTH-4), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(T), .B(B[B_WIDTH-1:4]), .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module \$_MUX8_ (A, B, C, D, E, F, G, H, S, T, U, Y);
 | 
			
		||||
input A, B, C, D, E, F, G, H, S, T, U;
 | 
			
		||||
output Y;
 | 
			
		||||
  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(8), .B_WIDTH(3), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({H,G,F,E,D,C,B,A}), .B({U,T,S}), .Y(Y));
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module \$_MUX16_ (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V, Y);
 | 
			
		||||
input A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, S, T, U, V;
 | 
			
		||||
output Y;
 | 
			
		||||
  \$__XILINX_SHIFTX  #(.A_SIGNED(0), .B_SIGNED(0), .A_WIDTH(16), .B_WIDTH(4), .Y_WIDTH(1)) _TECHMAP_REPLACE_ (.A({P,O,N,M,L,K,J,I,H,G,F,E,D,C,B,A}), .B({V,U,T,S}), .Y(Y));
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -205,7 +205,7 @@ endmodule
 | 
			
		|||
 | 
			
		||||
`endif
 | 
			
		||||
 | 
			
		||||
module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R);
 | 
			
		||||
module FDRE (output reg Q, input C, CE, D, R);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_C_INVERTED = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_D_INVERTED = 1'b0;
 | 
			
		||||
| 
						 | 
				
			
			@ -217,7 +217,7 @@ module FDRE ((* abc_flop_q *) output reg Q, input C, CE, D, R);
 | 
			
		|||
  endcase endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S);
 | 
			
		||||
module FDSE (output reg Q, input C, CE, D, S);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_C_INVERTED = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_D_INVERTED = 1'b0;
 | 
			
		||||
| 
						 | 
				
			
			@ -229,7 +229,7 @@ module FDSE ((* abc_flop_q *) output reg Q, input C, CE, D, S);
 | 
			
		|||
  endcase endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
 | 
			
		||||
module FDCE (output reg Q, input C, CE, D, CLR);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_C_INVERTED = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_D_INVERTED = 1'b0;
 | 
			
		||||
| 
						 | 
				
			
			@ -243,7 +243,7 @@ module FDCE ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
 | 
			
		|||
  endcase endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
 | 
			
		||||
module FDPE (output reg Q, input C, CE, D, PRE);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_C_INVERTED = 1'b0;
 | 
			
		||||
  parameter [0:0] IS_D_INVERTED = 1'b0;
 | 
			
		||||
| 
						 | 
				
			
			@ -257,25 +257,25 @@ module FDPE ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
 | 
			
		|||
  endcase endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDRE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, R);
 | 
			
		||||
module FDRE_1 (output reg Q, input C, CE, D, R);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  initial Q <= INIT;
 | 
			
		||||
  always @(negedge C) if (R) Q <= 1'b0; else if(CE) Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDSE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, S);
 | 
			
		||||
module FDSE_1 (output reg Q, input C, CE, D, S);
 | 
			
		||||
  parameter [0:0] INIT = 1'b1;
 | 
			
		||||
  initial Q <= INIT;
 | 
			
		||||
  always @(negedge C) if (S) Q <= 1'b1; else if(CE) Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDCE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, CLR);
 | 
			
		||||
module FDCE_1 (output reg Q, input C, CE, D, CLR);
 | 
			
		||||
  parameter [0:0] INIT = 1'b0;
 | 
			
		||||
  initial Q <= INIT;
 | 
			
		||||
  always @(negedge C, posedge CLR) if (CLR) Q <= 1'b0; else if (CE) Q <= D;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module FDPE_1 ((* abc_flop_q *) output reg Q, input C, CE, D, PRE);
 | 
			
		||||
module FDPE_1 (output reg Q, input C, CE, D, PRE);
 | 
			
		||||
  parameter [0:0] INIT = 1'b1;
 | 
			
		||||
  initial Q <= INIT;
 | 
			
		||||
  always @(negedge C, posedge PRE) if (PRE) Q <= 1'b1; else if (CE) Q <= D;
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +315,7 @@ module RAM128X1D (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SRL16E (
 | 
			
		||||
  (* abc_flop_q *) output Q,
 | 
			
		||||
  output Q,
 | 
			
		||||
  input A0, A1, A2, A3, CE, CLK, D
 | 
			
		||||
);
 | 
			
		||||
  parameter [15:0] INIT = 16'h0000;
 | 
			
		||||
| 
						 | 
				
			
			@ -333,7 +333,7 @@ module SRL16E (
 | 
			
		|||
endmodule
 | 
			
		||||
 | 
			
		||||
module SRLC32E (
 | 
			
		||||
  (* abc_flop_q *) output Q,
 | 
			
		||||
  output Q,
 | 
			
		||||
  output Q31,
 | 
			
		||||
  input [4:0] A,
 | 
			
		||||
  input CE, CLK, D
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,52 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  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.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
module \$shiftx (A, B, Y);
 | 
			
		||||
  parameter A_SIGNED = 0;
 | 
			
		||||
  parameter B_SIGNED = 0;
 | 
			
		||||
  parameter A_WIDTH = 1;
 | 
			
		||||
  parameter B_WIDTH = 1;
 | 
			
		||||
  parameter Y_WIDTH = 1;
 | 
			
		||||
 | 
			
		||||
  input [A_WIDTH-1:0] A;
 | 
			
		||||
  input [B_WIDTH-1:0] B;
 | 
			
		||||
  output [Y_WIDTH-1:0] Y;
 | 
			
		||||
 | 
			
		||||
  parameter [B_WIDTH-1:0] _TECHMAP_CONSTMSK_B_ = 0;
 | 
			
		||||
  parameter [B_WIDTH-1:0] _TECHMAP_CONSTVAL_B_ = 0;
 | 
			
		||||
 | 
			
		||||
  generate
 | 
			
		||||
    genvar i, j;
 | 
			
		||||
    // TODO: Check if this opt still necessary
 | 
			
		||||
    if (B_SIGNED) begin
 | 
			
		||||
      if (_TECHMAP_CONSTMSK_B_[B_WIDTH-1] && _TECHMAP_CONSTVAL_B_[B_WIDTH-1] == 1'b0)
 | 
			
		||||
        // Optimisation to remove B_SIGNED if sign bit of B is constant-0
 | 
			
		||||
        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(0), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH-1'd1), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B[B_WIDTH-2:0]), .Y(Y));
 | 
			
		||||
      else
 | 
			
		||||
        wire _TECHMAP_FAIL_ = 1;
 | 
			
		||||
    end
 | 
			
		||||
    else if (B_WIDTH < 3 || A_WIDTH <= 4) begin
 | 
			
		||||
      wire _TECHMAP_FAIL_ = 1;
 | 
			
		||||
    end
 | 
			
		||||
    else begin
 | 
			
		||||
        \$__XILINX_SHIFTX  #(.A_SIGNED(A_SIGNED), .B_SIGNED(B_SIGNED), .A_WIDTH(A_WIDTH), .B_WIDTH(B_WIDTH), .Y_WIDTH(Y_WIDTH)) _TECHMAP_REPLACE_ (.A(A), .B(B), .Y(Y));
 | 
			
		||||
    end
 | 
			
		||||
  endgenerate
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			@ -25,6 +25,8 @@
 | 
			
		|||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
#define XC7_WIRE_DELAY "160"
 | 
			
		||||
 | 
			
		||||
struct SynthXilinxPass : public ScriptPass
 | 
			
		||||
{
 | 
			
		||||
	SynthXilinxPass() : ScriptPass("synth_xilinx", "synthesis for Xilinx FPGAs") { }
 | 
			
		||||
| 
						 | 
				
			
			@ -70,9 +72,6 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		log("    -nosrl\n");
 | 
			
		||||
		log("        disable inference of shift registers\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -nomux\n");
 | 
			
		||||
		log("        disable inference of wide multiplexers\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -run <from_label>:<to_label>\n");
 | 
			
		||||
		log("        only run the commands between the labels (see below). an empty\n");
 | 
			
		||||
		log("        from label is synonymous to 'begin', and empty to label is\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +84,7 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		log("        run 'abc' with -dff option\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -abc9\n");
 | 
			
		||||
		log("        use abc9 instead of abc\n");
 | 
			
		||||
		log("        use new ABC9 flow (EXPERIMENTAL)\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("The following commands are executed by this synthesis command:\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +93,7 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	std::string top_opt, edif_file, blif_file, abc, arch;
 | 
			
		||||
	bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl, nomux;
 | 
			
		||||
	bool flatten, retime, vpr, nocarry, nobram, nodram, nosrl;
 | 
			
		||||
 | 
			
		||||
	void clear_flags() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -109,7 +108,6 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		nobram = false;
 | 
			
		||||
		nodram = false;
 | 
			
		||||
		nosrl = false;
 | 
			
		||||
		nomux = false;
 | 
			
		||||
		arch = "xc7";
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -173,10 +171,6 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
				nosrl = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-nomux") {
 | 
			
		||||
				nomux = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-abc9") {
 | 
			
		||||
				abc = "abc9";
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			@ -225,15 +219,11 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
		if (check_label("coarse")) {
 | 
			
		||||
			run("synth -run coarse");
 | 
			
		||||
 | 
			
		||||
			//if (!nomux || help_mode)
 | 
			
		||||
			//	run("muxpack", "(skip if '-nomux')");
 | 
			
		||||
 | 
			
		||||
			// shregmap -tech xilinx can cope with $shiftx and $mux
 | 
			
		||||
			//   cells for identifying variable-length shift registers,
 | 
			
		||||
			//   so attempt to convert $pmux-es to the former
 | 
			
		||||
			// Also: wide multiplexer inference benefits from this too
 | 
			
		||||
			if (!(nosrl && nomux) || help_mode)
 | 
			
		||||
				run("pmux2shiftx", "(skip if '-nosrl' and '-nomux')");
 | 
			
		||||
			if (!nosrl || help_mode)
 | 
			
		||||
				run("pmux2shiftx", "(skip if '-nosrl')");
 | 
			
		||||
 | 
			
		||||
			// Run a number of peephole optimisations, including one
 | 
			
		||||
			//   that optimises $mul cells driving $shiftx's B input
 | 
			
		||||
| 
						 | 
				
			
			@ -272,32 +262,26 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
 | 
			
		||||
			std::string techmap_files = " -map +/techmap.v";
 | 
			
		||||
			if (help_mode)
 | 
			
		||||
					techmap_files += " [-map +/xilinx/mux_map.v]";
 | 
			
		||||
			else if (!nomux)
 | 
			
		||||
					techmap_files += " -map +/xilinx/mux_map.v";
 | 
			
		||||
			if (help_mode)
 | 
			
		||||
					techmap_files += " [-map +/xilinx/arith_map.v]";
 | 
			
		||||
				techmap_files += " [-map +/xilinx/arith_map.v]";
 | 
			
		||||
			else if (!nocarry) {
 | 
			
		||||
					techmap_files += " -map +/xilinx/arith_map.v";
 | 
			
		||||
					if (vpr)
 | 
			
		||||
							techmap_files += " -D _EXPLICIT_CARRY";
 | 
			
		||||
					else if (abc == "abc9")
 | 
			
		||||
							techmap_files += " -D _CLB_CARRY";
 | 
			
		||||
				techmap_files += " -map +/xilinx/arith_map.v";
 | 
			
		||||
				if (vpr)
 | 
			
		||||
					techmap_files += " -D _EXPLICIT_CARRY";
 | 
			
		||||
				else if (abc == "abc9")
 | 
			
		||||
					techmap_files += " -D _CLB_CARRY";
 | 
			
		||||
			}
 | 
			
		||||
			run("techmap " + techmap_files);
 | 
			
		||||
			run("opt -fast");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("map_cells")) {
 | 
			
		||||
			if (!nomux || help_mode)
 | 
			
		||||
				run("muxcover -mux8 -mux16", "(skip if '-nomux')");
 | 
			
		||||
			run("techmap -map +/techmap.v -map +/xilinx/cells_map.v");
 | 
			
		||||
			run("clean");
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (check_label("map_luts")) {
 | 
			
		||||
			if (abc == "abc9")
 | 
			
		||||
				run(abc + " -lut +/xilinx/abc.lut -box +/xilinx/abc.box -W 160" + string(retime ? " -dff" : ""));
 | 
			
		||||
				run(abc + " -lut +/xilinx/abc_xc7.lut -box +/xilinx/abc_xc7.box -W " + XC7_WIRE_DELAY + string(retime ? " -dff" : ""));
 | 
			
		||||
			else if (help_mode)
 | 
			
		||||
				run(abc + " -luts 2:2,3,6:5,10,20 [-dff]");
 | 
			
		||||
			else
 | 
			
		||||
| 
						 | 
				
			
			@ -308,7 +292,7 @@ struct SynthXilinxPass : public ScriptPass
 | 
			
		|||
			//   has performed any necessary retiming
 | 
			
		||||
			if (!nosrl || help_mode)
 | 
			
		||||
				run("shregmap -minlen 3 -init -params -enpol any_or_none", "(skip if '-nosrl')");
 | 
			
		||||
			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/cells_map.v -map +/xilinx/ff_map.v");
 | 
			
		||||
			run("techmap -map +/xilinx/lut_map.v -map +/xilinx/ff_map.v -map +/xilinx/cells_map.v");
 | 
			
		||||
			run("dffinit -ff FDRE Q INIT -ff FDCE Q INIT -ff FDPE Q INIT -ff FDSE Q INIT "
 | 
			
		||||
					"-ff FDRE_1 Q INIT -ff FDCE_1 Q INIT -ff FDPE_1 Q INIT -ff FDSE_1 Q INIT");
 | 
			
		||||
			run("clean");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -250,3 +250,15 @@ module abc9_test023 #(
 | 
			
		|||
	wire [2*M-1:0] mask = {M{1'b1}};
 | 
			
		||||
	assign dout = (mask << din[N-1:0]) >> M;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module abc9_test024(input [3:0] i, output [3:0] o);
 | 
			
		||||
abc9_test024_sub a(i[1:0], o[1:0]);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module abc9_test024_sub(input [1:0] i, output [1:0] o);
 | 
			
		||||
assign o = i;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module abc9_test025(input [3:0] i, output [3:0] o);
 | 
			
		||||
abc9_test024_sub a(i[2:1], o[2:1]);
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,138 +0,0 @@
 | 
			
		|||
module mux_if_unbal_4_1 #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @*
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
    else if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    else if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    else if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    else o <= {W{1'bx}};
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_5_3 #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    o <= {W{1'bx}};
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
    if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    if (s == 4) o <= i[4*W+:W];
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_5_3_invert #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @*
 | 
			
		||||
    if (s != 0) 
 | 
			
		||||
	   	if (s != 1) 
 | 
			
		||||
			if (s != 2)
 | 
			
		||||
				if (s != 3)
 | 
			
		||||
					if (s != 4) o <= i[4*W+:W];
 | 
			
		||||
					else o <= i[0*W+:W];
 | 
			
		||||
				else o <= i[3*W+:W];
 | 
			
		||||
			else o <= i[2*W+:W];
 | 
			
		||||
		else o <= i[1*W+:W];
 | 
			
		||||
    else o <= {W{1'bx}};
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_5_3_width_mismatch #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    o <= {W{1'bx}};
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
    if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    if (s == 2) o[W-2:0] <= i[2*W+:W-1];
 | 
			
		||||
    if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    if (s == 4) o <= i[4*W+:W];
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_4_1_missing #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
//    else if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
//    else if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    else if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    else o <= {W{1'bx}};
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_5_3_order #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    o <= {W{1'bx}};
 | 
			
		||||
    if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    if (s == 4) o <= i[4*W+:W];
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_4_1_nonexcl #(parameter N=4, parameter W=1) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @*
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
    else if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    else if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    else if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
	else if (s == 0) o <= {W{1'b0}};
 | 
			
		||||
    else o <= {W{1'bx}};
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_unbal_5_3_nonexcl #(parameter N=5, parameter W=3) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    o <= {W{1'bx}};
 | 
			
		||||
    if (s == 0) o <= i[0*W+:W];
 | 
			
		||||
    if (s == 1) o <= i[1*W+:W];
 | 
			
		||||
    if (s == 2) o <= i[2*W+:W];
 | 
			
		||||
    if (s == 3) o <= i[3*W+:W];
 | 
			
		||||
    if (s == 4) o <= i[4*W+:W];
 | 
			
		||||
	if (s == 0) o <= i[2*W+:W];
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_case_unbal_8_7#(parameter N=8, parameter W=7) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @* begin
 | 
			
		||||
    o <= {W{1'bx}};
 | 
			
		||||
    case (s)
 | 
			
		||||
    0: o <= i[0*W+:W];
 | 
			
		||||
    default:
 | 
			
		||||
        case (s)
 | 
			
		||||
        1: o <= i[1*W+:W];
 | 
			
		||||
        2: o <= i[2*W+:W];
 | 
			
		||||
        default:
 | 
			
		||||
            case (s)
 | 
			
		||||
            3: o <= i[3*W+:W];
 | 
			
		||||
            4: o <= i[4*W+:W];
 | 
			
		||||
            5: o <= i[5*W+:W];
 | 
			
		||||
            default:
 | 
			
		||||
                case (s)
 | 
			
		||||
                    6: o <= i[6*W+:W];
 | 
			
		||||
                    default: o <= i[7*W+:W];
 | 
			
		||||
                endcase
 | 
			
		||||
            endcase
 | 
			
		||||
        endcase
 | 
			
		||||
    endcase
 | 
			
		||||
end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module mux_if_bal_8_2 #(parameter N=8, parameter W=2) (input [N*W-1:0] i, input [$clog2(N)-1:0] s, output reg [W-1:0] o);
 | 
			
		||||
always @*
 | 
			
		||||
    if (s[0] == 1'b0)
 | 
			
		||||
     if (s[1] == 1'b0)
 | 
			
		||||
      if (s[2] == 1'b0)
 | 
			
		||||
       o <= i[0*W+:W];
 | 
			
		||||
      else
 | 
			
		||||
       o <= i[1*W+:W];
 | 
			
		||||
     else
 | 
			
		||||
      if (s[2] == 1'b0)
 | 
			
		||||
       o <= i[2*W+:W];
 | 
			
		||||
      else
 | 
			
		||||
       o <= i[3*W+:W];
 | 
			
		||||
    else
 | 
			
		||||
     if (s[1] == 1'b0)
 | 
			
		||||
      if (s[2] == 1'b0)
 | 
			
		||||
       o <= i[4*W+:W];
 | 
			
		||||
      else
 | 
			
		||||
       o <= i[5*W+:W];
 | 
			
		||||
     else
 | 
			
		||||
      if (s[2] == 1'b0)
 | 
			
		||||
       o <= i[6*W+:W];
 | 
			
		||||
      else
 | 
			
		||||
       o <= i[7*W+:W];
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			@ -1,150 +0,0 @@
 | 
			
		|||
read_verilog muxpack.v
 | 
			
		||||
design -save read
 | 
			
		||||
hierarchy -top mux_if_unbal_4_1
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_5_3
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_5_3_invert
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_5_3_width_mismatch
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 2 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_4_1_missing
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_5_3_order
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_4_1_nonexcl
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_unbal_5_3_nonexcl
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_case_unbal_8_7
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 0 t:$mux
 | 
			
		||||
select -assert-count 1 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
 | 
			
		||||
design -load read
 | 
			
		||||
hierarchy -top mux_if_bal_8_2
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
muxpack
 | 
			
		||||
opt
 | 
			
		||||
stat
 | 
			
		||||
select -assert-count 7 t:$mux
 | 
			
		||||
select -assert-count 0 t:$pmux
 | 
			
		||||
design -stash gate
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports miter
 | 
			
		||||
| 
						 | 
				
			
			@ -1,22 +0,0 @@
 | 
			
		|||
module shregmap_test(input i, clk, output [1:0] q);
 | 
			
		||||
reg head = 1'b0;
 | 
			
		||||
reg [3:0] shift1 = 4'b0000;
 | 
			
		||||
reg [3:0] shift2 = 4'b0000;
 | 
			
		||||
 | 
			
		||||
always @(posedge clk) begin
 | 
			
		||||
    head <= i;
 | 
			
		||||
    shift1 <= {shift1[2:0], head};
 | 
			
		||||
    shift2 <= {shift2[2:0], head};
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
assign q = {shift2[3], shift1[3]};
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module $__SHREG_DFF_P_(input C, D, output Q);
 | 
			
		||||
parameter DEPTH = 1;
 | 
			
		||||
parameter [DEPTH-1:0] INIT = {DEPTH{1'b0}};
 | 
			
		||||
reg [DEPTH-1:0] r = INIT;
 | 
			
		||||
always @(posedge C) 
 | 
			
		||||
    r <= { r[DEPTH-2:0], D };
 | 
			
		||||
assign Q = r[DEPTH-1];
 | 
			
		||||
endmodule
 | 
			
		||||
| 
						 | 
				
			
			@ -1,31 +0,0 @@
 | 
			
		|||
read_verilog shregmap.v
 | 
			
		||||
design -copy-to model $__SHREG_DFF_P_
 | 
			
		||||
hierarchy -top shregmap_test
 | 
			
		||||
prep
 | 
			
		||||
design -save gold
 | 
			
		||||
 | 
			
		||||
techmap
 | 
			
		||||
shregmap -init
 | 
			
		||||
 | 
			
		||||
opt
 | 
			
		||||
 | 
			
		||||
stat
 | 
			
		||||
# show -width
 | 
			
		||||
select -assert-count 1 t:$_DFF_P_
 | 
			
		||||
select -assert-count 2 t:$__SHREG_DFF_P_
 | 
			
		||||
 | 
			
		||||
design -stash gate
 | 
			
		||||
 | 
			
		||||
design -import gold -as gold
 | 
			
		||||
design -import gate -as gate
 | 
			
		||||
design -copy-from model -as $__SHREG_DFF_P_ \$__SHREG_DFF_P_
 | 
			
		||||
prep
 | 
			
		||||
 | 
			
		||||
miter -equiv -flatten -make_assert -make_outputs gold gate miter
 | 
			
		||||
sat -verify -prove-asserts -show-ports -seq 5 miter
 | 
			
		||||
 | 
			
		||||
design -load gold
 | 
			
		||||
stat
 | 
			
		||||
 | 
			
		||||
design -load gate
 | 
			
		||||
stat
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue