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

	bool flag_noinit;
	bool flag_always;

	// get<0> ... mux cell
	// get<1> ... mux port index
	// get<2> ... mux bit index
	dict<SigBit, pool<tuple<Cell*, int, int>>> sigbit_muxusers;

	dict<SigBit, SigBit> sigbit_actsignals;
	dict<SigSpec, SigBit> sigspec_actsignals;
	dict<tuple<Cell*, int>, SigBit> muxport_actsignal;

	AssertpmuxWorker(Module *module, bool flag_noinit, bool flag_always) :
			module(module), sigmap(module), flag_noinit(flag_noinit), flag_always(flag_always)
	{
		for (auto wire : module->wires())
		{
			if (wire->port_output)
				for (auto bit : sigmap(wire))
					sigbit_actsignals[bit] = State::S1;
		}

		for (auto cell : module->cells())
		{
			if (cell->type.in("$mux", "$pmux"))
			{
				int width = cell->getParam("\\WIDTH").as_int();
				int numports = cell->type == "$mux" ? 2 : cell->getParam("\\S_WIDTH").as_int() + 1;

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

				for (int i = 0; i < numports; i++) {
					SigSpec bits = i == 0 ? sig_a : sig_b.extract(width*(i-1), width);
					for (int k = 0; k < width; k++) {
						tuple<Cell*, int, int> muxuser(cell, i, k);
						sigbit_muxusers[bits[k]].insert(muxuser);
					}
				}
			}
			else
			{
				for (auto &conn : cell->connections()) {
					if (!cell->known() || cell->input(conn.first))
						for (auto bit : sigmap(conn.second))
							sigbit_actsignals[bit] = State::S1;
				}
			}
		}
	}

	SigBit get_bit_activation(SigBit bit)
	{
		sigmap.apply(bit);

		if (sigbit_actsignals.count(bit) == 0)
		{
			SigSpec output;

			for (auto muxuser : sigbit_muxusers.at(bit))
			{
				Cell *cell = std::get<0>(muxuser);
				int portidx = std::get<1>(muxuser);
				int bitidx = std::get<2>(muxuser);

				tuple<Cell*, int> muxport(cell, portidx);

				if (muxport_actsignal.count(muxport) == 0) {
					if (portidx == 0)
						muxport_actsignal[muxport] = module->LogicNot(NEW_ID, cell->getPort("\\S"));
					else
						muxport_actsignal[muxport] = cell->getPort("\\S")[portidx-1];
				}

				output.append(module->LogicAnd(NEW_ID, muxport_actsignal.at(muxport), get_bit_activation(cell->getPort("\\Y")[bitidx])));
			}

			output.sort_and_unify();

			if (GetSize(output) == 0)
				output = State::S0;
			else if (GetSize(output) > 1)
				output = module->ReduceOr(NEW_ID, output);

			sigbit_actsignals[bit] = output.as_bit();
		}

		return sigbit_actsignals.at(bit);
	}

	SigBit get_activation(SigSpec sig)
	{
		sigmap.apply(sig);
		sig.sort_and_unify();

		if (sigspec_actsignals.count(sig) == 0)
		{
			SigSpec output;

			for (auto bit : sig)
				output.append(get_bit_activation(bit));

			output.sort_and_unify();

			if (GetSize(output) == 0)
				output = State::S0;
			else if (GetSize(output) > 1)
				output = module->ReduceOr(NEW_ID, output);

			sigspec_actsignals[sig] = output.as_bit();
		}

		return sigspec_actsignals.at(sig);
	}

	void run(Cell *pmux)
	{
		log("Adding assert for $pmux cell %s.%s.\n", log_id(module), log_id(pmux));

		int swidth = pmux->getParam("\\S_WIDTH").as_int();
		int cntbits = ceil_log2(swidth+1);

		SigSpec sel = pmux->getPort("\\S");
		SigSpec cnt(State::S0, cntbits);

		for (int i = 0; i < swidth; i++)
			cnt = module->Add(NEW_ID, cnt, sel[i]);

		SigSpec assert_a = module->Le(NEW_ID, cnt, SigSpec(1, cntbits));
		SigSpec assert_en;

		if (flag_noinit)
			assert_en.append(module->LogicNot(NEW_ID, module->Initstate(NEW_ID)));

		if (!flag_always)
			assert_en.append(get_activation(pmux->getPort("\\Y")));

		if (GetSize(assert_en) == 0)
			assert_en = State::S1;

		if (GetSize(assert_en) == 2)
			assert_en = module->LogicAnd(NEW_ID, assert_en[0], assert_en[1]);

		Cell *assert_cell = module->addAssert(NEW_ID, assert_a, assert_en);

		if (pmux->attributes.count("\\src") != 0)
			assert_cell->attributes["\\src"] = pmux->attributes.at("\\src");
	}
};

struct AssertpmuxPass : public Pass {
	AssertpmuxPass() : Pass("assertpmux", "convert internal signals to module ports") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    assertpmux [options] [selection]\n");
		log("\n");
		log("This command adds asserts to the design that assert that all parallel muxes\n");
		log("($pmux cells) have a maximum of one of their inputs enable at any time.\n");
		log("\n");
		log("    -noinit\n");
		log("        do not enforce the pmux condition during the init state\n");
		log("\n");
		log("    -always\n");
		log("        usually the $pmux condition is only checked when the $pmux output\n");
		log("        is used be the mux tree it drives. this option will deactivate this\n");
		log("        additional constrained and check the $pmux condition always.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		bool flag_noinit = false;
		bool flag_always = false;

		log_header(design, "Executing ASSERTPMUX pass (add asserts for $pmux cells).\n");

		size_t argidx;
		for (argidx = 1; argidx < args.size(); argidx++)
		{
			if (args[argidx] == "-noinit") {
				flag_noinit = true;
				continue;
			}
			if (args[argidx] == "-always") {
				flag_always = true;
				continue;
			}
			break;
		}
		extra_args(args, argidx, design);

		for (auto module : design->selected_modules())
		{
			AssertpmuxWorker worker(module, flag_noinit, flag_always);
			vector<Cell*> pmux_cells;

			for (auto cell : module->selected_cells())
				if (cell->type == "$pmux")
					pmux_cells.push_back(cell);

			for (auto cell : pmux_cells)
				worker.run(cell);
		}

	}
} AssertpmuxPass;

PRIVATE_NAMESPACE_END
