/*
 *  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/register.h"
#include "propagation.h"

void Clock::Add(const std::string& name, RTLIL::Wire* wire, float period,
                float rising_edge, float falling_edge, ClockType type) {
    wire->set_string_attribute(RTLIL::escape_id("CLOCK_SIGNAL"), "yes");
    wire->set_bool_attribute(RTLIL::escape_id("IS_GENERATED"), type == GENERATED);
    wire->set_bool_attribute(RTLIL::escape_id("IS_EXPLICIT"), type == EXPLICIT);
    wire->set_bool_attribute(RTLIL::escape_id("IS_PROPAGATED"), type == PROPAGATED);
    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::WireName(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 Clock::Add(const std::string& name, std::vector<RTLIL::Wire*> wires,
                float period, float rising_edge, float falling_edge, ClockType type) {
    std::for_each(wires.begin(), wires.end(), [&](RTLIL::Wire* wire) {
	Add(name, wire, period, rising_edge, falling_edge, type);
    });
}

void Clock::Add(RTLIL::Wire* wire, float period, float rising_edge,
                float falling_edge, ClockType type) {
    Add(Clock::WireName(wire), wire, period, rising_edge, falling_edge, type);
}

float Clock::Period(RTLIL::Wire* clock_wire) {
    if (!clock_wire->has_attribute(RTLIL::escape_id("PERIOD"))) {
	log_cmd_error("PERIOD has not been specified on wire '%s'.\n",
	              WireName(clock_wire).c_str());
    }
    float period(0);
    std::string period_str;
    try {
	period_str =
	    clock_wire->get_string_attribute(RTLIL::escape_id("PERIOD"));
	period = std::stof(period_str);
    } catch (const std::invalid_argument& e) {
	log_cmd_error(
	    "Incorrect value '%s' specifed on PERIOD attribute for wire "
	    "'%s'.\nPERIOD needs to be a float value.\n",
	    period_str.c_str(), WireName(clock_wire).c_str());
    }
    return 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",
	        WireName(clock_wire).c_str());
	    return std::make_pair(0, 0);
	}
	float falling_edge = period / 2;
	log_warning(
	    "Waveform has not been specified on wire '%s'.\nDefault value {0 %f} "
	    "will be used\n",
	    WireName(clock_wire).c_str(), 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")));
    if (std::sscanf(waveform.c_str(), "%f %f", &rising_edge, &falling_edge) !=
        2) {
	log_cmd_error(
	    "Incorrect value '%s' specifed on WAVEFORM attribute for wire "
	    "'%s'.\nWAVEFORM needs to be specified in form of '<rising_edge> "
	    "<falling_edge>' where the edge values are floats.\n",
	    waveform.c_str(), WireName(clock_wire).c_str());
    }
    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;
}

std::string Clock::Name(RTLIL::Wire* clock_wire) {
    if (clock_wire->has_attribute(RTLIL::escape_id("NAME"))) {
	return clock_wire->get_string_attribute(RTLIL::escape_id("NAME"));
    }
    return WireName(clock_wire);
}

std::string Clock::WireName(RTLIL::Wire* clock_wire) {
    if (!clock_wire) {
	return std::string();
    }
    return AddEscaping(RTLIL::unescape_id(clock_wire->name));
}

std::string Clock::SourcePinName(RTLIL::Wire* clock_wire) {
    if (clock_wire->has_attribute(RTLIL::escape_id("SOURCE_PINS"))) {
	return clock_wire->get_string_attribute(RTLIL::escape_id("SOURCE_PINS"));
    }
    return Name(clock_wire);
}

bool Clock::GetClockWireBoolAttribute(RTLIL::Wire* wire, const std::string& attribute_name) {
    if (wire->has_attribute(RTLIL::escape_id(attribute_name))) {
	return wire->get_bool_attribute(RTLIL::escape_id(attribute_name));
    }
    return false;
}

const std::map<std::string, RTLIL::Wire*> Clocks::GetClocks(
    RTLIL::Design* design) {
    std::map<std::string, 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.insert(std::make_pair(Clock::WireName(wire), wire));
	    }
	}
    }
    return clock_wires;
}

