mirror of
				https://github.com/YosysHQ/yosys
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'origin/xc7srl' into xc7mux
This commit is contained in:
		
						commit
						4486a98fd5
					
				
					 77 changed files with 4701 additions and 347 deletions
				
			
		| 
						 | 
				
			
			@ -38,7 +38,6 @@ OBJS += passes/techmap/attrmap.o
 | 
			
		|||
OBJS += passes/techmap/zinit.o
 | 
			
		||||
OBJS += passes/techmap/dff2dffs.o
 | 
			
		||||
OBJS += passes/techmap/flowmap.o
 | 
			
		||||
OBJS += passes/techmap/pmux2shiftx.o
 | 
			
		||||
endif
 | 
			
		||||
 | 
			
		||||
GENFILES += passes/techmap/techmap.inc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,17 +29,17 @@
 | 
			
		|||
// Kahn, Arthur B. (1962), "Topological sorting of large networks", Communications of the ACM 5 (11): 558-562, doi:10.1145/368996.369025
 | 
			
		||||
// http://en.wikipedia.org/wiki/Topological_sorting
 | 
			
		||||
 | 
			
		||||
#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_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"
 | 
			
		||||
#define ABC_COMMAND_LIB "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
#define ABC_COMMAND_CTR "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put; buffer; upsize {D}; dnsize {D}; stime -p"
 | 
			
		||||
#define ABC_COMMAND_LUT "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; if; mfs2"
 | 
			
		||||
#define ABC_COMMAND_SOP "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; dch -f; cover {I} {P}"
 | 
			
		||||
#define ABC_COMMAND_DFL "strash; ifraig; scorr; dc2; dretime; retime {D}; strash; &get -n; &dch -f; &nf {D}; &put"
 | 
			
		||||
 | 
			
		||||
#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 "strash; dretime; 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_LIB "strash; dretime; retime {D}; map {D}"
 | 
			
		||||
#define ABC_FAST_COMMAND_CTR "strash; dretime; retime {D}; map {D}; buffer; upsize {D}; dnsize {D}; stime -p"
 | 
			
		||||
#define ABC_FAST_COMMAND_LUT "strash; dretime; retime {D}; if"
 | 
			
		||||
#define ABC_FAST_COMMAND_SOP "strash; dretime; retime {D}; cover -I {I} -P {P}"
 | 
			
		||||
#define ABC_FAST_COMMAND_DFL "strash; dretime; retime {D}; map"
 | 
			
		||||
 | 
			
		||||
#include "kernel/register.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -331,19 +331,23 @@ std::string remap_name(RTLIL::IdString abc_name, RTLIL::Wire **orig_wire = nullp
 | 
			
		|||
{
 | 
			
		||||
	std::string abc_sname = abc_name.substr(1);
 | 
			
		||||
	if (abc_sname.substr(0, 5) == "ys__n") {
 | 
			
		||||
		int sid = std::stoi(abc_sname.substr(5));
 | 
			
		||||
		bool inv = abc_sname.back() == 'v';
 | 
			
		||||
		for (auto sig : signal_list) {
 | 
			
		||||
			if (sig.id == sid && sig.bit.wire != nullptr) {
 | 
			
		||||
				std::stringstream sstr;
 | 
			
		||||
				sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
 | 
			
		||||
				if (sig.bit.wire->width != 1)
 | 
			
		||||
					sstr << "[" << sig.bit.offset << "]";
 | 
			
		||||
				if (inv)
 | 
			
		||||
					sstr << "_inv";
 | 
			
		||||
				if (orig_wire != nullptr)
 | 
			
		||||
					*orig_wire = sig.bit.wire;
 | 
			
		||||
				return sstr.str();
 | 
			
		||||
		if (inv) abc_sname.pop_back();
 | 
			
		||||
		abc_sname.erase(0, 5);
 | 
			
		||||
		if (abc_sname.find_last_not_of("012345689") == std::string::npos) {
 | 
			
		||||
			int sid = std::stoi(abc_sname);
 | 
			
		||||
			for (auto sig : signal_list) {
 | 
			
		||||
				if (sig.id == sid && sig.bit.wire != nullptr) {
 | 
			
		||||
					std::stringstream sstr;
 | 
			
		||||
					sstr << "$abc$" << map_autoidx << "$" << sig.bit.wire->name.substr(1);
 | 
			
		||||
					if (sig.bit.wire->width != 1)
 | 
			
		||||
						sstr << "[" << sig.bit.offset << "]";
 | 
			
		||||
					if (inv)
 | 
			
		||||
						sstr << "_inv";
 | 
			
		||||
					if (orig_wire != nullptr)
 | 
			
		||||
						*orig_wire = sig.bit.wire;
 | 
			
		||||
					return sstr.str();
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -731,10 +735,6 @@ void abc_module(RTLIL::Design *design, RTLIL::Module *current_module, std::strin
 | 
			
		|||
	else
 | 
			
		||||
		abc_script += fast_mode ? ABC_FAST_COMMAND_DFL : ABC_COMMAND_DFL;
 | 
			
		||||
 | 
			
		||||
	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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1726,7 +1726,7 @@ struct AbcPass : public Pass {
 | 
			
		|||
								signal_init[initsig[i]] = State::S0;
 | 
			
		||||
								break;
 | 
			
		||||
							case State::S1:
 | 
			
		||||
								signal_init[initsig[i]] = State::S0;
 | 
			
		||||
								signal_init[initsig[i]] = State::S1;
 | 
			
		||||
								break;
 | 
			
		||||
							default:
 | 
			
		||||
								break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -111,9 +111,10 @@ struct AttrmapMap : AttrmapAction {
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
struct AttrmapRemove : AttrmapAction {
 | 
			
		||||
	bool has_value;
 | 
			
		||||
	string name, value;
 | 
			
		||||
	bool apply(IdString &id, Const &val) YS_OVERRIDE {
 | 
			
		||||
		return !(match_name(name, id) && match_value(value, val));
 | 
			
		||||
		return !(match_name(name, id) && (!has_value || match_value(value, val)));
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -235,6 +236,7 @@ struct AttrmapPass : public Pass {
 | 
			
		|||
				}
 | 
			
		||||
				auto action = new AttrmapRemove;
 | 
			
		||||
				action->name = arg1;
 | 
			
		||||
				action->has_value = (p != string::npos);
 | 
			
		||||
				action->value = val1;
 | 
			
		||||
				actions.push_back(std::unique_ptr<AttrmapAction>(action));
 | 
			
		||||
				continue;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -664,7 +664,7 @@ struct DfflibmapPass : public Pass {
 | 
			
		|||
		logmap_all();
 | 
			
		||||
 | 
			
		||||
		for (auto &it : design->modules_)
 | 
			
		||||
			if (design->selected(it.second) && !it.second->get_bool_attribute("\\blackbox"))
 | 
			
		||||
			if (design->selected(it.second) && !it.second->get_blackbox_attribute())
 | 
			
		||||
				dfflibmap(design, it.second, prepare_mode);
 | 
			
		||||
 | 
			
		||||
		cell_mappings.clear();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,82 +0,0 @@
 | 
			
		|||
/*
 | 
			
		||||
 *  yosys -- Yosys Open SYnthesis Suite
 | 
			
		||||
 *
 | 
			
		||||
 *  Copyright (C) 2012  Clifford Wolf <clifford@clifford.at>
 | 
			
		||||
 *
 | 
			
		||||
 *  Permission to use, copy, modify, and/or distribute this software for any
 | 
			
		||||
 *  purpose with or without fee is hereby granted, provided that the above
 | 
			
		||||
 *  copyright notice and this permission notice appear in all copies.
 | 
			
		||||
 *
 | 
			
		||||
 *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 | 
			
		||||
 *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
 | 
			
		||||
 *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
 | 
			
		||||
 *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 | 
			
		||||
 *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
 | 
			
		||||
 *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
 | 
			
		||||
 *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "kernel/yosys.h"
 | 
			
		||||
#include "kernel/sigtools.h"
 | 
			
		||||
 | 
			
		||||
USING_YOSYS_NAMESPACE
 | 
			
		||||
PRIVATE_NAMESPACE_BEGIN
 | 
			
		||||
 | 
			
		||||
struct Pmux2ShiftxPass : public Pass {
 | 
			
		||||
	Pmux2ShiftxPass() : Pass("pmux2shiftx", "transform $pmux cells to $shiftx cells") { }
 | 
			
		||||
	void help() YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    pmux2shiftx [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("This pass transforms $pmux cells to $shiftx cells.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing PMUX2SHIFTX pass.\n");
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++) {
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
		for (auto module : design->selected_modules())
 | 
			
		||||
		for (auto cell : module->selected_cells())
 | 
			
		||||
		{
 | 
			
		||||
			if (cell->type != "$pmux")
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			// Create a new encoder, out of a $pmux, that takes
 | 
			
		||||
			// the existing pmux's 'S' input and transforms it
 | 
			
		||||
			// back into a binary value
 | 
			
		||||
			RTLIL::SigSpec shiftx_a;
 | 
			
		||||
			RTLIL::SigSpec pmux_s;
 | 
			
		||||
 | 
			
		||||
			int s_width = cell->getParam("\\S_WIDTH").as_int();
 | 
			
		||||
			if (!cell->getPort("\\A").is_fully_undef()) {
 | 
			
		||||
				++s_width;
 | 
			
		||||
				shiftx_a.append(cell->getPort("\\A"));
 | 
			
		||||
				pmux_s.append(module->Not(NEW_ID, module->ReduceOr(NEW_ID, cell->getPort("\\S"))));
 | 
			
		||||
			}
 | 
			
		||||
			const int clog2width = ceil(log2(s_width));
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec pmux_b;
 | 
			
		||||
			pmux_b.append(RTLIL::Const(0, clog2width));
 | 
			
		||||
			for (int i = s_width-1; i > 0; i--)
 | 
			
		||||
				pmux_b.append(RTLIL::Const(i, clog2width));
 | 
			
		||||
			shiftx_a.append(cell->getPort("\\B"));
 | 
			
		||||
			pmux_s.append(cell->getPort("\\S"));
 | 
			
		||||
 | 
			
		||||
			RTLIL::SigSpec pmux_y = module->addWire(NEW_ID, clog2width);
 | 
			
		||||
			module->addPmux(NEW_ID, RTLIL::Const(RTLIL::Sx, clog2width), pmux_b, pmux_s, pmux_y);
 | 
			
		||||
			module->addShiftx(NEW_ID, shiftx_a, pmux_y, cell->getPort("\\Y"));
 | 
			
		||||
			module->remove(cell);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
} Pmux2ShiftxPass;
 | 
			
		||||
 | 
			
		||||
PRIVATE_NAMESPACE_END
 | 
			
		||||
| 
						 | 
				
			
			@ -26,7 +26,9 @@ PRIVATE_NAMESPACE_BEGIN
 | 
			
		|||
struct ShregmapTech
 | 
			
		||||
{
 | 
			
		||||
	virtual ~ShregmapTech() { }
 | 
			
		||||
	virtual bool analyze(vector<int> &taps) = 0;
 | 
			
		||||
	virtual void init(const Module * /*module*/, const SigMap &/*sigmap*/) {}
 | 
			
		||||
	virtual void non_chain_user(const SigBit &/*bit*/, const Cell* /*cell*/, IdString /*port*/) {}
 | 
			
		||||
	virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) = 0;
 | 
			
		||||
	virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) = 0;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +56,7 @@ struct ShregmapOptions
 | 
			
		|||
 | 
			
		||||
struct ShregmapTechGreenpak4 : ShregmapTech
 | 
			
		||||
{
 | 
			
		||||
	bool analyze(vector<int> &taps)
 | 
			
		||||
	bool analyze(vector<int> &taps, const vector<SigBit> &/*qbits*/)
 | 
			
		||||
	{
 | 
			
		||||
		if (GetSize(taps) > 2 && taps[0] == 0 && taps[2] < 17) {
 | 
			
		||||
			taps.clear();
 | 
			
		||||
| 
						 | 
				
			
			@ -91,6 +93,145 @@ struct ShregmapTechGreenpak4 : ShregmapTech
 | 
			
		|||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ShregmapTechXilinx7 : ShregmapTech
 | 
			
		||||
{
 | 
			
		||||
	dict<SigBit, std::tuple<Cell*,int,int>> sigbit_to_shiftx_offset;
 | 
			
		||||
	const ShregmapOptions &opts;
 | 
			
		||||
 | 
			
		||||
	ShregmapTechXilinx7(const ShregmapOptions &opts) : opts(opts) {}
 | 
			
		||||
 | 
			
		||||
	virtual void init(const Module* module, const SigMap &sigmap) override
 | 
			
		||||
	{
 | 
			
		||||
		for (const auto &i : module->cells_) {
 | 
			
		||||
			auto cell = i.second;
 | 
			
		||||
			if (cell->type == "$shiftx") {
 | 
			
		||||
				if (cell->getParam("\\Y_WIDTH") != 1) continue;
 | 
			
		||||
				int j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\A")))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, j++, 0);
 | 
			
		||||
				log_assert(j == cell->getParam("\\A_WIDTH").as_int());
 | 
			
		||||
			}
 | 
			
		||||
			else if (cell->type == "$mux") {
 | 
			
		||||
				int j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\A")))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 0, j++);
 | 
			
		||||
				j = 0;
 | 
			
		||||
				for (auto bit : sigmap(cell->getPort("\\B")))
 | 
			
		||||
					sigbit_to_shiftx_offset[bit] = std::make_tuple(cell, 1, j++);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual void non_chain_user(const SigBit &bit, const Cell *cell, IdString port) override
 | 
			
		||||
	{
 | 
			
		||||
		auto it = sigbit_to_shiftx_offset.find(bit);
 | 
			
		||||
		if (it == sigbit_to_shiftx_offset.end())
 | 
			
		||||
			return;
 | 
			
		||||
		if (cell) {
 | 
			
		||||
			if (cell->type == "$shiftx" && port == "\\A")
 | 
			
		||||
				return;
 | 
			
		||||
			if (cell->type == "$mux" && (port == "\\A" || port == "\\B"))
 | 
			
		||||
				return;
 | 
			
		||||
		}
 | 
			
		||||
		sigbit_to_shiftx_offset.erase(it);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual bool analyze(vector<int> &taps, const vector<SigBit> &qbits) override
 | 
			
		||||
	{
 | 
			
		||||
		if (GetSize(taps) == 1)
 | 
			
		||||
			return taps[0] >= opts.minlen-1 && sigbit_to_shiftx_offset.count(qbits[0]);
 | 
			
		||||
 | 
			
		||||
		if (taps.back() < opts.minlen-1)
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		Cell *shiftx = nullptr;
 | 
			
		||||
		int group = 0;
 | 
			
		||||
		for (int i = 0; i < GetSize(taps); ++i) {
 | 
			
		||||
			auto it = sigbit_to_shiftx_offset.find(qbits[i]);
 | 
			
		||||
			if (it == sigbit_to_shiftx_offset.end())
 | 
			
		||||
				return false;
 | 
			
		||||
 | 
			
		||||
			// Check taps are sequential
 | 
			
		||||
			if (i != taps[i])
 | 
			
		||||
				return false;
 | 
			
		||||
			// Check taps are not connected to a shift register,
 | 
			
		||||
			// or sequential to the same shift register
 | 
			
		||||
			if (i == 0) {
 | 
			
		||||
				int offset;
 | 
			
		||||
				std::tie(shiftx,offset,group) = it->second;
 | 
			
		||||
				if (offset != i)
 | 
			
		||||
					return false;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				Cell *shiftx_ = std::get<0>(it->second);
 | 
			
		||||
				if (shiftx_ != shiftx)
 | 
			
		||||
					return false;
 | 
			
		||||
				int offset = std::get<1>(it->second);
 | 
			
		||||
				if (offset != i)
 | 
			
		||||
					return false;
 | 
			
		||||
				int group_ = std::get<2>(it->second);
 | 
			
		||||
				if (group_ != group)
 | 
			
		||||
					return false;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		log_assert(shiftx);
 | 
			
		||||
 | 
			
		||||
		// Only map if $shiftx exclusively covers the shift register
 | 
			
		||||
		if (shiftx->type == "$shiftx") {
 | 
			
		||||
			if (GetSize(taps) != shiftx->getParam("\\A_WIDTH").as_int())
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
		else if (shiftx->type == "$mux") {
 | 
			
		||||
			if (GetSize(taps) != 2)
 | 
			
		||||
				return false;
 | 
			
		||||
		}
 | 
			
		||||
		else log_abort();
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual bool fixup(Cell *cell, dict<int, SigBit> &taps) override
 | 
			
		||||
	{
 | 
			
		||||
		const auto &tap = *taps.begin();
 | 
			
		||||
		auto bit = tap.second;
 | 
			
		||||
 | 
			
		||||
		auto it = sigbit_to_shiftx_offset.find(bit);
 | 
			
		||||
		log_assert(it != sigbit_to_shiftx_offset.end());
 | 
			
		||||
 | 
			
		||||
		auto newcell = cell->module->addCell(NEW_ID, "$__XILINX_SHREG_");
 | 
			
		||||
		newcell->set_src_attribute(cell->get_src_attribute());
 | 
			
		||||
		newcell->setParam("\\DEPTH", cell->getParam("\\DEPTH"));
 | 
			
		||||
		newcell->setParam("\\INIT", cell->getParam("\\INIT"));
 | 
			
		||||
		newcell->setParam("\\CLKPOL", cell->getParam("\\CLKPOL"));
 | 
			
		||||
		newcell->setParam("\\ENPOL", cell->getParam("\\ENPOL"));
 | 
			
		||||
 | 
			
		||||
		newcell->setPort("\\C", cell->getPort("\\C"));
 | 
			
		||||
		newcell->setPort("\\D", cell->getPort("\\D"));
 | 
			
		||||
		if (cell->hasPort("\\E"))
 | 
			
		||||
			newcell->setPort("\\E", cell->getPort("\\E"));
 | 
			
		||||
 | 
			
		||||
		Cell* shiftx = std::get<0>(it->second);
 | 
			
		||||
		RTLIL::SigSpec l_wire, q_wire;
 | 
			
		||||
		if (shiftx->type == "$shiftx") {
 | 
			
		||||
			l_wire = shiftx->getPort("\\B");
 | 
			
		||||
			q_wire = shiftx->getPort("\\Y");
 | 
			
		||||
			shiftx->setPort("\\Y", cell->module->addWire(NEW_ID));
 | 
			
		||||
		}
 | 
			
		||||
		else if (shiftx->type == "$mux") {
 | 
			
		||||
			l_wire = shiftx->getPort("\\S");
 | 
			
		||||
			q_wire = shiftx->getPort("\\Y");
 | 
			
		||||
			shiftx->setPort("\\Y", cell->module->addWire(NEW_ID));
 | 
			
		||||
		}
 | 
			
		||||
		else log_abort();
 | 
			
		||||
 | 
			
		||||
		newcell->setPort("\\Q", q_wire);
 | 
			
		||||
		newcell->setPort("\\L", l_wire);
 | 
			
		||||
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct ShregmapWorker
 | 
			
		||||
{
 | 
			
		||||
	Module *module;
 | 
			
		||||
| 
						 | 
				
			
			@ -113,8 +254,10 @@ struct ShregmapWorker
 | 
			
		|||
		for (auto wire : module->wires())
 | 
			
		||||
		{
 | 
			
		||||
			if (wire->port_output || wire->get_bool_attribute("\\keep")) {
 | 
			
		||||
				for (auto bit : sigmap(wire))
 | 
			
		||||
				for (auto bit : sigmap(wire)) {
 | 
			
		||||
					sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
					if (opts.tech) opts.tech->non_chain_user(bit, nullptr, {});
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (wire->attributes.count("\\init")) {
 | 
			
		||||
| 
						 | 
				
			
			@ -152,8 +295,10 @@ struct ShregmapWorker
 | 
			
		|||
 | 
			
		||||
			for (auto conn : cell->connections())
 | 
			
		||||
				if (cell->input(conn.first))
 | 
			
		||||
					for (auto bit : sigmap(conn.second))
 | 
			
		||||
					for (auto bit : sigmap(conn.second)) {
 | 
			
		||||
						sigbit_with_non_chain_users.insert(bit);
 | 
			
		||||
						if (opts.tech) opts.tech->non_chain_user(bit, cell, conn.first);
 | 
			
		||||
					}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -258,7 +403,7 @@ struct ShregmapWorker
 | 
			
		|||
					if (taps.empty() || taps.back() < depth-1)
 | 
			
		||||
						taps.push_back(depth-1);
 | 
			
		||||
 | 
			
		||||
					if (opts.tech->analyze(taps))
 | 
			
		||||
					if (opts.tech->analyze(taps, qbits))
 | 
			
		||||
						break;
 | 
			
		||||
 | 
			
		||||
					taps.pop_back();
 | 
			
		||||
| 
						 | 
				
			
			@ -377,6 +522,9 @@ struct ShregmapWorker
 | 
			
		|||
	ShregmapWorker(Module *module, const ShregmapOptions &opts) :
 | 
			
		||||
			module(module), sigmap(module), opts(opts), dff_count(0), shreg_count(0)
 | 
			
		||||
	{
 | 
			
		||||
		if (opts.tech)
 | 
			
		||||
			opts.tech->init(module, sigmap);
 | 
			
		||||
 | 
			
		||||
		make_sigbit_chain_next_prev();
 | 
			
		||||
		find_chain_start_cells();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -501,6 +649,12 @@ struct ShregmapPass : public Pass {
 | 
			
		|||
					clkpol = "pos";
 | 
			
		||||
					opts.zinit = true;
 | 
			
		||||
					opts.tech = new ShregmapTechGreenpak4;
 | 
			
		||||
				}
 | 
			
		||||
				else if (tech == "xilinx") {
 | 
			
		||||
					opts.init = true;
 | 
			
		||||
					opts.params = true;
 | 
			
		||||
					enpol = "any_or_none";
 | 
			
		||||
					opts.tech = new ShregmapTechXilinx7(opts);
 | 
			
		||||
				} else {
 | 
			
		||||
					argidx--;
 | 
			
		||||
					break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -599,7 +599,7 @@ struct SimplemapPass : public Pass {
 | 
			
		|||
		simplemap_get_mappers(mappers);
 | 
			
		||||
 | 
			
		||||
		for (auto mod : design->modules()) {
 | 
			
		||||
			if (!design->selected(mod))
 | 
			
		||||
			if (!design->selected(mod) || mod->get_blackbox_attribute())
 | 
			
		||||
				continue;
 | 
			
		||||
			std::vector<RTLIL::Cell*> cells = mod->cells();
 | 
			
		||||
			for (auto cell : cells) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,6 +84,7 @@ struct TechmapWorker
 | 
			
		|||
	bool flatten_mode;
 | 
			
		||||
	bool recursive_mode;
 | 
			
		||||
	bool autoproc_mode;
 | 
			
		||||
	bool ignore_wb;
 | 
			
		||||
 | 
			
		||||
	TechmapWorker()
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -92,6 +93,7 @@ struct TechmapWorker
 | 
			
		|||
		flatten_mode = false;
 | 
			
		||||
		recursive_mode = false;
 | 
			
		||||
		autoproc_mode = false;
 | 
			
		||||
		ignore_wb = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	std::string constmap_tpl_name(SigMap &sigmap, RTLIL::Module *tpl, RTLIL::Cell *cell, bool verbose)
 | 
			
		||||
| 
						 | 
				
			
			@ -383,7 +385,7 @@ struct TechmapWorker
 | 
			
		|||
	{
 | 
			
		||||
		std::string mapmsg_prefix = in_recursion ? "Recursively mapping" : "Mapping";
 | 
			
		||||
 | 
			
		||||
		if (!design->selected(module))
 | 
			
		||||
		if (!design->selected(module) || module->get_blackbox_attribute(ignore_wb))
 | 
			
		||||
			return false;
 | 
			
		||||
 | 
			
		||||
		bool log_continue = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -472,7 +474,7 @@ struct TechmapWorker
 | 
			
		|||
				RTLIL::Module *tpl = map->modules_[tpl_name];
 | 
			
		||||
				std::map<RTLIL::IdString, RTLIL::Const> parameters(cell->parameters.begin(), cell->parameters.end());
 | 
			
		||||
 | 
			
		||||
				if (tpl->get_bool_attribute("\\blackbox"))
 | 
			
		||||
				if (tpl->get_blackbox_attribute(ignore_wb))
 | 
			
		||||
					continue;
 | 
			
		||||
 | 
			
		||||
				if (!flatten_mode)
 | 
			
		||||
| 
						 | 
				
			
			@ -925,6 +927,9 @@ struct TechmapPass : public Pass {
 | 
			
		|||
		log("    -autoproc\n");
 | 
			
		||||
		log("        Automatically call \"proc\" on implementations that contain processes.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -wb\n");
 | 
			
		||||
		log("        Ignore the 'whitebox' attribute on cell implementations.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -assert\n");
 | 
			
		||||
		log("        this option will cause techmap to exit with an error if it can't map\n");
 | 
			
		||||
		log("        a selected cell. only cell types that end on an underscore are accepted\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1031,7 +1036,7 @@ struct TechmapPass : public Pass {
 | 
			
		|||
		simplemap_get_mappers(worker.simplemap_mappers);
 | 
			
		||||
 | 
			
		||||
		std::vector<std::string> map_files;
 | 
			
		||||
		std::string verilog_frontend = "verilog -nooverwrite";
 | 
			
		||||
		std::string verilog_frontend = "verilog -nooverwrite -noblackbox";
 | 
			
		||||
		int max_iter = -1;
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
| 
						 | 
				
			
			@ -1068,6 +1073,10 @@ struct TechmapPass : public Pass {
 | 
			
		|||
				worker.autoproc_mode = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			if (args[argidx] == "-wb") {
 | 
			
		||||
				worker.ignore_wb = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
| 
						 | 
				
			
			@ -1145,7 +1154,7 @@ struct FlattenPass : public Pass {
 | 
			
		|||
	{
 | 
			
		||||
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    flatten [selection]\n");
 | 
			
		||||
		log("    flatten [options] [selection]\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("This pass flattens the design by replacing cells by their implementation. This\n");
 | 
			
		||||
		log("pass is very similar to the 'techmap' pass. The only difference is that this\n");
 | 
			
		||||
| 
						 | 
				
			
			@ -1154,17 +1163,29 @@ struct FlattenPass : public Pass {
 | 
			
		|||
		log("Cells and/or modules with the 'keep_hierarchy' attribute set will not be\n");
 | 
			
		||||
		log("flattened by this command.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
		log("    -wb\n");
 | 
			
		||||
		log("        Ignore the 'whitebox' attribute on cell implementations.\n");
 | 
			
		||||
		log("\n");
 | 
			
		||||
	}
 | 
			
		||||
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
 | 
			
		||||
	{
 | 
			
		||||
		log_header(design, "Executing FLATTEN pass (flatten design).\n");
 | 
			
		||||
		log_push();
 | 
			
		||||
 | 
			
		||||
		extra_args(args, 1, design);
 | 
			
		||||
 | 
			
		||||
		TechmapWorker worker;
 | 
			
		||||
		worker.flatten_mode = true;
 | 
			
		||||
 | 
			
		||||
		size_t argidx;
 | 
			
		||||
		for (argidx = 1; argidx < args.size(); argidx++) {
 | 
			
		||||
			if (args[argidx] == "-wb") {
 | 
			
		||||
				worker.ignore_wb = true;
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
		extra_args(args, argidx, design);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		std::map<RTLIL::IdString, std::set<RTLIL::IdString, RTLIL::sort_by_id_str>> celltypeMap;
 | 
			
		||||
		for (auto module : design->modules())
 | 
			
		||||
			celltypeMap[module->name].insert(module->name);
 | 
			
		||||
| 
						 | 
				
			
			@ -1209,7 +1230,7 @@ struct FlattenPass : public Pass {
 | 
			
		|||
 | 
			
		||||
			dict<RTLIL::IdString, RTLIL::Module*> new_modules;
 | 
			
		||||
			for (auto mod : vector<Module*>(design->modules()))
 | 
			
		||||
				if (used_modules[mod->name] || mod->get_bool_attribute("\\blackbox")) {
 | 
			
		||||
				if (used_modules[mod->name] || mod->get_blackbox_attribute(worker.ignore_wb)) {
 | 
			
		||||
					new_modules[mod->name] = mod;
 | 
			
		||||
				} else {
 | 
			
		||||
					log("Deleting now unused module %s.\n", log_id(mod));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue