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

YOSYS_NAMESPACE_BEGIN
extern void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth);
YOSYS_NAMESPACE_END

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

void proc_clean_switch(RTLIL::SwitchRule *sw, RTLIL::CaseRule *parent, bool &did_something, int &count, int max_depth)
{
	if (sw->signal.size() > 0 && sw->signal.is_fully_const())
	{
		int found_matching_case_idx = -1;
		for (int i = 0; i < int(sw->cases.size()) && found_matching_case_idx < 0; i++)
		{
			RTLIL::CaseRule *cs = sw->cases[i];
			if (cs->compare.size() == 0)
				break;
			for (int j = 0; j < int(cs->compare.size()); j++) {
				RTLIL::SigSpec &val = cs->compare[j];
				if (!val.is_fully_const())
					continue;
				if (val == sw->signal) {
					cs->compare.clear();
					found_matching_case_idx = i;
					break;
				} else
					cs->compare.erase(cs->compare.begin()+(j--));
			}
			if (cs->compare.size() == 0 && found_matching_case_idx < 0) {
				sw->cases.erase(sw->cases.begin()+(i--));
				delete cs;
			}
		}
		while (found_matching_case_idx >= 0 && int(sw->cases.size()) > found_matching_case_idx+1) {
			delete sw->cases.back();
			sw->cases.pop_back();
		}
		if (found_matching_case_idx == 0)
			sw->signal = RTLIL::SigSpec();
	}

	if (parent->switches.front() == sw && sw->cases.size() == 1 &&
			(sw->signal.size() == 0 || sw->cases[0]->compare.empty()))
	{
		did_something = true;
		for (auto &action : sw->cases[0]->actions)
			parent->actions.push_back(action);
		parent->switches.insert(parent->switches.begin(), sw->cases[0]->switches.begin(), sw->cases[0]->switches.end());
		sw->cases[0]->switches.clear();
		delete sw->cases[0];
		sw->cases.clear();
	}
	else
	{
		bool all_fully_def = true;
		for (auto cs : sw->cases)
		{
			if (max_depth != 0)
				proc_clean_case(cs, did_something, count, max_depth-1);
			int size = 0;
			for (auto cmp : cs->compare)
			{
				size += cmp.size();
				if (!cmp.is_fully_def())
					all_fully_def = false;
			}
			if (sw->signal.size() != size)
				all_fully_def = false;
		}
		if (all_fully_def)
		{
			for (auto cs = sw->cases.begin(); cs != sw->cases.end();)
			{
				if ((*cs)->empty())
				{
					did_something = true;
					delete *cs;
					cs = sw->cases.erase(cs);
				}
				else ++cs;
			}
		}
		else
		{
			while (!sw->cases.empty() && sw->cases.back()->empty())
			{
				did_something = true;
				delete sw->cases.back();
				sw->cases.pop_back();
			}
		}
	}
}

PRIVATE_NAMESPACE_END
YOSYS_NAMESPACE_BEGIN

void proc_clean_case(RTLIL::CaseRule *cs, bool &did_something, int &count, int max_depth)
{
	for (size_t i = 0; i < cs->actions.size(); i++) {
		if (cs->actions[i].first.size() == 0) {
			did_something = true;
			cs->actions.erase(cs->actions.begin() + (i--));
		}
	}
	for (size_t i = 0; i < cs->switches.size(); i++) {
		RTLIL::SwitchRule *sw = cs->switches[i];
		if (sw->empty()) {
			cs->switches.erase(cs->switches.begin() + (i--));
			did_something = true;
			delete sw;
			count++;
		} else if (max_depth != 0)
			proc_clean_switch(sw, cs, did_something, count, max_depth-1);
	}
}

YOSYS_NAMESPACE_END
PRIVATE_NAMESPACE_BEGIN

void proc_clean(RTLIL::Module *mod, RTLIL::Process *proc, int &total_count, bool quiet)
{
	int count = 0;
	bool did_something = true;
	for (size_t i = 0; i < proc->syncs.size(); i++) {
		for (size_t j = 0; j < proc->syncs[i]->actions.size(); j++)
			if (proc->syncs[i]->actions[j].first.size() == 0)
				proc->syncs[i]->actions.erase(proc->syncs[i]->actions.begin() + (j--));
		if (proc->syncs[i]->actions.size() == 0) {
			delete proc->syncs[i];
			proc->syncs.erase(proc->syncs.begin() + (i--));
		}
	}
	while (did_something) {
		did_something = false;
		proc_clean_case(&proc->root_case, did_something, count, -1);
	}
	if (count > 0 && !quiet)
		log("Found and cleaned up %d empty switch%s in `%s.%s'.\n", count, count == 1 ? "" : "es", mod->name.c_str(), proc->name.c_str());
	total_count += count;
}

struct ProcCleanPass : public Pass {
	ProcCleanPass() : Pass("proc_clean", "remove empty parts of processes") { }
	void help() YS_OVERRIDE
	{
		//   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
		log("\n");
		log("    proc_clean [options] [selection]\n");
		log("\n");
		log("    -quiet\n");
		log("        do not print any messages.\n");
		log("\n");
		log("This pass removes empty parts of processes and ultimately removes a process\n");
		log("if it contains only empty structures.\n");
		log("\n");
	}
	void execute(std::vector<std::string> args, RTLIL::Design *design) YS_OVERRIDE
	{
		int total_count = 0;
		bool quiet = false;

		if (find(args.begin(), args.end(), "-quiet") == args.end())
			log_header(design, "Executing PROC_CLEAN pass (remove empty switches from decision trees).\n");

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

		for (auto mod : design->modules()) {
			std::vector<RTLIL::IdString> delme;
			if (!design->selected(mod))
				continue;
			for (auto &proc_it : mod->processes) {
				if (!design->selected(mod, proc_it.second))
					continue;
				proc_clean(mod, proc_it.second, total_count, quiet);
				if (proc_it.second->syncs.size() == 0 && proc_it.second->root_case.switches.size() == 0 &&
						proc_it.second->root_case.actions.size() == 0) {
					if (!quiet)
						log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str());
					delme.push_back(proc_it.first);
				}
			}
			for (auto &id : delme) {
				delete mod->processes[id];
				mod->processes.erase(id);
			}
		}

		if (!quiet)
			log("Cleaned up %d empty switch%s.\n", total_count, total_count == 1 ? "" : "es");
	}
} ProcCleanPass;

PRIVATE_NAMESPACE_END
