/*
 *  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 <cmath>
#include <regex>
#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(), [&](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) {
    wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes");
    wire->set_string_attribute(RTLIL::escape_id("CLASS"), "clock");
    wire->set_string_attribute(RTLIL::escape_id("NAME"), name);
    wire->set_string_attribute(RTLIL::escape_id("SOURCE_PINS"), Clock::ClockWireName(wire));
    wire->set_string_attribute(RTLIL::escape_id("PERIOD"), std::to_string(period));
    std::string waveform(std::to_string(rising_edge) + " " + std::to_string(falling_edge));
    wire->set_string_attribute(RTLIL::escape_id("WAVEFORM"), waveform);
}

void Clocks::AddClock(RTLIL::Wire* wire, float period,
                      float rising_edge, float falling_edge) {
    AddClock(Clock::ClockWireName(wire), wire, period, rising_edge, falling_edge);
}

const std::vector<RTLIL::Wire*> Clocks::GetClocks(RTLIL::Design* design) {
    std::vector<RTLIL::Wire*> clock_wires;
    RTLIL::Module* top_module = design->top_module();
    for (auto& wire_obj : top_module->wires_) {
	auto& wire = wire_obj.second;
	if (wire->has_attribute(RTLIL::escape_id("CLOCK_SIGNAL"))) {
		if (wire->get_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL")) == "yes") {
			clock_wires.push_back(wire);
		}
	}
    }
    return clock_wires;
}

void Clocks::Propagate(RTLIL::Design* design, NaturalPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start natural clock propagation\n");
#endif
    for (auto& clock_wire : Clocks::GetClocks(design)) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
#endif
	auto aliases = pass->FindAliasWires(clock_wire);
	AddClock(Clock::ClockWireName(clock_wire), aliases,
	         Clock::Period(clock_wire), Clock::RisingEdge(clock_wire),
	         Clock::FallingEdge(clock_wire));
    }
#ifdef SDC_DEBUG
    log("Finish natural clock propagation\n\n");
#endif
}

void Clocks::Propagate(RTLIL::Design* design, BufferPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start buffer clock propagation\n");
    log("IBUF pass\n");
#endif
    PropagateThroughBuffers(pass, design, IBuf());
#ifdef SDC_DEBUG
    log("BUFG pass\n");
#endif
    PropagateThroughBuffers(pass, design, Bufg());
#ifdef SDC_DEBUG
    log("Finish buffer clock propagation\n\n");
#endif
}

void Clocks::Propagate(RTLIL::Design* design, ClockDividerPropagation* pass) {
#ifdef SDC_DEBUG
    log("Start clock divider clock propagation\n");
#endif
    for (auto& clock_wire : Clocks::GetClocks(design)) {
#ifdef SDC_DEBUG
	log("Processing clock %s\n", RTLIL::id2cstr(clock_wire->name));
#endif
	pass->PropagateClocksForCellType(clock_wire, "PLLE2_ADV");
	PropagateThroughBuffers(pass, design, Bufg());
    }
#ifdef SDC_DEBUG
    log("Finish clock divider clock propagation\n\n");
#endif
}

void Clocks::PropagateThroughBuffers(Propagation* pass, RTLIL::Design* design,
                                    Buffer buffer) {
    for (auto& clock_wire : Clocks::GetClocks(design)) {
#ifdef SDC_DEBUG
	log("Clock wire %s\n", Clock::ClockWireName(clock_wire).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::id2cstr(wire->name));
#endif
	    path_delay += buffer.delay;
	    AddClock(wire, Clock::Period(clock_wire),
	             Clock::RisingEdge(clock_wire) + path_delay,
	             Clock::FallingEdge(clock_wire) + path_delay);
	}
    }
}

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); });
}

Clock::Clock(RTLIL::Wire* wire, float period,
             float rising_edge, float falling_edge)
    : Clock(RTLIL::unescape_id(wire->name), wire, period, rising_edge, falling_edge) {}

float Clock::Period(RTLIL::Wire* clock_wire) {
    if (!clock_wire->has_attribute(RTLIL::escape_id("PERIOD"))) {
	log_warning("Period has not been specified\n Default value 0 will be used\n");
	return 0;
    }
    return std::stof(clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD")));
}

std::pair<float, float> Clock::Waveform(RTLIL::Wire* clock_wire) {
    if (!clock_wire->has_attribute(RTLIL::escape_id("WAVEFORM"))) {
	float period(Period(clock_wire));
	if (!period) {
	    log_cmd_error("Neither PERIOD nor WAVEFORM has been specified for wire %s\n", ClockWireName(clock_wire).c_str());
	    return std::make_pair(0,0);
	}
	float falling_edge = period / 2;
	log_warning("Waveform has not been specified\n Default value {0 %f} will be used\n", falling_edge);
	return std::make_pair(0, falling_edge);
    }
    float rising_edge(0);
    float falling_edge(0);
    std::string waveform(clock_wire->get_string_attribute(RTLIL::escape_id("WAVEFORM")));
    std::sscanf(waveform.c_str(), "%f %f", &rising_edge, &falling_edge);
    return std::make_pair(rising_edge, falling_edge);
}

float Clock::RisingEdge(RTLIL::Wire* clock_wire) {
    return Waveform(clock_wire).first;
}

float Clock::FallingEdge(RTLIL::Wire* clock_wire) {
    return Waveform(clock_wire).second;
}

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_ = fmod(rising_edge, period_);
    falling_edge_ = fmod(falling_edge, period_);
}

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{"\\$"}, "\\$");
}
