/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *
 *  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 "nextpnr.h"
#include <boost/algorithm/string.hpp>
#include "log.h"

NEXTPNR_NAMESPACE_BEGIN

assertion_failure::assertion_failure(std::string msg, std::string expr_str, std::string filename, int line)
        : runtime_error("Assertion failure: " + msg + " (" + filename + ":" + std::to_string(line) + ")"), msg(msg),
          expr_str(expr_str), filename(filename), line(line)
{
    log_flush();
}

void IdString::set(const BaseCtx *ctx, const std::string &s)
{
    auto it = ctx->idstring_str_to_idx->find(s);
    if (it == ctx->idstring_str_to_idx->end()) {
        index = ctx->idstring_idx_to_str->size();
        auto insert_rc = ctx->idstring_str_to_idx->insert({s, index});
        ctx->idstring_idx_to_str->push_back(&insert_rc.first->first);
    } else {
        index = it->second;
    }
}

const std::string &IdString::str(const BaseCtx *ctx) const { return *ctx->idstring_idx_to_str->at(index); }

const char *IdString::c_str(const BaseCtx *ctx) const { return str(ctx).c_str(); }

void IdString::initialize_add(const BaseCtx *ctx, const char *s, int idx)
{
    NPNR_ASSERT(ctx->idstring_str_to_idx->count(s) == 0);
    NPNR_ASSERT(int(ctx->idstring_idx_to_str->size()) == idx);
    auto insert_rc = ctx->idstring_str_to_idx->insert({s, idx});
    ctx->idstring_idx_to_str->push_back(&insert_rc.first->first);
}

TimingConstrObjectId BaseCtx::timingWildcardObject()
{
    TimingConstrObjectId id;
    id.index = 0;
    return id;
}

TimingConstrObjectId BaseCtx::timingClockDomainObject(NetInfo *clockDomain)
{
    NPNR_ASSERT(clockDomain->clkconstr != nullptr);
    if (clockDomain->clkconstr->domain_tmg_id != TimingConstrObjectId()) {
        return clockDomain->clkconstr->domain_tmg_id;
    } else {
        TimingConstraintObject obj;
        TimingConstrObjectId id;
        id.index = int(constraintObjects.size());
        obj.id = id;
        obj.type = TimingConstraintObject::CLOCK_DOMAIN;
        obj.entity = clockDomain->name;
        clockDomain->clkconstr->domain_tmg_id = id;
        constraintObjects.push_back(obj);
        return id;
    }
}

TimingConstrObjectId BaseCtx::timingNetObject(NetInfo *net)
{
    if (net->tmg_id != TimingConstrObjectId()) {
        return net->tmg_id;
    } else {
        TimingConstraintObject obj;
        TimingConstrObjectId id;
        id.index = int(constraintObjects.size());
        obj.id = id;
        obj.type = TimingConstraintObject::NET;
        obj.entity = net->name;
        constraintObjects.push_back(obj);
        net->tmg_id = id;
        return id;
    }
}

TimingConstrObjectId BaseCtx::timingCellObject(CellInfo *cell)
{
    if (cell->tmg_id != TimingConstrObjectId()) {
        return cell->tmg_id;
    } else {
        TimingConstraintObject obj;
        TimingConstrObjectId id;
        id.index = int(constraintObjects.size());
        obj.id = id;
        obj.type = TimingConstraintObject::CELL;
        obj.entity = cell->name;
        constraintObjects.push_back(obj);
        cell->tmg_id = id;
        return id;
    }
}

TimingConstrObjectId BaseCtx::timingPortObject(CellInfo *cell, IdString port)
{
    if (cell->ports.at(port).tmg_id != TimingConstrObjectId()) {
        return cell->ports.at(port).tmg_id;
    } else {
        TimingConstraintObject obj;
        TimingConstrObjectId id;
        id.index = int(constraintObjects.size());
        obj.id = id;
        obj.type = TimingConstraintObject::CELL_PORT;
        obj.entity = cell->name;
        obj.port = port;
        constraintObjects.push_back(obj);
        cell->ports.at(port).tmg_id = id;
        return id;
    }
}

Property::Property() : is_string(false), str(""), intval(0) {}

Property::Property(int64_t intval, int width) : is_string(false), intval(intval)
{
    str.reserve(width);
    for (int i = 0; i < width; i++)
        str.push_back((intval & (1ULL << i)) ? S1 : S0);
}

Property::Property(const std::string &strval) : is_string(true), str(strval), intval(0xDEADBEEF) {}

Property::Property(State bit) : is_string(false), str(std::string("") + char(bit)), intval(bit == S1) {}

std::string Property::to_string() const
{
    if (is_string) {
        std::string result = str;
        int state = 0;
        for (char c : str) {
            if (state == 0) {
                if (c == '0' || c == '1' || c == 'x' || c == 'z')
                    state = 0;
                else if (c == ' ')
                    state = 1;
                else
                    state = 2;
            } else if (state == 1 && c != ' ')
                state = 2;
        }
        if (state < 2)
            result += " ";
        return result;
    } else {
        return std::string(str.rbegin(), str.rend());
    }
}

Property Property::from_string(const std::string &s)
{
    Property p;

    size_t cursor = s.find_first_not_of("01xz");
    if (cursor == std::string::npos) {
        p.str = std::string(s.rbegin(), s.rend());
        p.is_string = false;
        p.update_intval();
    } else if (s.find_first_not_of(' ', cursor) == std::string::npos) {
        p = Property(s.substr(0, s.size() - 1));
    } else {
        p = Property(s);
    }
    return p;
}

void BaseCtx::addConstraint(std::unique_ptr<TimingConstraint> constr)
{
    for (auto fromObj : constr->from)
        constrsFrom.emplace(fromObj, constr.get());
    for (auto toObj : constr->to)
        constrsTo.emplace(toObj, constr.get());
    IdString name = constr->name;
    constraints[name] = std::move(constr);
}

void BaseCtx::removeConstraint(IdString constrName)
{
    TimingConstraint *constr = constraints[constrName].get();
    for (auto fromObj : constr->from) {
        auto fromConstrs = constrsFrom.equal_range(fromObj);
        constrsFrom.erase(std::find(fromConstrs.first, fromConstrs.second, std::make_pair(fromObj, constr)));
    }
    for (auto toObj : constr->to) {
        auto toConstrs = constrsFrom.equal_range(toObj);
        constrsFrom.erase(std::find(toConstrs.first, toConstrs.second, std::make_pair(toObj, constr)));
    }
    constraints.erase(constrName);
}

const char *BaseCtx::nameOfBel(BelId bel) const
{
    const Context *ctx = getCtx();
    return ctx->getBelName(bel).c_str(ctx);
}

const char *BaseCtx::nameOfWire(WireId wire) const
{
    const Context *ctx = getCtx();
    return ctx->getWireName(wire).c_str(ctx);
}

const char *BaseCtx::nameOfPip(PipId pip) const
{
    const Context *ctx = getCtx();
    return ctx->getPipName(pip).c_str(ctx);
}

const char *BaseCtx::nameOfGroup(GroupId group) const
{
    const Context *ctx = getCtx();
    return ctx->getGroupName(group).c_str(ctx);
}

WireId Context::getNetinfoSourceWire(const NetInfo *net_info) const
{
    if (net_info->driver.cell == nullptr)
        return WireId();

    auto src_bel = net_info->driver.cell->bel;

    if (src_bel == BelId())
        return WireId();

    IdString driver_port = net_info->driver.port;

    auto driver_port_it = net_info->driver.cell->pins.find(driver_port);
    if (driver_port_it != net_info->driver.cell->pins.end())
        driver_port = driver_port_it->second;

    return getBelPinWire(src_bel, driver_port);
}

WireId Context::getNetinfoSinkWire(const NetInfo *net_info, const PortRef &user_info) const
{
    auto dst_bel = user_info.cell->bel;

    if (dst_bel == BelId())
        return WireId();

    IdString user_port = user_info.port;

    auto user_port_it = user_info.cell->pins.find(user_port);

    if (user_port_it != user_info.cell->pins.end())
        user_port = user_port_it->second;

    return getBelPinWire(dst_bel, user_port);
}

delay_t Context::getNetinfoRouteDelay(const NetInfo *net_info, const PortRef &user_info) const
{
#ifdef ARCH_ECP5
    if (net_info->is_global)
        return 0;
#endif

    if (net_info->wires.empty())
        return predictDelay(net_info, user_info);

    WireId src_wire = getNetinfoSourceWire(net_info);
    if (src_wire == WireId())
        return 0;

    WireId dst_wire = getNetinfoSinkWire(net_info, user_info);
    WireId cursor = dst_wire;
    delay_t delay = 0;

    while (cursor != WireId() && cursor != src_wire) {
        auto it = net_info->wires.find(cursor);

        if (it == net_info->wires.end())
            break;

        PipId pip = it->second.pip;
        if (pip == PipId())
            break;

        delay += getPipDelay(pip).maxDelay();
        delay += getWireDelay(cursor).maxDelay();
        cursor = getPipSrcWire(pip);
    }

    if (cursor == src_wire)
        return delay + getWireDelay(src_wire).maxDelay();

    return predictDelay(net_info, user_info);
}

static uint32_t xorshift32(uint32_t x)
{
    x ^= x << 13;
    x ^= x >> 17;
    x ^= x << 5;
    return x;
}

uint32_t Context::checksum() const
{
    uint32_t cksum = xorshift32(123456789);

    uint32_t cksum_nets_sum = 0;
    for (auto &it : nets) {
        auto &ni = *it.second;
        uint32_t x = 123456789;
        x = xorshift32(x + xorshift32(it.first.index));
        x = xorshift32(x + xorshift32(ni.name.index));
        if (ni.driver.cell)
            x = xorshift32(x + xorshift32(ni.driver.cell->name.index));
        x = xorshift32(x + xorshift32(ni.driver.port.index));
        x = xorshift32(x + xorshift32(getDelayChecksum(ni.driver.budget)));

        for (auto &u : ni.users) {
            if (u.cell)
                x = xorshift32(x + xorshift32(u.cell->name.index));
            x = xorshift32(x + xorshift32(u.port.index));
            x = xorshift32(x + xorshift32(getDelayChecksum(u.budget)));
        }

        uint32_t attr_x_sum = 0;
        for (auto &a : ni.attrs) {
            uint32_t attr_x = 123456789;
            attr_x = xorshift32(attr_x + xorshift32(a.first.index));
            for (char ch : a.second.str)
                attr_x = xorshift32(attr_x + xorshift32((int)ch));
            attr_x_sum += attr_x;
        }
        x = xorshift32(x + xorshift32(attr_x_sum));

        uint32_t wire_x_sum = 0;
        for (auto &w : ni.wires) {
            uint32_t wire_x = 123456789;
            wire_x = xorshift32(wire_x + xorshift32(getWireChecksum(w.first)));
            wire_x = xorshift32(wire_x + xorshift32(getPipChecksum(w.second.pip)));
            wire_x = xorshift32(wire_x + xorshift32(int(w.second.strength)));
            wire_x_sum += wire_x;
        }
        x = xorshift32(x + xorshift32(wire_x_sum));

        cksum_nets_sum += x;
    }
    cksum = xorshift32(cksum + xorshift32(cksum_nets_sum));

    uint32_t cksum_cells_sum = 0;
    for (auto &it : cells) {
        auto &ci = *it.second;
        uint32_t x = 123456789;
        x = xorshift32(x + xorshift32(it.first.index));
        x = xorshift32(x + xorshift32(ci.name.index));
        x = xorshift32(x + xorshift32(ci.type.index));

        uint32_t port_x_sum = 0;
        for (auto &p : ci.ports) {
            uint32_t port_x = 123456789;
            port_x = xorshift32(port_x + xorshift32(p.first.index));
            port_x = xorshift32(port_x + xorshift32(p.second.name.index));
            if (p.second.net)
                port_x = xorshift32(port_x + xorshift32(p.second.net->name.index));
            port_x = xorshift32(port_x + xorshift32(p.second.type));
            port_x_sum += port_x;
        }
        x = xorshift32(x + xorshift32(port_x_sum));

        uint32_t attr_x_sum = 0;
        for (auto &a : ci.attrs) {
            uint32_t attr_x = 123456789;
            attr_x = xorshift32(attr_x + xorshift32(a.first.index));
            for (char ch : a.second.str)
                attr_x = xorshift32(attr_x + xorshift32((int)ch));
            attr_x_sum += attr_x;
        }
        x = xorshift32(x + xorshift32(attr_x_sum));

        uint32_t param_x_sum = 0;
        for (auto &p : ci.params) {
            uint32_t param_x = 123456789;
            param_x = xorshift32(param_x + xorshift32(p.first.index));
            for (char ch : p.second.str)
                param_x = xorshift32(param_x + xorshift32((int)ch));
            param_x_sum += param_x;
        }
        x = xorshift32(x + xorshift32(param_x_sum));

        x = xorshift32(x + xorshift32(getBelChecksum(ci.bel)));
        x = xorshift32(x + xorshift32(ci.belStrength));

        uint32_t pin_x_sum = 0;
        for (auto &a : ci.pins) {
            uint32_t pin_x = 123456789;
            pin_x = xorshift32(pin_x + xorshift32(a.first.index));
            pin_x = xorshift32(pin_x + xorshift32(a.second.index));
            pin_x_sum += pin_x;
        }
        x = xorshift32(x + xorshift32(pin_x_sum));

        cksum_cells_sum += x;
    }
    cksum = xorshift32(cksum + xorshift32(cksum_cells_sum));

    return cksum;
}

void Context::check() const
{
    for (auto &n : nets) {
        auto ni = n.second.get();
        NPNR_ASSERT(n.first == ni->name);
        for (auto &w : ni->wires) {
            NPNR_ASSERT(ni == getBoundWireNet(w.first));
            if (w.second.pip != PipId()) {
                NPNR_ASSERT(w.first == getPipDstWire(w.second.pip));
                NPNR_ASSERT(ni == getBoundPipNet(w.second.pip));
            }
        }
        if (ni->driver.cell != nullptr)
            NPNR_ASSERT(ni->driver.cell->ports.at(ni->driver.port).net == ni);
        for (auto user : ni->users) {
            NPNR_ASSERT(user.cell->ports.at(user.port).net == ni);
        }
    }

    for (auto w : getWires()) {
        auto ni = getBoundWireNet(w);
        if (ni != nullptr) {
            NPNR_ASSERT(ni->wires.count(w));
        }
    }

    for (auto &c : cells) {
        auto ci = c.second.get();
        NPNR_ASSERT(c.first == ci->name);
        if (ci->bel != BelId())
            NPNR_ASSERT(getBoundBelCell(c.second->bel) == ci);
        for (auto &port : c.second->ports) {
            NetInfo *net = port.second.net;
            if (net != nullptr) {
                NPNR_ASSERT(nets.find(net->name) != nets.end());
                if (port.second.type == PORT_OUT) {
                    NPNR_ASSERT(net->driver.cell == c.second.get() && net->driver.port == port.first);
                } else if (port.second.type == PORT_IN) {
                    NPNR_ASSERT(std::count_if(net->users.begin(), net->users.end(), [&](const PortRef &pr) {
                                    return pr.cell == c.second.get() && pr.port == port.first;
                                }) == 1);
                }
            }
        }
    }
}

void BaseCtx::addClock(IdString net, float freq)
{
    std::unique_ptr<ClockConstraint> cc(new ClockConstraint());
    cc->period = getCtx()->getDelayFromNS(1000 / freq);
    cc->high = getCtx()->getDelayFromNS(500 / freq);
    cc->low = getCtx()->getDelayFromNS(500 / freq);
    if (!nets.count(net)) {
        log_warning("net '%s' does not exist in design, ignoring clock constraint\n", net.c_str(this));
    } else {
        nets.at(net)->clkconstr = std::move(cc);
        log_info("constraining clock net '%s' to %.02f MHz\n", net.c_str(this), freq);
    }
}

void BaseCtx::createRectangularRegion(IdString name, int x0, int y0, int x1, int y1)
{
    std::unique_ptr<Region> new_region(new Region());
    new_region->name = name;
    new_region->constr_bels = true;
    new_region->constr_pips = false;
    new_region->constr_wires = false;
    for (int x = x0; x <= x1; x++) {
        for (int y = y0; y <= y1; y++) {
            for (auto bel : getCtx()->getBelsByTile(x, y))
                new_region->bels.insert(bel);
        }
    }
    region[name] = std::move(new_region);
}
void BaseCtx::addBelToRegion(IdString name, BelId bel) { region[name]->bels.insert(bel); }
void BaseCtx::constrainCellToRegion(IdString cell, IdString region_name)
{
    cells[cell]->region = region[region_name].get();
}
DecalXY BaseCtx::constructDecalXY(DecalId decal, float x, float y)
{
    DecalXY dxy;
    dxy.decal = decal;
    dxy.x = x;
    dxy.y = y;
    return dxy;
}

void BaseCtx::archInfoToAttributes()
{
    for (auto &cell : cells) {
        auto ci = cell.second.get();
        if (ci->bel != BelId()) {
            if (ci->attrs.find(id("BEL")) != ci->attrs.end()) {
                ci->attrs.erase(ci->attrs.find(id("BEL")));
            }
            ci->attrs[id("NEXTPNR_BEL")] = getCtx()->getBelName(ci->bel).str(this);
            ci->attrs[id("BEL_STRENGTH")] = (int)ci->belStrength;
        }
        if (ci->constr_x != ci->UNCONSTR)
            ci->attrs[id("CONSTR_X")] = ci->constr_x;
        if (ci->constr_y != ci->UNCONSTR)
            ci->attrs[id("CONSTR_Y")] = ci->constr_y;
        if (ci->constr_z != ci->UNCONSTR) {
            ci->attrs[id("CONSTR_Z")] = ci->constr_z;
            ci->attrs[id("CONSTR_ABS_Z")] = ci->constr_abs_z ? 1 : 0;
        }
        if (ci->constr_parent != nullptr)
            ci->attrs[id("CONSTR_PARENT")] = ci->constr_parent->name.str(this);
        if (!ci->constr_children.empty()) {
            std::string constr = "";
            for (auto &item : ci->constr_children) {
                if (!constr.empty())
                    constr += std::string(";");
                constr += item->name.c_str(this);
            }
            ci->attrs[id("CONSTR_CHILDREN")] = constr;
        }
    }
    for (auto &net : getCtx()->nets) {
        auto ni = net.second.get();
        std::string routing;
        bool first = true;
        for (auto &item : ni->wires) {
            if (!first)
                routing += ";";
            routing += getCtx()->getWireName(item.first).c_str(this);
            routing += ";";
            if (item.second.pip != PipId())
                routing += getCtx()->getPipName(item.second.pip).c_str(this);
            routing += ";" + std::to_string(item.second.strength);
            first = false;
        }
        ni->attrs[id("ROUTING")] = routing;
    }
}

void BaseCtx::attributesToArchInfo()
{
    for (auto &cell : cells) {
        auto ci = cell.second.get();
        auto val = ci->attrs.find(id("NEXTPNR_BEL"));
        if (val != ci->attrs.end()) {
            auto str = ci->attrs.find(id("BEL_STRENGTH"));
            PlaceStrength strength = PlaceStrength::STRENGTH_USER;
            if (str != ci->attrs.end())
                strength = (PlaceStrength)str->second.as_int64();

            BelId b = getCtx()->getBelByName(id(val->second.as_string()));
            getCtx()->bindBel(b, ci, strength);
        }

        val = ci->attrs.find(id("CONSTR_PARENT"));
        if (val != ci->attrs.end()) {
            auto parent = cells.find(id(val->second.str));
            if (parent != cells.end())
                ci->constr_parent = parent->second.get();
            else
                continue;
        }

        val = ci->attrs.find(id("CONSTR_X"));
        if (val != ci->attrs.end())
            ci->constr_x = val->second.as_int64();

        val = ci->attrs.find(id("CONSTR_Y"));
        if (val != ci->attrs.end())
            ci->constr_y = val->second.as_int64();

        val = ci->attrs.find(id("CONSTR_Z"));
        if (val != ci->attrs.end())
            ci->constr_z = val->second.as_int64();

        val = ci->attrs.find(id("CONSTR_ABS_Z"));
        if (val != ci->attrs.end())
            ci->constr_abs_z = val->second.as_int64() == 1;

        val = ci->attrs.find(id("CONSTR_PARENT"));
        if (val != ci->attrs.end()) {
            auto parent = cells.find(id(val->second.as_string()));
            if (parent != cells.end())
                ci->constr_parent = parent->second.get();
        }
        val = ci->attrs.find(id("CONSTR_CHILDREN"));
        if (val != ci->attrs.end()) {
            std::vector<std::string> strs;
            auto children = val->second.as_string();
            boost::split(strs, children, boost::is_any_of(";"));
            for (auto val : strs) {
                if (cells.count(id(val.c_str())))
                    ci->constr_children.push_back(cells.find(id(val.c_str()))->second.get());
            }
        }
    }
    for (auto &net : getCtx()->nets) {
        auto ni = net.second.get();
        auto val = ni->attrs.find(id("ROUTING"));
        if (val != ni->attrs.end()) {
            std::vector<std::string> strs;
            auto routing = val->second.as_string();
            boost::split(strs, routing, boost::is_any_of(";"));
            for (size_t i = 0; i < strs.size() / 3; i++) {
                std::string wire = strs[i * 3];
                std::string pip = strs[i * 3 + 1];
                PlaceStrength strength = (PlaceStrength)std::stoi(strs[i * 3 + 2]);
                if (pip.empty())
                    getCtx()->bindWire(getCtx()->getWireByName(id(wire)), ni, strength);
                else
                    getCtx()->bindPip(getCtx()->getPipByName(id(pip)), ni, strength);
            }
        }
    }
    getCtx()->assignArchInfo();
}

NEXTPNR_NAMESPACE_END
