/*
 *  yosys -- Yosys Open SYnthesis Suite
 *
 *  Copyright (C) 2020  The Symbiflow Authors
 *
 *  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 "clocks.h"
#include <cassert>
#include "kernel/log.h"
#include "kernel/register.h"
#include "propagation.h"

void Clocks::AddClock(const std::string& name, std::vector<RTLIL::Wire*> wires,
                      float period, float rising_edge, float falling_edge) {
    std::for_each(wires.begin(), wires.end(), [&, this](RTLIL::Wire* wire) {
	AddClock(name, wire, period, rising_edge, falling_edge);
    });
}

void Clocks::AddClock(const std::string& name, RTLIL::Wire* wire, float period,
                      float rising_edge, float falling_edge) {
    auto clock =
        std::find_if(clocks_.begin(), clocks_.end(),
                     [&](Clock& clock) { return clock.Name() == name; });
    if (clock != clocks_.end()) {
	log("Clock %s already exists and will be overwritten\n", name.c_str());
	clock->UpdateClock(wire, period, rising_edge, falling_edge);
    } else {
	log("Inserting clock %s with period %f, r:%f, f:%f\n", name.c_str(),
	    period, rising_edge, falling_edge);
	clocks_.emplace_back(name, wire, period, rising_edge, falling_edge);
    }
}

void Clocks::AddClock(Clock& clock) {
    AddClock(clock.Name(), clock.GetClockWires(), clock.Period(),
             clock.RisingEdge(), clock.FallingEdge());
}

std::vector<std::string> Clocks::GetClockNames() {
    std::vector<std::string> res;
    for (auto clock : clocks_) {
	res.push_back(clock.Name());
#ifdef SDC_DEBUG
	std::stringstream ss;
	for (auto clock_wire : clock.GetClockWires()) {
	    ss << RTLIL::unescape_id(clock_wire->name) << " ";
	}
	log("create_clock -period %f -name %s -waveform {%f %f} %s\n",
	    clock.Period(), clock.Name().c_str(), clock.RisingEdge(),
	    clock.FallingEdge(), ss.str().c_str());
#endif
    }
    return res;
}

void Clocks::Propagate(NaturalPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start natural clock propagation\n");
#endif
    for (auto clock : clocks_) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", clock.Name().c_str());
#endif
	auto clock_wires = clock.GetClockWires();
	for (auto clock_wire : clock_wires) {
	    auto aliases = pass->FindAliasWires(clock_wire);
	    AddClock(clock.Name(), aliases, clock.Period(),
	                  clock.RisingEdge(), clock.FallingEdge());
	}
    }
#ifdef SDC_DEBUG
    log("Finish natural clock propagation\n\n");
#endif
}

void Clocks::Propagate(BufferPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start buffer clock propagation\n");
    log("IBUF pass\n");
#endif
    std::vector<Clock> clocks(clocks_);
    for (auto clock : clocks) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", clock.Name().c_str());
#endif
	PropagateThroughBuffer(pass, clock, IBuf());
    }
#ifdef SDC_DEBUG
    log("BUFG pass\n");
#endif
    clocks = clocks_;
    for (auto clock : clocks) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", clock.Name().c_str());
#endif
	PropagateThroughBuffer(pass, clock, Bufg());
    }
#ifdef SDC_DEBUG
    log("Finish buffer clock propagation\n\n");
#endif
}

void Clocks::Propagate(ClockDividerPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start clock divider clock propagation\n");
#endif
    for (auto clock : clocks_) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", clock.Name().c_str());
#endif
	auto clock_wires = clock.GetClockWires();
	for (auto clock_wire : clock_wires) {
	    auto pll_clocks =
	        pass->FindSinkClocksForCellType(clock_wire, "PLLE2_ADV");
	    for (auto pll_clock : pll_clocks) {
#ifdef SDC_DEBUG
		log("PLL clock: %s\n", pll_clock.Name().c_str());
#endif
		AddClock(pll_clock);
		PropagateThroughBuffer(pass, pll_clock, Bufg());
	    }
	}
    }
#ifdef SDC_DEBUG
    log("Finish clock divider clock propagation\n\n");
#endif
}

void Clocks::PropagateThroughBuffer(Propagation* pass, Clock& clock,
                                    Buffer buffer) {
    auto clock_wires = clock.GetClockWires();
    for (auto clock_wire : clock_wires) {
#ifdef SDC_DEBUG
	log("Clock wire %s\n", RTLIL::unescape_id(clock_wire->name).c_str());
#endif
	auto buf_wires = pass->FindSinkWiresForCellType(clock_wire, buffer.name,
	                                                buffer.output);
	int path_delay(0);
	for (auto wire : buf_wires) {
#ifdef SDC_DEBUG
	    log("%s wire: %s\n", buffer.name.c_str(),
	        RTLIL::unescape_id(wire->name).c_str());
#endif
	    path_delay += buffer.delay;
	    AddClock(RTLIL::unescape_id(wire->name), wire, clock.Period(),
	             clock.RisingEdge() + path_delay,
	             clock.FallingEdge() + path_delay);
	}
    }
}

void Clocks::WriteSdc(std::ostream& file) {
    for (auto& clock : clocks_) {
	auto clock_wires = clock.GetClockWires();
	// FIXME: Input port nets are not found in VPR
	if (std::all_of(clock_wires.begin(), clock_wires.end(),
	                [&](RTLIL::Wire* wire) { return wire->port_input; })) {
	    continue;
	}
	file << "create_clock -period " << clock.Period();
	file << " -waveform {" << clock.RisingEdge() << " "
	     << clock.FallingEdge() << "}";
	for (auto clock_wire : clock_wires) {
	    if (clock_wire->port_input) {
		continue;
	    }
	    file << " " << Clock::ClockWireName(clock_wire);
	}
	file << std::endl;
    }
}

Clock::Clock(const std::string& name, RTLIL::Wire* wire, float period,
             float rising_edge, float falling_edge)
    : name_(name),
      period_(period),
      rising_edge_(rising_edge),
      falling_edge_(falling_edge) {
    UpdateWires(wire);
}

Clock::Clock(const std::string& name, std::vector<RTLIL::Wire*> wires,
             float period, float rising_edge, float falling_edge)
    : name_(name),
      period_(period),
      rising_edge_(rising_edge),
      falling_edge_(falling_edge) {
    std::for_each(wires.begin(), wires.end(),
                  [&, this](RTLIL::Wire* wire) { UpdateWires(wire); });
}

void Clock::UpdateClock(RTLIL::Wire* wire, float period, float rising_edge,
                        float falling_edge) {
    UpdateWires(wire);
    UpdatePeriod(period);
    UpdateWaveform(rising_edge, falling_edge);
}

void Clock::UpdateWires(RTLIL::Wire* wire) {
    if (std::find(clock_wires_.begin(), clock_wires_.end(), wire) ==
        clock_wires_.end()) {
	clock_wires_.push_back(wire);
    }
}

void Clock::UpdatePeriod(float period) {
    period_ = period;
}

void Clock::UpdateWaveform(float rising_edge, float falling_edge) {
    rising_edge_ = rising_edge;
    falling_edge_ = falling_edge;
}

std::string Clock::ClockWireName(RTLIL::Wire* wire) {
    if (!wire) {
	return std::string();
    }
    std::string wire_name(RTLIL::unescape_id(wire->name));
    return std::regex_replace(wire_name, std::regex{"\\$"}, "\\$");
}
