/*
 *  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/register.h"
#include "kernel/sigtools.h"
#include "kernel/consteval.h"
#include "kernel/log.h"
#include <sstream>
#include <stdlib.h>
#include <stdio.h>

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

struct proc_dlatch_db_t
{
	Module *module;
	SigMap sigmap;

	pool<Cell*> generated_dlatches;
	dict<Cell*, vector<SigBit>> mux_srcbits;
	dict<SigBit, pair<Cell*, int>> mux_drivers;
	dict<SigBit, int> sigusers;

	proc_dlatch_db_t(Module *module) : module(module), sigmap(module)
	{
		for (auto cell : module->cells())
		{
			if (cell->type.in("$mux", "$pmux"))
			{
				auto sig_y = sigmap(cell->getPort("\\Y"));
				for (int i = 0; i < GetSize(sig_y); i++)
					mux_drivers[sig_y[i]] = pair<Cell*, int>(cell, i);

				pool<SigBit> mux_srcbits_pool;
				for (auto bit : sigmap(cell->getPort("\\A")))
					mux_srcbits_pool.insert(bit);
				for (auto bit : sigmap(cell->getPort("\\B")))
					mux_srcbits_pool.insert(bit);

				vector<SigBit> mux_srcbits_vec;
				for (auto bit : mux_srcbits_pool)
					if (bit.wire != nullptr)
						mux_srcbits_vec.push_back(bit);

				mux_srcbits[cell].swap(mux_srcbits_vec);
			}

			for (auto &conn : cell->connections())
				if (!cell->known() || cell->input(conn.first))
					for (auto bit : sigmap(conn.second))
						sigusers[bit]++;
		}

		for (auto wire : module->wires())
			if (wire->port_input)
				for (auto bit : sigmap(wire))
					sigusers[bit]++;
	}

	bool quickcheck(const SigSpec &haystack, const SigSpec &needle)
	{
		pool<SigBit> haystack_bits = sigmap(haystack).to_sigbit_pool();
		pool<SigBit> needle_bits = sigmap(needle).to_sigbit_pool();

		pool<Cell*> cells_queue, cells_visited;
		pool<SigBit> bits_queue, bits_visited;

		bits_queue = haystack_bits;
		while (!bits_queue.empty())
		{
			for (auto &bit : bits_queue) {
				auto it = mux_drivers.find(bit);
				if (it != mux_drivers.end())
					if (!cells_visited.count(it->second.first))
						cells_queue.insert(it->second.first);
				bits_visited.insert(bit);
			}

			bits_queue.clear();

			for (auto c : cells_queue) {
				for (auto bit : mux_srcbits[c]) {
					if (needle_bits.count(bit))
						return true;
					if (!bits_visited.count(bit))
						bits_queue.insert(bit);
				}
			}

			cells_queue.clear();
		}

		return false;
	}

	struct rule_node_t
	{
		// a node is true if "signal" equals "match" and [any
		// of the child nodes is true or "children" is empty]
		SigBit signal, match;
		vector<int> children;

		bool operator==(const rule_node_t &other) const {
			return signal == other.signal && match == other.match && children == other.children;
		}

		unsigned int hash() const {
			unsigned int h = mkhash_init;
			mkhash(h, signal.hash());
			mkhash(h, match.hash());
			for (auto i : children) mkhash(h, i);
			return h;
		}
	};

	enum tf_node_types_t : int {
		true_node = 1,
		false_node = 2
	};

	idict<rule_node_t, 3> rules_db;
	dict<int, SigBit> rules_sig;

	int make_leaf(SigBit signal, SigBit match)
	{
		rule_node_t node;
		node.signal = signal;
		node.match = match;
		return rules_db(node);
	}

	int make_inner(SigBit signal, SigBit match, int child)
	{
		rule_node_t node;
		node.signal = signal;
		node.match = match;
		node.children.push_back(child);
		return rules_db(node);
	}

	int make_inner(const pool<int> &children)
	{
		rule_node_t node;
		node.signal = State::S0;
		node.match = State::S0;
		node.children = vector<int>(children.begin(), children.end());
		std::sort(node.children.begin(), node.children.end());
		return rules_db(node);
	}

	int find_mux_feedback(SigBit haystack, SigBit needle, bool set_undef)
	{
		if (sigusers[haystack] > 1)
			set_undef = false;

		if (haystack == needle)
			return true_node;

		auto it = mux_drivers.find(haystack);
		if (it == mux_drivers.end())
			return false_node;

		Cell *cell = it->second.first;
		int index = it->second.second;

		SigSpec sig_a = sigmap(cell->getPort("\\A"));
		SigSpec sig_b = sigmap(cell->getPort("\\B"));
		SigSpec sig_s = sigmap(cell->getPort("\\S"));
		int width = GetSize(sig_a);

		pool<int> children;

		int n = find_mux_feedback(sig_a[index], needle, set_undef);
		if (n != false_node) {
			if (set_undef && sig_a[index] == needle) {
				SigSpec sig = cell->getPort("\\A");
				sig[index] = State::Sx;
				cell->setPort("\\A", sig);
			}
			for (int i = 0; i < GetSize(sig_s); i++)
				n = make_inner(sig_s[i], State::S0, n);
			children.insert(n);
		}

		for (int i = 0; i < GetSize(sig_s); i++) {
			n = find_mux_feedback(sig_b[i*width + index], needle, set_undef);
			if (n != false_node) {
				if (set_undef && sig_b[i*width + index] == needle) {
					SigSpec sig = cell->getPort("\\B");
					sig[i*width + index] = State::Sx;
					cell->setPort("\\B", sig);
				}
				children.insert(make_inner(sig_s[i], State::S1, n));
			}
		}

		if (children.empty())
			return false_node;

		return make_inner(children);
	}

	SigBit make_hold(int n, string &src)
	{
		if (n == true_node)
			return State::S1;

		if (n == false_node)
			return State::S0;

		if (rules_sig.count(n))
			return rules_sig.at(n);

		const rule_node_t &rule = rules_db[n];
		SigSpec and_bits;

		if (rule.signal != rule.match) {
			if (rule.match == State::S1)
				and_bits.append(rule.signal);
			else if (rule.match == State::S0)
				and_bits.append(module->Not(NEW_ID, rule.signal, false, src));
			else
				and_bits.append(module->Eq(NEW_ID, rule.signal, rule.match, false, src));
		}

		if (!rule.children.empty()) {
			SigSpec or_bits;
			for (int k : rule.children)
				or_bits.append(make_hold(k, src));
			and_bits.append(module->ReduceOr(NEW_ID, or_bits, false, src));
		}

		if (GetSize(and_bits) == 2)
			and_bits = module->And(NEW_ID, and_bits[0], and_bits[1], false, src);
		log_assert(GetSize(and_bits) == 1);

		rules_sig[n] = and_bits[0];
		return and_bits[0];
	}

	void fixup_mux(Cell *cell)
	{
		SigSpec sig_a = cell->getPort("\\A");
		SigSpec sig_b = cell->getPort("\\B");
		SigSpec sig_s = cell->getPort("\\S");
		SigSpec sig_any_valid_b;

		SigSpec sig_new_b, sig_new_s;
		for (int i = 0; i < GetSize(sig_s); i++) {
			SigSpec b = sig_b.extract(i*GetSize(sig_a), GetSize(sig_a));
			if (!b.is_fully_undef()) {
				sig_any_valid_b = b;
				sig_new_b.append(b);
				sig_new_s.append(sig_s[i]);
			}
		}

		if (sig_new_s.empty()) {
			sig_new_b = sig_a;
			sig_new_s = State::S0;
		}

		if (sig_a.is_fully_undef() && !sig_any_valid_b.empty())
			cell->setPort("\\A", sig_any_valid_b);

		if (GetSize(sig_new_s) == 1) {
			cell->type = "$mux";
			cell->unsetParam("\\S_WIDTH");
		} else {
			cell->type = "$pmux";
			cell->setParam("\\S_WIDTH", GetSize(sig_new_s));
		}

		cell->setPort("\\B", sig_new_b);
		cell->setPort("\\S", sig_new_s);
	}

	void fixup_muxes()
	{
		pool<Cell*> visited, queue;
		dict<Cell*, pool<SigBit>> upstream_cell2net;
		dict<SigBit, pool<Cell*>> upstream_net2cell;

		CellTypes ct;
		ct.setup_internals();

		for (auto cell : module->cells())
		for (auto conn : cell->connections()) {
			if (cell->input(conn.first))
				for (auto bit : sigmap(conn.second))
					upstream_cell2net[cell].insert(bit);
			if (cell->output(conn.first))
				for (auto bit : sigmap(conn.second))
					upstream_net2cell[bit].insert(cell);
		}

		queue = generated_dlatches;
		while (!queue.empty())
		{
			pool<Cell*> next_queue;

			for (auto cell : queue) {
				if (cell->type.in("$mux", "$pmux"))
					fixup_mux(cell);
				for (auto bit : upstream_cell2net[cell])
					for (auto cell : upstream_net2cell[bit])
						next_queue.insert(cell);
				visited.insert(cell);
			}

			queue.clear();
			for (auto cell : next_queue) {
				if (!visited.count(cell) && ct.cell_known(cell->type))
					queue.insert(cell);
			}
		}
	}
};

void proc_dlatch(proc_dlatch_db_t &db, RTLIL::Process *proc)
{
	std::vector<RTLIL::SyncRule*> new_syncs;
	RTLIL::SigSig latches_bits, nolatches_bits;
	dict<SigBit, SigBit> latches_out_in;
	dict<SigBit, int> latches_hold;
	std::string src = proc->get_src_attribute();

	for (auto sr : proc->syncs)
	{
		if (sr->type != RTLIL::SyncType::STa) {
			new_syncs.push_back(sr);
			continue;
		}

		if (proc->get_bool_attribute(ID(always_ff)))
			log_error("Found non edge/level sensitive event in always_ff process `%s.%s'.\n",
					db.module->name.c_str(), proc->name.c_str());

		for (auto ss : sr->actions)
		{
			db.sigmap.apply(ss.first);
			db.sigmap.apply(ss.second);

			if (!db.quickcheck(ss.second, ss.first)) {
				nolatches_bits.first.append(ss.first);
				nolatches_bits.second.append(ss.second);
				continue;
			}

			for (int i = 0; i < GetSize(ss.first); i++)
				latches_out_in[ss.first[i]] = ss.second[i];
		}

		delete sr;
	}

	latches_out_in.sort();
	for (auto &it : latches_out_in) {
		int n = db.find_mux_feedback(it.second, it.first, true);
		if (n == db.false_node) {
			nolatches_bits.first.append(it.first);
			nolatches_bits.second.append(it.second);
		} else {
			latches_bits.first.append(it.first);
			latches_bits.second.append(it.second);
			latches_hold[it.first] = n;
		}
	}

	int offset = 0;
	for (auto chunk : nolatches_bits.first.chunks()) {
		SigSpec lhs = chunk, rhs = nolatches_bits.second.extract(offset, chunk.width);
		if (proc->get_bool_attribute(ID(always_latch)))
			log_error("No latch inferred for signal `%s.%s' from always_latch process `%s.%s'.\n",
					db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
		else
			log("No latch inferred for signal `%s.%s' from process `%s.%s'.\n",
					db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
		db.module->connect(lhs, rhs);
		offset += chunk.width;
	}

	offset = 0;
	while (offset < GetSize(latches_bits.first))
	{
		int width = 1;
		int n = latches_hold[latches_bits.first[offset]];
		Wire *w = latches_bits.first[offset].wire;

		if (w != nullptr)
		{
			while (offset+width < GetSize(latches_bits.first) &&
					n == latches_hold[latches_bits.first[offset+width]] &&
					w == latches_bits.first[offset+width].wire)
				width++;

			SigSpec lhs = latches_bits.first.extract(offset, width);
			SigSpec rhs = latches_bits.second.extract(offset, width);

			Cell *cell = db.module->addDlatch(NEW_ID, db.module->Not(NEW_ID, db.make_hold(n, src)), rhs, lhs);
			cell->set_src_attribute(src);
			db.generated_dlatches.insert(cell);

			if (proc->get_bool_attribute(ID(always_comb)))
				log_error("Latch inferred for signal `%s.%s' from always_comb process `%s.%s'.\n",
						db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str());
			else
				log("Latch inferred for signal `%s.%s' from process `%s.%s': %s\n",
						db.module->name.c_str(), log_signal(lhs), db.module->name.c_str(), proc->name.c_str(), log_id(cell));
		}

		offset += width;
	}

	new_syncs.swap(proc->syncs);
}

struct ProcDlatchPass : public Pass {
	ProcDlatchPass() : Pass("proc_dlatch", "extract latches from processes") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    proc_dlatch [selection]\n");
		log("\n");
		log("This pass identifies latches in the processes and converts them to\n");
		log("d-type latches.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		log_header(design, "Executing PROC_DLATCH pass (convert process syncs to latches).\n");

		extra_args(args, 1, design);

		for (auto module : design->selected_modules()) {
			proc_dlatch_db_t db(module);
			for (auto &proc_it : module->processes)
				if (design->selected(module, proc_it.second))
					proc_dlatch(db, proc_it.second);
			db.fixup_muxes();
		}
	}
} ProcDlatchPass;

PRIVATE_NAMESPACE_END
