/* -*- c++ -*-
 *  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.
 *
 */

#ifndef MODTOOLS_H
#define MODTOOLS_H

#include "kernel/yosys.h"
#include "kernel/sigtools.h"
#include "kernel/celltypes.h"

YOSYS_NAMESPACE_BEGIN

struct ModIndex : public RTLIL::Monitor
{
	struct PortInfo {
		RTLIL::Cell* cell;
		RTLIL::IdString port;
		int offset;

		PortInfo() : cell(), port(), offset() { }
		PortInfo(RTLIL::Cell* _c, RTLIL::IdString _p, int _o) : cell(_c), port(_p), offset(_o) { }

		bool operator<(const PortInfo &other) const {
			if (cell != other.cell)
				return cell < other.cell;
			if (offset != other.offset)
				return offset < other.offset;
			return port < other.port;
		}

		bool operator==(const PortInfo &other) const {
			return cell == other.cell && port == other.port && offset == other.offset;
		}

		unsigned int hash() const {
			return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
		}
	};

	struct SigBitInfo
	{
		bool is_input, is_output;
		pool<PortInfo> ports;

		SigBitInfo() : is_input(false), is_output(false) { }

		bool operator==(const SigBitInfo &other) const {
			return is_input == other.is_input && is_output == other.is_output && ports == other.ports;
		}

		void merge(const SigBitInfo &other)
		{
			is_input = is_input || other.is_input;
			is_output = is_output || other.is_output;
			ports.insert(other.ports.begin(), other.ports.end());
		}
	};

	SigMap sigmap;
	RTLIL::Module *module;
	std::map<RTLIL::SigBit, SigBitInfo> database;
	int auto_reload_counter;
	bool auto_reload_module;

	void port_add(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig)
	{
		for (int i = 0; i < GetSize(sig); i++) {
			RTLIL::SigBit bit = sigmap(sig[i]);
			if (bit.wire)
				database[bit].ports.insert(PortInfo(cell, port, i));
		}
	}

	void port_del(RTLIL::Cell *cell, RTLIL::IdString port, const RTLIL::SigSpec &sig)
	{
		for (int i = 0; i < GetSize(sig); i++) {
			RTLIL::SigBit bit = sigmap(sig[i]);
			if (bit.wire)
				database[bit].ports.erase(PortInfo(cell, port, i));
		}
	}

	const SigBitInfo &info(RTLIL::SigBit bit)
	{
		return database[sigmap(bit)];
	}

	void reload_module(bool reset_sigmap = true)
	{
		if (reset_sigmap) {
			sigmap.clear();
			sigmap.set(module);
		}

		database.clear();
		for (auto wire : module->wires())
			if (wire->port_input || wire->port_output)
				for (int i = 0; i < GetSize(wire); i++) {
					RTLIL::SigBit bit = sigmap(RTLIL::SigBit(wire, i));
					if (bit.wire && wire->port_input)
						database[bit].is_input = true;
					if (bit.wire && wire->port_output)
						database[bit].is_output = true;
				}
		for (auto cell : module->cells())
			for (auto &conn : cell->connections())
				port_add(cell, conn.first, conn.second);

		if (auto_reload_module) {
			if (++auto_reload_counter > 2)
				log_warning("Auto-reload in ModIndex -- possible performance bug!\n");
			auto_reload_module = false;
		}
	}

	void check()
	{
#ifndef NDEBUG
		if (auto_reload_module)
			return;

		for (auto it : database)
			log_assert(it.first == sigmap(it.first));

		auto database_bak = std::move(database);
		reload_module(false);

		if (!(database == database_bak))
		{
			for (auto &it : database_bak)
				if (!database.count(it.first))
					log("ModuleIndex::check(): Only in database_bak, not database: %s\n", log_signal(it.first));

			for (auto &it : database)
				if (!database_bak.count(it.first))
					log("ModuleIndex::check(): Only in database, not database_bak: %s\n", log_signal(it.first));
				else if (!(it.second == database_bak.at(it.first)))
					log("ModuleIndex::check(): Different content for database[%s].\n", log_signal(it.first));

			log_assert(database == database_bak);
		}
#endif
	}

	void notify_connect(RTLIL::Cell *cell, const RTLIL::IdString &port, const RTLIL::SigSpec &old_sig, RTLIL::SigSpec &sig) YS_OVERRIDE
	{
		log_assert(module == cell->module);

		if (auto_reload_module)
			return;

		port_del(cell, port, old_sig);
		port_add(cell, port, sig);
	}

	void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const RTLIL::SigSig &sigsig) YS_OVERRIDE
	{
		log_assert(module == mod);

		if (auto_reload_module)
			return;

		for (int i = 0; i < GetSize(sigsig.first); i++)
		{
			RTLIL::SigBit lhs = sigmap(sigsig.first[i]);
			RTLIL::SigBit rhs = sigmap(sigsig.second[i]);
			bool has_lhs = database.count(lhs) != 0;
			bool has_rhs = database.count(rhs) != 0;

			if (!has_lhs && !has_rhs) {
				sigmap.add(lhs, rhs);
			} else
			if (!has_rhs) {
				SigBitInfo new_info = database.at(lhs);
				database.erase(lhs);
				sigmap.add(lhs, rhs);
				lhs = sigmap(lhs);
				if (lhs.wire)
					database[lhs] = new_info;
			} else
			if (!has_lhs) {
				SigBitInfo new_info = database.at(rhs);
				database.erase(rhs);
				sigmap.add(lhs, rhs);
				rhs = sigmap(rhs);
				if (rhs.wire)
					database[rhs] = new_info;
			} else {
				SigBitInfo new_info = database.at(lhs);
				new_info.merge(database.at(rhs));
				database.erase(lhs);
				database.erase(rhs);
				sigmap.add(lhs, rhs);
				rhs = sigmap(rhs);
				if (rhs.wire)
					database[rhs] = new_info;
			}
		}
	}

	void notify_connect(RTLIL::Module *mod YS_ATTRIBUTE(unused), const std::vector<RTLIL::SigSig>&) YS_OVERRIDE
	{
		log_assert(module == mod);
		auto_reload_module = true;
	}

	void notify_blackout(RTLIL::Module *mod YS_ATTRIBUTE(unused)) YS_OVERRIDE
	{
		log_assert(module == mod);
		auto_reload_module = true;
	}

	ModIndex(RTLIL::Module *_m) : sigmap(_m), module(_m)
	{
		auto_reload_counter = 0;
		auto_reload_module = true;
		module->monitors.insert(this);
	}

	~ModIndex()
	{
		module->monitors.erase(this);
	}

	SigBitInfo *query(RTLIL::SigBit bit)
	{
		if (auto_reload_module)
			reload_module();

		auto it = database.find(sigmap(bit));
		if (it == database.end())
			return nullptr;
		else
			return &it->second;
	}

	bool query_is_input(RTLIL::SigBit bit)
	{
		const SigBitInfo *info = query(bit);
		if (info == nullptr)
			return false;
		return info->is_input;
	}

	bool query_is_output(RTLIL::SigBit bit)
	{
		const SigBitInfo *info = query(bit);
		if (info == nullptr)
			return false;
		return info->is_output;
	}

	pool<PortInfo> &query_ports(RTLIL::SigBit bit)
	{
		static pool<PortInfo> empty_result_set;
		SigBitInfo *info = query(bit);
		if (info == nullptr)
			return empty_result_set;
		return info->ports;
	}

	void dump_db()
	{
		log("--- ModIndex Dump ---\n");

		if (auto_reload_module) {
			log("AUTO-RELOAD\n");
			reload_module();
		}

		for (auto &it : database) {
			log("BIT %s:\n", log_signal(it.first));
			if (it.second.is_input)
				log("  PRIMARY INPUT\n");
			if (it.second.is_output)
				log("  PRIMARY OUTPUT\n");
			for (auto &port : it.second.ports)
				log("  PORT: %s.%s[%d] (%s)\n", log_id(port.cell),
						log_id(port.port), port.offset, log_id(port.cell->type));
		}
	}
};

struct ModWalker
{
	struct PortBit
	{
		RTLIL::Cell *cell;
		RTLIL::IdString port;
		int offset;

		bool operator<(const PortBit &other) const {
			if (cell != other.cell)
				return cell < other.cell;
			if (port != other.port)
				return port < other.port;
			return offset < other.offset;
		}

		bool operator==(const PortBit &other) const {
			return cell == other.cell && port == other.port && offset == other.offset;
		}

		unsigned int hash() const {
			return mkhash_add(mkhash(cell->name.hash(), port.hash()), offset);
		}
	};

	RTLIL::Design *design;
	RTLIL::Module *module;

	CellTypes ct;
	SigMap sigmap;

	dict<RTLIL::SigBit, pool<PortBit>> signal_drivers;
	dict<RTLIL::SigBit, pool<PortBit>> signal_consumers;
	pool<RTLIL::SigBit> signal_inputs, signal_outputs;

	dict<RTLIL::Cell*, pool<RTLIL::SigBit>> cell_outputs, cell_inputs;

	void add_wire(RTLIL::Wire *wire)
	{
		if (wire->port_input) {
			std::vector<RTLIL::SigBit> bits = sigmap(wire);
			for (auto bit : bits)
				if (bit.wire != NULL)
					signal_inputs.insert(bit);
		}

		if (wire->port_output) {
			std::vector<RTLIL::SigBit> bits = sigmap(wire);
			for (auto bit : bits)
				if (bit.wire != NULL)
					signal_outputs.insert(bit);
		}
	}

	void add_cell_port(RTLIL::Cell *cell, RTLIL::IdString port, std::vector<RTLIL::SigBit> bits, bool is_output, bool is_input)
	{
		for (int i = 0; i < int(bits.size()); i++)
			if (bits[i].wire != NULL) {
				PortBit pbit = { cell, port, i };
				if (is_output) {
					signal_drivers[bits[i]].insert(pbit);
					cell_outputs[cell].insert(bits[i]);
				}
				if (is_input) {
					signal_consumers[bits[i]].insert(pbit);
					cell_inputs[cell].insert(bits[i]);
				}
			}
	}

	void add_cell(RTLIL::Cell *cell)
	{
		if (ct.cell_known(cell->type)) {
			for (auto &conn : cell->connections())
				add_cell_port(cell, conn.first, sigmap(conn.second),
						ct.cell_output(cell->type, conn.first),
						ct.cell_input(cell->type, conn.first));
		} else {
			for (auto &conn : cell->connections())
				add_cell_port(cell, conn.first, sigmap(conn.second), true, true);
		}
	}

	ModWalker() : design(NULL), module(NULL)
	{
	}

	ModWalker(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
	{
		setup(design, module, filter_ct);
	}

	void setup(RTLIL::Design *design, RTLIL::Module *module, CellTypes *filter_ct = NULL)
	{
		this->design = design;
		this->module = module;

		ct.clear();
		ct.setup(design);
		sigmap.set(module);

		signal_drivers.clear();
		signal_consumers.clear();
		signal_inputs.clear();
		signal_outputs.clear();

		for (auto &it : module->wires_)
			add_wire(it.second);
		for (auto &it : module->cells_)
			if (filter_ct == NULL || filter_ct->cell_known(it.second->type))
				add_cell(it.second);
	}

	// get_* methods -- single RTLIL::SigBit

	template<typename T>
	inline bool get_drivers(pool<PortBit> &result, RTLIL::SigBit bit) const
	{
		bool found = false;
		if (signal_drivers.count(bit)) {
			const pool<PortBit> &r = signal_drivers.at(bit);
			result.insert(r.begin(), r.end());
			found = true;
		}
		return found;
	}

	template<typename T>
	inline bool get_consumers(pool<PortBit> &result, RTLIL::SigBit bit) const
	{
		bool found = false;
		if (signal_consumers.count(bit)) {
			const pool<PortBit> &r = signal_consumers.at(bit);
			result.insert(r.begin(), r.end());
			found = true;
		}
		return found;
	}

	template<typename T>
	inline bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const
	{
		bool found = false;
		if (signal_inputs.count(bit))
			result.insert(bit), found = true;
		return found;
	}

	template<typename T>
	inline bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigBit bit) const
	{
		bool found = false;
		if (signal_outputs.count(bit))
			result.insert(bit), found = true;
		return found;
	}

	// get_* methods -- container of RTLIL::SigBit's (always by reference)

	template<typename T>
	inline bool get_drivers(pool<PortBit> &result, const T &bits) const
	{
		bool found = false;
		for (RTLIL::SigBit bit : bits)
			if (signal_drivers.count(bit)) {
				const pool<PortBit> &r = signal_drivers.at(bit);
				result.insert(r.begin(), r.end());
				found = true;
			}
		return found;
	}

	template<typename T>
	inline bool get_consumers(pool<PortBit> &result, const T &bits) const
	{
		bool found = false;
		for (RTLIL::SigBit bit : bits)
			if (signal_consumers.count(bit)) {
				const pool<PortBit> &r = signal_consumers.at(bit);
				result.insert(r.begin(), r.end());
				found = true;
			}
		return found;
	}

	template<typename T>
	inline bool get_inputs(pool<RTLIL::SigBit> &result, const T &bits) const
	{
		bool found = false;
		for (RTLIL::SigBit bit : bits)
			if (signal_inputs.count(bit))
				result.insert(bit), found = true;
		return found;
	}

	template<typename T>
	inline bool get_outputs(pool<RTLIL::SigBit> &result, const T &bits) const
	{
		bool found = false;
		for (RTLIL::SigBit bit : bits)
			if (signal_outputs.count(bit))
				result.insert(bit), found = true;
		return found;
	}

	// get_* methods -- call by RTLIL::SigSpec (always by value)

	bool get_drivers(pool<PortBit> &result, RTLIL::SigSpec signal) const
	{
		std::vector<RTLIL::SigBit> bits = sigmap(signal);
		return get_drivers(result, bits);
	}

	bool get_consumers(pool<PortBit> &result, RTLIL::SigSpec signal) const
	{
		std::vector<RTLIL::SigBit> bits = sigmap(signal);
		return get_consumers(result, bits);
	}

	bool get_inputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const
	{
		std::vector<RTLIL::SigBit> bits = sigmap(signal);
		return get_inputs(result, bits);
	}

	bool get_outputs(pool<RTLIL::SigBit> &result, RTLIL::SigSpec signal) const
	{
		std::vector<RTLIL::SigBit> bits = sigmap(signal);
		return get_outputs(result, bits);
	}

	// has_* methods -- call by reference

	template<typename T>
	inline bool has_drivers(const T &sig) const {
		pool<PortBit> result;
		return get_drivers(result, sig);
	}

	template<typename T>
	inline bool has_consumers(const T &sig) const {
		pool<PortBit> result;
		return get_consumers(result, sig);
	}

	template<typename T>
	inline bool has_inputs(const T &sig) const {
		pool<RTLIL::SigBit> result;
		return get_inputs(result, sig);
	}

	template<typename T>
	inline bool has_outputs(const T &sig) const {
		pool<RTLIL::SigBit> result;
		return get_outputs(result, sig);
	}

	// has_* methods -- call by value

	inline bool has_drivers(RTLIL::SigSpec sig) const {
		pool<PortBit> result;
		return get_drivers(result, sig);
	}

	inline bool has_consumers(RTLIL::SigSpec sig) const {
		pool<PortBit> result;
		return get_consumers(result, sig);
	}

	inline bool has_inputs(RTLIL::SigSpec sig) const {
		pool<RTLIL::SigBit> result;
		return get_inputs(result, sig);
	}

	inline bool has_outputs(RTLIL::SigSpec sig) const {
		pool<RTLIL::SigBit> result;
		return get_outputs(result, sig);
	}
};

YOSYS_NAMESPACE_END

#endif
