/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
 *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
 *  Copyright (C) 2018  Serge Bazanski <q3k@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 "cells.h"
#include "nextpnr.h"
#include "util.h"

#include <boost/range/iterator_range.hpp>

NEXTPNR_NAMESPACE_BEGIN

bool Arch::logicCellsCompatible(const CellInfo **it, const size_t size) const
{
    bool dffs_exist = false, dffs_neg = false;
    const NetInfo *cen = nullptr, *clk = nullptr, *sr = nullptr;
    int locals_count = 0;

    for (auto cell : boost::make_iterator_range(it, it + size)) {
        NPNR_ASSERT(cell->type == id_ICESTORM_LC);
        if (cell->lcInfo.dffEnable) {
            if (!dffs_exist) {
                dffs_exist = true;
                cen = cell->lcInfo.cen;
                clk = cell->lcInfo.clk;
                sr = cell->lcInfo.sr;

                if (cen != nullptr && !cen->is_global)
                    locals_count++;
                if (clk != nullptr && !clk->is_global)
                    locals_count++;
                if (sr != nullptr && !sr->is_global)
                    locals_count++;

                if (cell->lcInfo.negClk) {
                    dffs_neg = true;
                }
            } else {
                if (cen != cell->lcInfo.cen)
                    return false;
                if (clk != cell->lcInfo.clk)
                    return false;
                if (sr != cell->lcInfo.sr)
                    return false;
                if (dffs_neg != cell->lcInfo.negClk)
                    return false;
            }
        }

        locals_count += cell->lcInfo.inputCount;
    }

    return locals_count <= 32;
}

bool Arch::isBelLocationValid(BelId bel) const
{
    if (getBelType(bel) == id_ICESTORM_LC) {
        std::array<const CellInfo *, 8> bel_cells;
        size_t num_cells = 0;
        Loc bel_loc = getBelLocation(bel);
        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
            CellInfo *ci_other = getBoundBelCell(bel_other);
            if (ci_other != nullptr)
                bel_cells[num_cells++] = ci_other;
        }
        return logicCellsCompatible(bel_cells.data(), num_cells);
    } else {
        CellInfo *ci = getBoundBelCell(bel);
        if (ci == nullptr)
            return true;
        else
            return isValidBelForCell(ci, bel);
    }
}

static inline bool _io_pintype_need_clk_in(unsigned pin_type) { return (pin_type & 0x01) == 0x00; }

static inline bool _io_pintype_need_clk_out(unsigned pin_type)
{
    return ((pin_type & 0x30) == 0x30) || ((pin_type & 0x3c) && ((pin_type & 0x0c) != 0x08));
}

static inline bool _io_pintype_need_clk_en(unsigned pin_type)
{
    return _io_pintype_need_clk_in(pin_type) || _io_pintype_need_clk_out(pin_type);
}

bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
{
    if (cell->type == id_ICESTORM_LC) {
        NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC);

        std::array<const CellInfo *, 8> bel_cells;
        size_t num_cells = 0;

        Loc bel_loc = getBelLocation(bel);
        for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
            CellInfo *ci_other = getBoundBelCell(bel_other);
            if (ci_other != nullptr && bel_other != bel)
                bel_cells[num_cells++] = ci_other;
        }

        bel_cells[num_cells++] = cell;
        return logicCellsCompatible(bel_cells.data(), num_cells);
    } else if (cell->type == id_SB_IO) {
        // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to.

        // Find shared PLL by looking for driving bel siblings from D_IN_0
        // that are a PLL clock output.
        auto wire = getBelPinWire(bel, id_D_IN_0);
        for (auto pin : getWireBelPins(wire)) {
            if (pin.pin == id_PLLOUT_A || pin.pin == id_PLLOUT_B) {
                // Is there a PLL there ?
                auto pll_cell = getBoundBelCell(pin.bel);
                if (pll_cell == nullptr)
                    break;

                // Is that port actually used ?
                if ((pin.pin == id_PLLOUT_B) && !is_sb_pll40_dual(this, pll_cell))
                    break;

                // Is that SB_IO used at an input ?
                if ((cell->ports[id_D_IN_0].net == nullptr) && (cell->ports[id_D_IN_1].net == nullptr))
                    break;

                // Are we perhaps a PAD INPUT Bel that can be placed here?
                if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this))
                    return true;

                // Conflict
                return false;
            }
        }

        Loc ioLoc = getBelLocation(bel);
        Loc compLoc = ioLoc;
        compLoc.z = 1 - compLoc.z;

        // Check LVDS pairing
        if (cell->ioInfo.lvds) {
            // Check correct z and complement location is free
            if (ioLoc.z != 0)
                return false;
            BelId compBel = getBelByLocation(compLoc);
            CellInfo *compCell = getBoundBelCell(compBel);
            if (compCell)
                return false;
        } else {
            // Check LVDS IO is not placed at complement location
            BelId compBel = getBelByLocation(compLoc);
            CellInfo *compCell = getBoundBelCell(compBel);
            if (compCell && compCell->ioInfo.lvds)
                return false;

            // Check for conflicts on shared nets
            // - CLOCK_ENABLE
            // - OUTPUT_CLK
            // - INPUT_CLK
            if (compCell) {
                bool use[6] = {
                        _io_pintype_need_clk_in(cell->ioInfo.pintype),
                        _io_pintype_need_clk_in(compCell->ioInfo.pintype),
                        _io_pintype_need_clk_out(cell->ioInfo.pintype),
                        _io_pintype_need_clk_out(compCell->ioInfo.pintype),
                        _io_pintype_need_clk_en(cell->ioInfo.pintype),
                        _io_pintype_need_clk_en(compCell->ioInfo.pintype),
                };
                NetInfo *nets[] = {
                        cell->ports[id_INPUT_CLK].net,    compCell->ports[id_INPUT_CLK].net,
                        cell->ports[id_OUTPUT_CLK].net,   compCell->ports[id_OUTPUT_CLK].net,
                        cell->ports[id_CLOCK_ENABLE].net, compCell->ports[id_CLOCK_ENABLE].net,
                };

                for (int i = 0; i < 6; i++)
                    if (use[i] && (nets[i] != nets[i ^ 1]) && (use[i ^ 1] || (nets[i ^ 1] != nullptr)))
                        return false;
            }
        }

        return getBelPackagePin(bel) != "";
    } else if (cell->type == id_SB_GB) {
        if (cell->gbInfo.forPadIn)
            return true;
        NPNR_ASSERT(cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net != nullptr);
        const NetInfo *net = cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net;
        int glb_id = getDrivenGlobalNetwork(bel);
        if (net->is_reset && net->is_enable)
            return false;
        else if (net->is_reset)
            return (glb_id % 2) == 0;
        else if (net->is_enable)
            return (glb_id % 2) == 1;
        else
            return true;
    } else {
        // TODO: IO cell clock checks
        return true;
    }
}

NEXTPNR_NAMESPACE_END
