/*
 *  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 EquivMarkWorker
{
	Module *module;
	SigMap sigmap;

	// cache for traversing signal flow graph
	dict<SigBit, pool<IdString>> up_bit2cells;
	dict<IdString, pool<SigBit>> up_cell2bits;
	pool<IdString> edge_cells, equiv_cells;

	// graph traversal state
	pool<SigBit> queue, visited;

	// assigned regions
	dict<IdString, int> cell_regions;
	dict<SigBit, int> bit_regions;
	int next_region;

	// merge-find
	mfp<int> region_mf;

	EquivMarkWorker(Module *module) : module(module), sigmap(module)
	{
		for (auto cell : module->cells())
		{
			if (cell->type == "$equiv")
				equiv_cells.insert(cell->name);

			for (auto &port : cell->connections())
			{
				if (cell->input(port.first))
					for (auto bit : sigmap(port.second))
						up_cell2bits[cell->name].insert(bit);

				if (cell->output(port.first))
					for (auto bit : sigmap(port.second))
						up_bit2cells[bit].insert(cell->name);
			}
		}

		next_region = 0;
	}

	void mark()
	{
		while (!queue.empty())
		{
			pool<IdString> cells;

			for (auto &bit : queue)
			{
				// log_assert(bit_regions.count(bit) == 0);
				bit_regions[bit] = next_region;
				visited.insert(bit);

				for (auto cell : up_bit2cells[bit])
					if (edge_cells.count(cell) == 0)
						cells.insert(cell);
			}

			queue.clear();

			for (auto cell : cells)
			{
				if (next_region == 0 && equiv_cells.count(cell))
					continue;

				if (cell_regions.count(cell)) {
					if (cell_regions.at(cell) != 0)
						region_mf.merge(cell_regions.at(cell), next_region);
					continue;
				}

				cell_regions[cell] = next_region;

				for (auto bit : up_cell2bits[cell])
					if (visited.count(bit) == 0)
						queue.insert(bit);
			}
		}

		next_region++;
	}

	void run()
	{
		log("Running equiv_mark on module %s:\n", log_id(module));

		// marking region 0

		for (auto wire : module->wires())
			if (wire->port_id > 0)
				for (auto bit : sigmap(wire))
					queue.insert(bit);

		for (auto cell_name : equiv_cells)
		{
			auto cell = module->cell(cell_name);

			SigSpec sig_a = sigmap(cell->getPort("\\A"));
			SigSpec sig_b = sigmap(cell->getPort("\\B"));

			if (sig_a == sig_b) {
				for (auto bit : sig_a)
					queue.insert(bit);
				edge_cells.insert(cell_name);
				cell_regions[cell_name] = 0;
			}
		}

		mark();

		// marking unsolved regions

		for (auto cell : module->cells())
		{
			if (cell_regions.count(cell->name) || cell->type != "$equiv")
				continue;

			SigSpec sig_a = sigmap(cell->getPort("\\A"));
			SigSpec sig_b = sigmap(cell->getPort("\\B"));

			log_assert(sig_a != sig_b);

			for (auto bit : sig_a)
				queue.insert(bit);

			for (auto bit : sig_b)
				queue.insert(bit);

			cell_regions[cell->name] = next_region;
			mark();
		}

		// setting attributes

		dict<int, int> final_region_map;
		int next_final_region = 0;

		dict<int, int> region_cell_count;
		dict<int, int> region_wire_count;

		for (int i = 0; i < next_region; i++) {
			int r = region_mf.find(i);
			if (final_region_map.count(r) == 0)
				final_region_map[r] = next_final_region++;
			final_region_map[i] = final_region_map[r];
		}

		for (auto cell : module->cells())
		{
			if (cell_regions.count(cell->name)) {
				int r = final_region_map.at(cell_regions.at(cell->name));
				cell->attributes["\\equiv_region"] = Const(r);
				region_cell_count[r]++;
			} else
				cell->attributes.erase("\\equiv_region");
		}

		for (auto wire : module->wires())
		{
			pool<int> regions;
			for (auto bit : sigmap(wire))
				if (bit_regions.count(bit))
					regions.insert(region_mf.find(bit_regions.at(bit)));

			if (GetSize(regions) == 1) {
				int r = final_region_map.at(*regions.begin());
				wire->attributes["\\equiv_region"] = Const(r);
				region_wire_count[r]++;
			} else
				wire->attributes.erase("\\equiv_region");
		}

		for (int i = 0; i < next_final_region; i++)
			log("  region %d: %d cells, %d wires\n", i, region_wire_count[i], region_cell_count[i]);
	}
};

struct EquivMarkPass : public Pass {
	EquivMarkPass() : Pass("equiv_mark", "mark equivalence checking regions") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    equiv_mark [options] [selection]\n");
		log("\n");
		log("This command marks the regions in an equivalence checking module. Region 0 is\n");
		log("the proven part of the circuit. Regions with higher numbers are connected\n");
		log("unproven subcricuits. The integer attribute 'equiv_region' is set on all\n");
		log("wires and cells.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing EQUIV_MARK pass.\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++) {
			// if (args[argidx] == "-foobar") {
			// 	continue;
			// }
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_whole_modules_warn()) {
			EquivMarkWorker worker(module);
			worker.run();
		}
	}
} EquivMarkPass;

PRIVATE_NAMESPACE_END
