/*
 *  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/rtlil.h"
#include "kernel/log.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

void create_miter_equiv(struct Pass *that, std::vector<std::string> args, RTLIL::Design *design)
{
	bool flag_ignore_gold_x = false;
	bool flag_make_outputs = false;
	bool flag_make_outcmp = false;
	bool flag_make_assert = false;
	bool flag_flatten = false;

	log_header(design, "Executing MITER pass (creating miter circuit).\n");

	size_t argidx;
	for (argidx = 2; argidx < args.size(); argidx++)
	{
		if (args[argidx] == "-ignore_gold_x") {
			flag_ignore_gold_x = true;
			continue;
		}
		if (args[argidx] == "-make_outputs") {
			flag_make_outputs = true;
			continue;
		}
		if (args[argidx] == "-make_outcmp") {
			flag_make_outcmp = true;
			continue;
		}
		if (args[argidx] == "-make_assert") {
			flag_make_assert = true;
			continue;
		}
		if (args[argidx] == "-flatten") {
			flag_flatten = true;
			continue;
		}
		break;
	}
	if (argidx+3 != args.size() || args[argidx].compare(0, 1, "-") == 0)
		that->cmd_error(args, argidx, "command argument error");

	RTLIL::IdString gold_name = RTLIL::escape_id(args[argidx++]);
	RTLIL::IdString gate_name = RTLIL::escape_id(args[argidx++]);
	RTLIL::IdString miter_name = RTLIL::escape_id(args[argidx++]);

	if (design->modules_.count(gold_name) == 0)
		log_cmd_error("Can't find gold module %s!\n", gold_name.c_str());
	if (design->modules_.count(gate_name) == 0)
		log_cmd_error("Can't find gate module %s!\n", gate_name.c_str());
	if (design->modules_.count(miter_name) != 0)
		log_cmd_error("There is already a module %s!\n", miter_name.c_str());

	RTLIL::Module *gold_module = design->modules_.at(gold_name);
	RTLIL::Module *gate_module = design->modules_.at(gate_name);

	for (auto &it : gold_module->wires_) {
		RTLIL::Wire *w1 = it.second, *w2;
		if (w1->port_id == 0)
			continue;
		if (gate_module->wires_.count(it.second->name) == 0)
			goto match_gold_port_error;
		w2 = gate_module->wires_.at(it.second->name);
		if (w1->port_input != w2->port_input)
			goto match_gold_port_error;
		if (w1->port_output != w2->port_output)
			goto match_gold_port_error;
		if (w1->width != w2->width)
			goto match_gold_port_error;
		continue;
	match_gold_port_error:
		log_cmd_error("No matching port in gate module was found for %s!\n", it.second->name.c_str());
	}

	for (auto &it : gate_module->wires_) {
		RTLIL::Wire *w1 = it.second, *w2;
		if (w1->port_id == 0)
			continue;
		if (gold_module->wires_.count(it.second->name) == 0)
			goto match_gate_port_error;
		w2 = gold_module->wires_.at(it.second->name);
		if (w1->port_input != w2->port_input)
			goto match_gate_port_error;
		if (w1->port_output != w2->port_output)
			goto match_gate_port_error;
		if (w1->width != w2->width)
			goto match_gate_port_error;
		continue;
	match_gate_port_error:
		log_cmd_error("No matching port in gold module was found for %s!\n", it.second->name.c_str());
	}

	log("Creating miter cell \"%s\" with gold cell \"%s\" and gate cell \"%s\".\n", RTLIL::id2cstr(miter_name), RTLIL::id2cstr(gold_name), RTLIL::id2cstr(gate_name));

	RTLIL::Module *miter_module = new RTLIL::Module;
	miter_module->name = miter_name;
	design->add(miter_module);

	RTLIL::Cell *gold_cell = miter_module->addCell("\\gold", gold_name);
	RTLIL::Cell *gate_cell = miter_module->addCell("\\gate", gate_name);

	RTLIL::SigSpec all_conditions;

	for (auto &it : gold_module->wires_)
	{
		RTLIL::Wire *w1 = it.second;

		if (w1->port_input)
		{
			RTLIL::Wire *w2 = miter_module->addWire("\\in_" + RTLIL::unescape_id(w1->name), w1->width);
			w2->port_input = true;

			gold_cell->setPort(w1->name, w2);
			gate_cell->setPort(w1->name, w2);
		}

		if (w1->port_output)
		{
			RTLIL::Wire *w2_gold = miter_module->addWire("\\gold_" + RTLIL::unescape_id(w1->name), w1->width);
			w2_gold->port_output = flag_make_outputs;

			RTLIL::Wire *w2_gate = miter_module->addWire("\\gate_" + RTLIL::unescape_id(w1->name), w1->width);
			w2_gate->port_output = flag_make_outputs;

			gold_cell->setPort(w1->name, w2_gold);
			gate_cell->setPort(w1->name, w2_gate);

			RTLIL::SigSpec this_condition;

			if (flag_ignore_gold_x)
			{
				RTLIL::SigSpec gold_x = miter_module->addWire(NEW_ID, w2_gold->width);
				for (int i = 0; i < w2_gold->width; i++) {
					RTLIL::Cell *eqx_cell = miter_module->addCell(NEW_ID, "$eqx");
					eqx_cell->parameters["\\A_WIDTH"] = 1;
					eqx_cell->parameters["\\B_WIDTH"] = 1;
					eqx_cell->parameters["\\Y_WIDTH"] = 1;
					eqx_cell->parameters["\\A_SIGNED"] = 0;
					eqx_cell->parameters["\\B_SIGNED"] = 0;
					eqx_cell->setPort("\\A", RTLIL::SigSpec(w2_gold, i));
					eqx_cell->setPort("\\B", RTLIL::State::Sx);
					eqx_cell->setPort("\\Y", gold_x.extract(i, 1));
				}

				RTLIL::SigSpec gold_masked = miter_module->addWire(NEW_ID, w2_gold->width);
				RTLIL::SigSpec gate_masked = miter_module->addWire(NEW_ID, w2_gate->width);

				RTLIL::Cell *or_gold_cell = miter_module->addCell(NEW_ID, "$or");
				or_gold_cell->parameters["\\A_WIDTH"] = w2_gold->width;
				or_gold_cell->parameters["\\B_WIDTH"] = w2_gold->width;
				or_gold_cell->parameters["\\Y_WIDTH"] = w2_gold->width;
				or_gold_cell->parameters["\\A_SIGNED"] = 0;
				or_gold_cell->parameters["\\B_SIGNED"] = 0;
				or_gold_cell->setPort("\\A", w2_gold);
				or_gold_cell->setPort("\\B", gold_x);
				or_gold_cell->setPort("\\Y", gold_masked);

				RTLIL::Cell *or_gate_cell = miter_module->addCell(NEW_ID, "$or");
				or_gate_cell->parameters["\\A_WIDTH"] = w2_gate->width;
				or_gate_cell->parameters["\\B_WIDTH"] = w2_gate->width;
				or_gate_cell->parameters["\\Y_WIDTH"] = w2_gate->width;
				or_gate_cell->parameters["\\A_SIGNED"] = 0;
				or_gate_cell->parameters["\\B_SIGNED"] = 0;
				or_gate_cell->setPort("\\A", w2_gate);
				or_gate_cell->setPort("\\B", gold_x);
				or_gate_cell->setPort("\\Y", gate_masked);

				RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx");
				eq_cell->parameters["\\A_WIDTH"] = w2_gold->width;
				eq_cell->parameters["\\B_WIDTH"] = w2_gate->width;
				eq_cell->parameters["\\Y_WIDTH"] = 1;
				eq_cell->parameters["\\A_SIGNED"] = 0;
				eq_cell->parameters["\\B_SIGNED"] = 0;
				eq_cell->setPort("\\A", gold_masked);
				eq_cell->setPort("\\B", gate_masked);
				eq_cell->setPort("\\Y", miter_module->addWire(NEW_ID));
				this_condition = eq_cell->getPort("\\Y");
			}
			else
			{
				RTLIL::Cell *eq_cell = miter_module->addCell(NEW_ID, "$eqx");
				eq_cell->parameters["\\A_WIDTH"] = w2_gold->width;
				eq_cell->parameters["\\B_WIDTH"] = w2_gate->width;
				eq_cell->parameters["\\Y_WIDTH"] = 1;
				eq_cell->parameters["\\A_SIGNED"] = 0;
				eq_cell->parameters["\\B_SIGNED"] = 0;
				eq_cell->setPort("\\A", w2_gold);
				eq_cell->setPort("\\B", w2_gate);
				eq_cell->setPort("\\Y", miter_module->addWire(NEW_ID));
				this_condition = eq_cell->getPort("\\Y");
			}

			if (flag_make_outcmp)
			{
				RTLIL::Wire *w_cmp = miter_module->addWire("\\cmp_" + RTLIL::unescape_id(w1->name));
				w_cmp->port_output = true;
				miter_module->connect(RTLIL::SigSig(w_cmp, this_condition));
			}

			all_conditions.append(this_condition);
		}
	}

	if (all_conditions.size() != 1) {
		RTLIL::Cell *reduce_cell = miter_module->addCell(NEW_ID, "$reduce_and");
		reduce_cell->parameters["\\A_WIDTH"] = all_conditions.size();
		reduce_cell->parameters["\\Y_WIDTH"] = 1;
		reduce_cell->parameters["\\A_SIGNED"] = 0;
		reduce_cell->setPort("\\A", all_conditions);
		reduce_cell->setPort("\\Y", miter_module->addWire(NEW_ID));
		all_conditions = reduce_cell->getPort("\\Y");
	}

	if (flag_make_assert) {
		RTLIL::Cell *assert_cell = miter_module->addCell(NEW_ID, "$assert");
		assert_cell->setPort("\\A", all_conditions);
		assert_cell->setPort("\\EN", State::S1);
	}

	RTLIL::Wire *w_trigger = miter_module->addWire("\\trigger");
	w_trigger->port_output = true;

	RTLIL::Cell *not_cell = miter_module->addCell(NEW_ID, "$not");
	not_cell->parameters["\\A_WIDTH"] = all_conditions.size();
	not_cell->parameters["\\A_WIDTH"] = all_conditions.size();
	not_cell->parameters["\\Y_WIDTH"] = w_trigger->width;
	not_cell->parameters["\\A_SIGNED"] = 0;
	not_cell->setPort("\\A", all_conditions);
	not_cell->setPort("\\Y", w_trigger);

	miter_module->fixup_ports();

	if (flag_flatten) {
		log_push();
		Pass::call_on_module(design, miter_module, "flatten -wb; opt_expr -keepdc -undriven;;");
		log_pop();
	}
}

void create_miter_assert(struct Pass *that, std::vector<std::string> args, RTLIL::Design *design)
{
	bool flag_make_outputs = false;
	bool flag_flatten = false;

	log_header(design, "Executing MITER pass (creating miter circuit).\n");

	size_t argidx;
	for (argidx = 2; argidx < args.size(); argidx++)
	{
		if (args[argidx] == "-make_outputs") {
			flag_make_outputs = true;
			continue;
		}
		if (args[argidx] == "-flatten") {
			flag_flatten = true;
			continue;
		}
		break;
	}
	if ((argidx+1 != args.size() && argidx+2 != args.size()) || args[argidx].compare(0, 1, "-") == 0)
		that->cmd_error(args, argidx, "command argument error");

	IdString module_name = RTLIL::escape_id(args[argidx++]);
	IdString miter_name = argidx < args.size() ? RTLIL::escape_id(args[argidx++]) : "";

	if (design->modules_.count(module_name) == 0)
		log_cmd_error("Can't find module %s!\n", module_name.c_str());
	if (!miter_name.empty() && design->modules_.count(miter_name) != 0)
		log_cmd_error("There is already a module %s!\n", miter_name.c_str());

	Module *module = design->module(module_name);

	if (!miter_name.empty()) {
		module = module->clone();
		module->name = miter_name;
		design->add(module);
	}

	if (!flag_make_outputs)
		for (auto wire : module->wires())
			wire->port_output = false;

	Wire *trigger = module->addWire("\\trigger");
	trigger->port_output = true;
	module->fixup_ports();

	if (flag_flatten) {
		log_push();
		Pass::call_on_module(design, module, "flatten -wb;;");
		log_pop();
	}

	SigSpec assert_signals, assume_signals;
	vector<Cell*> cell_list = module->cells();
	for (auto cell : cell_list)
	{
		if (!cell->type.in("$assert", "$assume"))
			continue;

		SigBit is_active = module->Nex(NEW_ID, cell->getPort("\\A"), State::S1);
		SigBit is_enabled = module->Eqx(NEW_ID, cell->getPort("\\EN"), State::S1);

		if (cell->type == "$assert") {
			assert_signals.append(module->And(NEW_ID, is_active, is_enabled));
		} else {
			assume_signals.append(module->And(NEW_ID, is_active, is_enabled));
		}

		module->remove(cell);
	}

	if (assume_signals.empty())
	{
		module->addReduceOr(NEW_ID, assert_signals, trigger);
	}
	else
	{
		Wire *assume_q = module->addWire(NEW_ID);
		assume_q->attributes["\\init"] = State::S0;
		assume_signals.append(assume_q);

		SigSpec assume_nok = module->ReduceOr(NEW_ID, assume_signals);
		SigSpec assume_ok = module->Not(NEW_ID, assume_nok);
		module->addFf(NEW_ID, assume_nok, assume_q);

		SigSpec assert_fail = module->ReduceOr(NEW_ID, assert_signals);
		module->addAnd(NEW_ID, assert_fail, assume_ok, trigger);
	}

	if (flag_flatten) {
		log_push();
		Pass::call_on_module(design, module, "opt_expr -keepdc -undriven;;");
		log_pop();
	}
}

struct MiterPass : public Pass {
	MiterPass() : Pass("miter", "automatically create a miter circuit") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    miter -equiv [options] gold_name gate_name miter_name\n");
		log("\n");
		log("Creates a miter circuit for equivalence checking. The gold- and gate- modules\n");
		log("must have the same interfaces. The miter circuit will have all inputs of the\n");
		log("two source modules, prefixed with 'in_'. The miter circuit has a 'trigger'\n");
		log("output that goes high if an output mismatch between the two source modules is\n");
		log("detected.\n");
		log("\n");
		log("    -ignore_gold_x\n");
		log("        a undef (x) bit in the gold module output will match any value in\n");
		log("        the gate module output.\n");
		log("\n");
		log("    -make_outputs\n");
		log("        also route the gold- and gate-outputs to 'gold_*' and 'gate_*' outputs\n");
		log("        on the miter circuit.\n");
		log("\n");
		log("    -make_outcmp\n");
		log("        also create a cmp_* output for each gold/gate output pair.\n");
		log("\n");
		log("    -make_assert\n");
		log("        also create an 'assert' cell that checks if trigger is always low.\n");
		log("\n");
		log("    -flatten\n");
		log("        call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
		log("\n");
		log("\n");
		log("    miter -assert [options] module [miter_name]\n");
		log("\n");
		log("Creates a miter circuit for property checking. All input ports are kept,\n");
		log("output ports are discarded. An additional output 'trigger' is created that\n");
		log("goes high when an assert is violated. Without a miter_name, the existing\n");
		log("module is modified.\n");
		log("\n");
		log("    -make_outputs\n");
		log("        keep module output ports.\n");
		log("\n");
		log("    -flatten\n");
		log("        call 'flatten -wb; opt_expr -keepdc -undriven;;' on the miter circuit.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		if (args.size() > 1 && args[1] == "-equiv") {
			create_miter_equiv(this, args, design);
			return;
		}

		if (args.size() > 1 && args[1] == "-assert") {
			create_miter_assert(this, args, design);
			return;
		}

		log_cmd_error("Missing mode parameter!\n");
	}
} MiterPass;

PRIVATE_NAMESPACE_END
