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

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_WIRES"), 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::SourceWireName(RTLIL::Wire *clock_wire)
{
    if (clock_wire->has_attribute(RTLIL::escape_id("SOURCE_WIRES"))) {
        return clock_wire->get_string_attribute(RTLIL::escape_id("SOURCE_WIRES"));
    }
    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;
}
