/*
 *  nextpnr -- Next Generation Place and Route
 *
 *  Copyright (C) 2018  Clifford Wolf <clifford@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 <algorithm>
#include <cmath>
#include <regex>
#include "cells.h"
#include "gfx.h"
#include "log.h"
#include "nextpnr.h"
#include "placer1.h"
#include "router1.h"
#include "util.h"

#include "torc/common/DirectoryTree.hpp"

NEXTPNR_NAMESPACE_BEGIN

std::unique_ptr<const TorcInfo> torc_info;
TorcInfo::TorcInfo(BaseCtx *ctx, const std::string &inDeviceName, const std::string &inPackageName)
        : TorcInfo(inDeviceName, inPackageName)
{
    static const std::regex re_loc(".+_X(\\d+)Y(\\d+)");
    std::cmatch what;
    tile_to_xy.resize(tiles.getTileCount());
    for (TileIndex tileIndex(0); tileIndex < tiles.getTileCount(); tileIndex++) {
         const auto &tileInfo = tiles.getTileInfo(tileIndex);
        if (!std::regex_match(tileInfo.getName(), what, re_loc))
            throw;
        const auto x = boost::lexical_cast<int>(what.str(1));
        const auto y = boost::lexical_cast<int>(what.str(2));
        tile_to_xy[tileIndex] = std::make_pair(x,y);
    }

    bel_to_site_index.reserve(sites.getSiteCount() * 4);
    bel_to_loc.reserve(sites.getSiteCount() * 4);
    site_index_to_bel.resize(sites.getSiteCount());
    site_index_to_type.resize(sites.getSiteCount());
    BelId b;
    b.index = 0;
    for (SiteIndex i(0); i < sites.getSiteCount(); ++i) {
        const auto &site = sites.getSite(i);
        const auto &pd = site.getPrimitiveDefPtr();
        const auto &type = pd->getName();
        int x, y;
        std::tie(x,y) = tile_to_xy[site.getTileIndex()];

        if (type == "SLICEL" || type == "SLICEM") {
            bel_to_site_index.push_back(i);
            bel_to_site_index.push_back(i);
            bel_to_site_index.push_back(i);
            bel_to_site_index.push_back(i);
            site_index_to_type[i] = id_SLICE_LUT6;
            const auto site_name = site.getName();
            if (!std::regex_match(site_name.c_str(), what, re_loc))
                throw;
            const auto sx = boost::lexical_cast<int>(what.str(1));
            if ((sx & 1) == 0) {
                bel_to_loc.emplace_back(x, y, 0);
                bel_to_loc.emplace_back(x, y, 1);
                bel_to_loc.emplace_back(x, y, 2);
                bel_to_loc.emplace_back(x, y, 3);
            } else {
                bel_to_loc.emplace_back(x, y, 4);
                bel_to_loc.emplace_back(x, y, 5);
                bel_to_loc.emplace_back(x, y, 6);
                bel_to_loc.emplace_back(x, y, 7);
            }
            site_index_to_bel[i] = b;
            b.index += 4;
        } else if (type == "IOB33S" || type == "IOB33M") {
            bel_to_site_index.push_back(i);
            site_index_to_type[i] = id_IOB33;
            // TODO: Fix z when two IOBs on same tile
            bel_to_loc.emplace_back(x, y, 0);
            site_index_to_bel[i] = b;
            ++b.index;
        } else if (type == "IOB18S" || type == "IOB18M") {
            bel_to_site_index.push_back(i);
            site_index_to_type[i] = id_IOB18;
            // TODO: Fix z when two IOBs on same tile
            bel_to_loc.emplace_back(x, y, 0);
            site_index_to_bel[i] = b;
            ++b.index;
        } else {
            bel_to_site_index.push_back(i);
            site_index_to_type[i] = ctx->id(type);
            bel_to_loc.emplace_back(x, y, 0);
            site_index_to_bel[i] = b;
            ++b.index;
        }
    }
    num_bels = bel_to_site_index.size();
    bel_to_site_index.shrink_to_fit();
    bel_to_loc.shrink_to_fit();

    const std::regex re_124("(.+_)?[NESW][NESWLR](\\d)((BEG(_[NS])?)|(END(_[NS])?)|[A-E])?\\d(_\\d)?");
    const std::regex re_L("(.+_)?L(H|V|VB)(_L)?\\d+(_\\d)?");
    const std::regex re_BYP("BYP(_ALT)?\\d");
    const std::regex re_BYP_B("BYP_[BL]\\d");
    const std::regex re_BOUNCE_NS("(BYP|FAN)_BOUNCE_[NS]3_\\d");
    const std::regex re_FAN("FAN(_ALT)?\\d");
    const std::regex re_CLB_I1_6("CLBL[LM]_(L|LL|M)_[A-D]([1-6])");
    const std::regex bufg_i("CLK_BUFG_BUFGCTRL\\d+_I0");
    const std::regex bufg_o("CLK_BUFG_BUFGCTRL\\d+_O");
    const std::regex hrow("CLK_HROW_CLK[01]_[34]");
    std::unordered_map</*TileTypeIndex*/ unsigned, std::vector<delay_t>> delay_lookup;
    std::unordered_map<Segments::SegmentReference, TileIndex> segment_to_anchor;
    Tilewire currentTilewire;
    WireId w;
    w.index = 0;
    for (TileIndex tileIndex(0); tileIndex < tiles.getTileCount(); tileIndex++) {
        // iterate over every wire in the tile
        const auto &tileInfo = tiles.getTileInfo(tileIndex);
        auto tileTypeIndex = tileInfo.getTypeIndex();
        auto wireCount = tiles.getWireCount(tileTypeIndex);
        currentTilewire.setTileIndex(tileIndex);
        for (WireIndex wireIndex(0); wireIndex < wireCount; wireIndex++) {
            currentTilewire.setWireIndex(wireIndex);
            const auto &currentSegment = segments.getTilewireSegment(currentTilewire);

            if (!currentSegment.isTrivial()) {
                auto r = segment_to_anchor.emplace(currentSegment, currentSegment.getAnchorTileIndex());
                if (r.second) {
                    TilewireVector segment;
                    const_cast<DDB &>(*ddb).expandSegment(currentTilewire, segment, DDB::eExpandDirectionNone);
                    // expand all of the arcs
                    TilewireVector::const_iterator sep = segment.begin();
                    TilewireVector::const_iterator see = segment.end();
                    while(sep < see) {
                        // expand the tilewire sinks
                        const Tilewire& tilewire = *sep++;

                        const auto &tileInfo = tiles.getTileInfo(tilewire.getTileIndex());
                        const auto &tileTypeName = tiles.getTileTypeName(tileInfo.getTypeIndex());
                        if (boost::starts_with(tileTypeName, "INT") || boost::starts_with(tileTypeName, "CLB")) {
                            r.first->second = tilewire.getTileIndex();
                            break;
                        }
                    }
                }
                if (r.first->second != tileIndex)
                    continue;

                segment_to_wire.emplace(currentSegment, w);
            } else
                trivial_to_wire.emplace(currentTilewire, w);

            wire_to_tilewire.push_back(currentTilewire);

            auto it = delay_lookup.find(tileTypeIndex);
            if (it == delay_lookup.end()) {
                auto wireCount = tiles.getWireCount(tileTypeIndex);
                std::vector<delay_t> tile_delays(wireCount);
                for (WireIndex wireIndex(0); wireIndex < wireCount; wireIndex++) {
                    const WireInfo &wireInfo = tiles.getWireInfo(tileTypeIndex, wireIndex);
                    auto wire_name = wireInfo.getName();
                    if (std::regex_match(wire_name, what, re_124)) {
                        switch (what.str(2)[0]) {
                        case '1':
                            tile_delays[wireIndex] = 150;
                            break;
                        case '2':
                            tile_delays[wireIndex] = 170;
                            break;
                        case '4':
                            tile_delays[wireIndex] = 210;
                            break;
                        case '6':
                            tile_delays[wireIndex] = 210;
                            break;
                        default:
                            throw;
                        }
                    } else if (std::regex_match(wire_name, what, re_L)) {
                        std::string l(what[2]);
                        if (l == "H")
                            tile_delays[wireIndex] = 360;
                        else if (l == "VB")
                            tile_delays[wireIndex] = 300;
                        else if (l == "V")
                            tile_delays[wireIndex] = 350;
                        else
                            throw;
                    } else if (std::regex_match(wire_name, what, re_BYP)) {
                        tile_delays[wireIndex] = 190;
                    } else if (std::regex_match(wire_name, what, re_BYP_B)) {
                    } else if (std::regex_match(wire_name, what, re_FAN)) {
                        tile_delays[wireIndex] = 190;
                    } else if (std::regex_match(wire_name, what, re_CLB_I1_6)) {
                        switch (what.str(2)[0]) {
                        case '1':
                            tile_delays[wireIndex] = 280;
                            break;
                        case '2':
                            tile_delays[wireIndex] = 280;
                            break;
                        case '3':
                            tile_delays[wireIndex] = 180;
                            break;
                        case '4':
                            tile_delays[wireIndex] = 180;
                            break;
                        case '5':
                            tile_delays[wireIndex] = 80;
                            break;
                        case '6':
                            tile_delays[wireIndex] = 40;
                            break;
                        default:
                            throw;
                        }
                    }
                }
                it = delay_lookup.emplace(tileTypeIndex, std::move(tile_delays)).first;
            }
            assert(it != delay_lookup.end());

            DelayInfo d;
            d.delay = it->second[currentTilewire.getWireIndex()];
            wire_to_delay.emplace_back(std::move(d));

            ++w.index;
        }
    }
    segment_to_anchor.clear();
    wire_to_tilewire.shrink_to_fit();
    wire_to_delay.shrink_to_fit();
    num_wires = wire_to_tilewire.size();
    wire_is_global.resize(num_wires);

    wire_to_pips_downhill.resize(num_wires);
    // std::unordered_map<Arc, int> arc_to_pip;
    ArcVector arcs;
    ExtendedWireInfo ewi(*ddb);
    PipId p;
    p.index = 0;
    for (w.index = 0; w.index < num_wires; ++w.index) {
        const auto &currentTilewire = wire_to_tilewire[w.index];
        if (currentTilewire.isUndefined())
            continue;

        const auto &tileInfo = tiles.getTileInfo(currentTilewire.getTileIndex());
        const auto tileTypeName = tiles.getTileTypeName(tileInfo.getTypeIndex());
        const bool clb = boost::starts_with(
                tileTypeName, "CLB"); // Disable all CLB route-throughs (i.e. LUT in->out, LUT A->AMUX, for now)

        auto &pips = wire_to_pips_downhill[w.index];
        const bool clk_tile = boost::starts_with(tileTypeName, "CLK");

        bool global_tile = false;

        arcs.clear();
        //const_cast<DDB &>(*ddb).expandSegmentSinks(currentTilewire, arcs, DDB::eExpandDirectionNone,
        //                                           false /* inUseTied */, true /*inUseRegular */,
        //                                           true /* inUseIrregular */, !clb /* inUseRoutethrough */);
        {
            // expand the segment
            TilewireVector segment;
            const_cast<DDB &>(*ddb).expandSegment(currentTilewire, segment, DDB::eExpandDirectionNone);
            // expand all of the arcs
            TilewireVector::const_iterator sep = segment.begin();
            TilewireVector::const_iterator see = segment.end();
            while(sep < see) {
                // expand the tilewire sinks
                const Tilewire& tilewire = *sep++;

                const auto &tileInfo = tiles.getTileInfo(tilewire.getTileIndex());
                const auto &tileTypeName = tiles.getTileTypeName(tileInfo.getTypeIndex());
                global_tile = global_tile || boost::starts_with(tileTypeName, "CLK") || boost::starts_with(tileTypeName, "HCLK") || boost::starts_with(tileTypeName, "CFG");

                TilewireVector sinks;
                const_cast<DDB &>(*ddb).expandTilewireSinks(tilewire, sinks, false /*inUseTied*/, true /*inUseRegular*/, true /*inUseIrregular*/,
                        !clb /* inUseRoutethrough */);
                // rewrite the sinks as arcs
                TilewireVector::const_iterator sip = sinks.begin();
                TilewireVector::const_iterator sie = sinks.end();
                while(sip < sie) {
                    Arc a(tilewire, *sip++);

                    // Disable BUFG I0 -> O routethrough
                    if (clk_tile) {
                        ewi.set(a.getSourceTilewire());
                        if (std::regex_match(ewi.mWireName, bufg_i)) {
                            ewi.set(a.getSinkTilewire());
                            if (std::regex_match(ewi.mWireName, bufg_o))
                                continue;
                        }
                    }

                    // Disable entering HROW from INT_[LR].CLK[01]
                    if (boost::starts_with(tileTypeName, "CLK_HROW")) {
                        ewi.set(a.getSourceTilewire());
                        if (std::regex_match(ewi.mWireName, hrow))
                            continue;
                    }

                    pips.emplace_back(p);
                    pip_to_arc.emplace_back(a);
                    // arc_to_pip.emplace(a, p.index);
                    ++p.index;
                }
            }
        }
        pips.shrink_to_fit();

        if (global_tile)
            wire_is_global[w.index] = true;
    }
    pip_to_arc.shrink_to_fit();
    num_pips = pip_to_arc.size();

    height = (int)tiles.getRowCount();
    width = (int)tiles.getColCount();
}
TorcInfo::TorcInfo(const std::string& inDeviceName, const std::string &inPackageName)
    : ddb(new DDB(inDeviceName, inPackageName)), sites(ddb->getSites()), tiles(ddb->getTiles()),
          segments(ddb->getSegments())
{
}

// -----------------------------------------------------------------------

void IdString::initialize_arch(const BaseCtx *ctx)
{
#define X(t) initialize_add(ctx, #t, ID_##t);
#include "constids.inc"
#undef X
}

// -----------------------------------------------------------------------

Arch::Arch(ArchArgs args) : args(args)
{
    torc::common::DirectoryTree directoryTree("/opt/torc/src/torc");
    if (args.type == ArchArgs::Z020) {
        torc_info = std::unique_ptr<TorcInfo>(new TorcInfo(this, "xc7z020", args.package));
    } else if (args.type == ArchArgs::VX980) {
        torc_info = std::unique_ptr<TorcInfo>(new TorcInfo(this, "xc7vx980t", args.package));
    } else {
        log_error("Unsupported XC7 chip type.\n");
    }

        width = torc_info->width;
        height = torc_info->height;
    /*if (getCtx()->verbose)*/ {
        log_info("Number of bels:  %d\n", torc_info->num_bels);
        log_info("Number of wires: %d\n", torc_info->num_wires);
        log_info("Number of pips:  %d\n", torc_info->num_pips);
    }

    bel_to_cell.resize(torc_info->num_bels);
    wire_to_net.resize(torc_info->num_wires);
    pip_to_net.resize(torc_info->num_pips);
}

// -----------------------------------------------------------------------

std::string Arch::getChipName() const
{
    if (args.type == ArchArgs::Z020) {
        return "z020";
    } else if (args.type == ArchArgs::VX980) {
        return "vx980";
    } else {
        log_error("Unsupported XC7 chip type.\n");
    }
}

// -----------------------------------------------------------------------

IdString Arch::archArgsToId(ArchArgs args) const
{
    if (args.type == ArchArgs::Z020)
        return id("z020");
    if (args.type == ArchArgs::VX980)
        return id("vx980");
    return IdString();
}

// -----------------------------------------------------------------------

static bool endsWith(const std::string& str, const std::string& suffix)
{
    return str.size() >= suffix.size() && 0 == str.compare(str.size()-suffix.size(), suffix.size(), suffix);
}

BelId Arch::getBelByName(IdString name) const
{
    std::string n = name.str(this);
    int ndx = 0;
    if (endsWith(n,"_A") || endsWith(n,"_B") || endsWith(n,"_C") || endsWith(n,"_D"))
    {
        ndx = (int)(n.back() - 'A');
        n = n.substr(0,n.size()-2);
    }
    auto it = torc_info->sites.findSiteIndex(n);
    if (it != SiteIndex(-1)) {
        BelId id = torc_info->site_index_to_bel.at(it);
        id.index += ndx;
        return id;
    }
    return BelId();
}

BelId Arch::getBelByLocation(Loc loc) const
{
    BelId bel;

    if (bel_by_loc.empty()) {
        for (int i = 0; i < torc_info->num_bels; i++) {
            BelId b;
            b.index = i;
            bel_by_loc[getBelLocation(b)] = b;
        }
    }

    auto it = bel_by_loc.find(loc);
    if (it != bel_by_loc.end())
        bel = it->second;

    return bel;
}

BelRange Arch::getBelsByTile(int x, int y) const
{
    BelRange br;

    br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index;
    br.e.cursor = br.b.cursor;

    if (br.e.cursor != -1) {
        while (br.e.cursor < chip_info->num_bels && chip_info->bel_data[br.e.cursor].x == x &&
               chip_info->bel_data[br.e.cursor].y == y)
            br.e.cursor++;
    }

    return br;
}

PortType Arch::getBelPinType(BelId bel, IdString pin) const
{
    NPNR_ASSERT(bel != BelId());

    int num_bel_wires = chip_info->bel_data[bel.index].num_bel_wires;
    const BelWirePOD *bel_wires = chip_info->bel_data[bel.index].bel_wires.get();

    if (num_bel_wires < 7) {
        for (int i = 0; i < num_bel_wires; i++) {
            if (bel_wires[i].port == pin.index)
                return PortType(bel_wires[i].type);
        }
    } else {
        int b = 0, e = num_bel_wires - 1;
        while (b <= e) {
            int i = (b + e) / 2;
            if (bel_wires[i].port == pin.index)
                return PortType(bel_wires[i].type);
            if (bel_wires[i].port > pin.index)
                e = i - 1;
            else
                b = i + 1;
        }
    }

    return PORT_INOUT;
}

std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const
{
    std::vector<std::pair<IdString, std::string>> ret;
    return ret;
}

WireId Arch::getBelPinWire(BelId bel, IdString pin) const
{
    auto pin_name = pin.str(this);
    auto bel_type = getBelType(bel);
    if (bel_type == id_SLICE_LUT6) {
        // For all LUT based inputs and outputs (I1-I6,O,OQ,OMUX) then change the I/O into the LUT
        if (pin_name[0] == 'I' || pin_name[0] == 'O') {
            switch (torc_info->bel_to_loc[bel.index].z) {
            case 0:
            case 4:
                pin_name[0] = 'A';
                break;
            case 1:
            case 5:
                pin_name[0] = 'B';
                break;
            case 2:
            case 6:
                pin_name[0] = 'C';
                break;
            case 3:
            case 7:
                pin_name[0] = 'D';
                break;
            default:
                throw;
            }
        }
    } else if (bel_type == id_PS7 || bel_type == id_MMCME2_ADV) {
        // e.g. Convert DDRARB[0] -> DDRARB0
        pin_name.erase(std::remove_if(pin_name.begin(), pin_name.end(), boost::is_any_of("[]")), pin_name.end());
    }

    auto site_index = torc_info->bel_to_site_index[bel.index];
    const auto &site = torc_info->sites.getSite(site_index);
    auto &tw = site.getPinTilewire(pin_name);

    if (tw.isUndefined())
        log_error("no wire found for site '%s' pin '%s' \n", torc_info->bel_to_name(bel.index).c_str(),
                  pin_name.c_str());

    return torc_info->tilewire_to_wire(tw);
}

std::vector<IdString> Arch::getBelPins(BelId bel) const
{
    std::vector<IdString> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

// -----------------------------------------------------------------------

WireId Arch::getWireByName(IdString name) const
{
    WireId ret;
    if (wire_by_name.empty()) {
        for (int i = 0; i < torc_info->num_wires; i++)
            wire_by_name[id(torc_info->wire_to_name(i))] = i;
    }

    auto it = wire_by_name.find(name);
    if (it != wire_by_name.end())
        ret.index = it->second;

    return ret;
}

IdString Arch::getWireType(WireId wire) const
{
    NPNR_ASSERT(wire != WireId());
    NPNR_ASSERT("TODO");
    return IdString();
}

// -----------------------------------------------------------------------
std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) const
{
    std::vector<std::pair<IdString, std::string>> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

// -----------------------------------------------------------------------

PipId Arch::getPipByName(IdString name) const
{
    PipId ret;

    if (pip_by_name.empty()) {
        for (int i = 0; i < torc_info->num_pips; i++) {
            PipId pip;
            pip.index = i;
            pip_by_name[getPipName(pip)] = i;
        }
    }

    auto it = pip_by_name.find(name);
    if (it != pip_by_name.end())
        ret.index = it->second;

    return ret;
}

IdString Arch::getPipName(PipId pip) const
{
    NPNR_ASSERT(pip != PipId());

    ExtendedWireInfo ewi_src(*torc_info->ddb, torc_info->pip_to_arc[pip.index].getSourceTilewire());
    ExtendedWireInfo ewi_dst(*torc_info->ddb, torc_info->pip_to_arc[pip.index].getSinkTilewire());
    std::stringstream pip_name;
    pip_name << ewi_src.mTileName << "." << ewi_src.mWireName << ".->." << ewi_dst.mWireName;
    return id(pip_name.str());
}

std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId pip) const
{
    std::vector<std::pair<IdString, std::string>> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

// -----------------------------------------------------------------------

BelId Arch::getPackagePinBel(const std::string &pin) const { return getBelByName(id(pin)); }

std::string Arch::getBelPackagePin(BelId bel) const
{
    NPNR_ASSERT("TODO");
    return "";
}

// -----------------------------------------------------------------------

GroupId Arch::getGroupByName(IdString name) const
{
    for (auto g : getGroups())
        if (getGroupName(g) == name)
            return g;
    return GroupId();
}

IdString Arch::getGroupName(GroupId group) const
{
    std::string suffix;

    switch (group.type) {
    NPNR_ASSERT("TODO");
    default:
        return IdString();
    }

    return id("X" + std::to_string(group.x) + "/Y" + std::to_string(group.y) + "/" + suffix);
}

std::vector<GroupId> Arch::getGroups() const
{
    std::vector<GroupId> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

std::vector<BelId> Arch::getGroupBels(GroupId group) const
{
    std::vector<BelId> ret;
    return ret;
}

std::vector<WireId> Arch::getGroupWires(GroupId group) const
{
    std::vector<WireId> ret;
    return ret;
}

std::vector<PipId> Arch::getGroupPips(GroupId group) const
{
    std::vector<PipId> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

std::vector<GroupId> Arch::getGroupGroups(GroupId group) const
{
    std::vector<GroupId> ret;
    NPNR_ASSERT("TODO");
    return ret;
}

// -----------------------------------------------------------------------

bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const { return false; }

// -----------------------------------------------------------------------

bool Arch::place() { return placer1(getCtx(), Placer1Cfg(getCtx())); }

bool Arch::route() { return router1(getCtx(), Router1Cfg(getCtx())); }

// -----------------------------------------------------------------------

DecalXY Arch::getBelDecal(BelId bel) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_BEL;
    decalxy.decal.index = bel.index;
    decalxy.decal.active = bel_to_cell.at(bel.index) != nullptr;
    return decalxy;
}

DecalXY Arch::getWireDecal(WireId wire) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_WIRE;
    decalxy.decal.index = wire.index;
    decalxy.decal.active = wire_to_net.at(wire.index) != nullptr;
    return decalxy;
}

DecalXY Arch::getPipDecal(PipId pip) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_PIP;
    decalxy.decal.index = pip.index;
    decalxy.decal.active = pip_to_net.at(pip.index) != nullptr;
    return decalxy;
};

DecalXY Arch::getGroupDecal(GroupId group) const
{
    DecalXY decalxy;
    decalxy.decal.type = DecalId::TYPE_GROUP;
    decalxy.decal.index = (group.type << 16) | (group.x << 8) | (group.y);
    decalxy.decal.active = true;
    return decalxy;
};

std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
{
    std::vector<GraphicElement> ret;

    if (decal.type == DecalId::TYPE_BEL) {
        BelId bel;
        bel.index = decal.index;
        auto bel_type = getBelType(bel);
        int x = torc_info->bel_to_loc[bel.index].x;
        int y = torc_info->bel_to_loc[bel.index].y;
        int z = torc_info->bel_to_loc[bel.index].z;
        if (bel_type == id_SLICE_LUT6) {
            GraphicElement el;
            /*if (z>3) {
                z = z - 4;
                x -= logic_cell_x2- logic_cell_x1;
            }*/
            el.type = GraphicElement::TYPE_BOX;
            el.style = decal.active ? GraphicElement::STYLE_ACTIVE : GraphicElement::STYLE_INACTIVE;
            el.x1 = x + logic_cell_x1;
            el.x2 = x + logic_cell_x2;
            el.y1 = y + logic_cell_y1 + (z)*logic_cell_pitch;
            el.y2 = y + logic_cell_y2 + (z)*logic_cell_pitch;
            ret.push_back(el);
        }

    }

    return ret;
}

// -----------------------------------------------------------------------

bool Arch::getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const
{
    if (cell->type == id_SLICE_LUT6) {
        if (fromPort.index >= id_I1.index && fromPort.index <= id_I6.index) {
            if (toPort == id_O) {
                delay.delay = 124; // Tilo
                return true;
            }
            if (toPort == id_OQ) {
                delay.delay = 95; // Tas
                return true;
            }
        }
        if (fromPort == id_CLK) {
            if (toPort == id_OQ) {
                delay.delay = 456; // Tcko
                return true;
            }
        }
    } else if (cell->type == id_BUFGCTRL) {
        return true;
    }
    return false;
}

// Get the port class, also setting clockPort to associated clock if applicable
TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const
{
    if (cell->type == id_SLICE_LUT6) {
        if (port == id_CLK)
            return TMG_CLOCK_INPUT;
        if (port == id_CIN)
            return TMG_COMB_INPUT;
        if (port == id_COUT)
            return TMG_COMB_OUTPUT;
        if (port == id_O) {
            // LCs with no inputs are constant drivers
            if (cell->lcInfo.inputCount == 0)
                return TMG_IGNORE;
            return TMG_COMB_OUTPUT;
        }
        if (cell->lcInfo.dffEnable) {
            clockInfoCount = 1;
            if (port == id_OQ)
                return TMG_REGISTER_OUTPUT;
            return TMG_REGISTER_INPUT;
        } else {
            return TMG_COMB_INPUT;
        }
        // TODO
        // if (port == id_OMUX)
    } else if (cell->type == id_IOB33 || cell->type == id_IOB18) {
        if (port == id_I)
            return TMG_STARTPOINT;
        else if (port == id_O)
            return TMG_ENDPOINT;
    } else if (cell->type == id_BUFGCTRL) {
        if (port == id_O)
            return TMG_COMB_OUTPUT;
        return TMG_COMB_INPUT;
    } else if (cell->type == id_PS7) {
        // TODO
        return TMG_IGNORE;
    } else if (cell->type == id_MMCME2_ADV) {
        return TMG_IGNORE;
    }
    log_error("no timing info for port '%s' of cell type '%s'\n", port.c_str(this), cell->type.c_str(this));
}

TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port, int index) const
{
    TimingClockingInfo info;
    if (cell->type == id_SLICE_LUT6) {
        info.clock_port = id_CLK;
        info.edge = cell->lcInfo.negClk ? FALLING_EDGE : RISING_EDGE;
        if (port == id_OQ) {
            bool has_clktoq = getCellDelay(cell, id_CLK, id_OQ, info.clockToQ);
            NPNR_ASSERT(has_clktoq);
        } else {
            info.setup.delay = 124; // Tilo
            info.hold.delay = 0;
        }
    } else {
        NPNR_ASSERT_FALSE("unhandled cell type in getPortClockingInfo");
    }
    return info;
}

bool Arch::isGlobalNet(const NetInfo *net) const
{
    if (net == nullptr)
        return false;
    return net->driver.cell != nullptr && net->driver.cell->type == id_BUFGCTRL && net->driver.port == id_O;
}

// Assign arch arg info
void Arch::assignArchInfo()
{
    for (auto &net : getCtx()->nets) {
        NetInfo *ni = net.second.get();
        if (isGlobalNet(ni))
            ni->is_global = true;
        ni->is_enable = false;
        ni->is_reset = false;
        for (auto usr : ni->users) {
            if (is_enable_port(this, usr))
                ni->is_enable = true;
            if (is_reset_port(this, usr))
                ni->is_reset = true;
        }
    }
    for (auto &cell : getCtx()->cells) {
        CellInfo *ci = cell.second.get();
        assignCellInfo(ci);
    }
}

void Arch::assignCellInfo(CellInfo *cell)
{
    cell->belType = cell->type;
    if (cell->type == id_SLICE_LUT6) {
        cell->lcInfo.dffEnable = bool_or_default(cell->params, id_DFF_ENABLE);
        cell->lcInfo.carryEnable = bool_or_default(cell->params, id_CARRY_ENABLE);
        cell->lcInfo.negClk = bool_or_default(cell->params, id_NEG_CLK);
        cell->lcInfo.clk = get_net_or_empty(cell, id_CLK);
        cell->lcInfo.cen = get_net_or_empty(cell, id_CEN);
        cell->lcInfo.sr = get_net_or_empty(cell, id_SR);
        cell->lcInfo.inputCount = 0;
        if (get_net_or_empty(cell, id_I1))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I2))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I3))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I4))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I5))
            cell->lcInfo.inputCount++;
        if (get_net_or_empty(cell, id_I6))
            cell->lcInfo.inputCount++;
    }
}

NEXTPNR_NAMESPACE_END
