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

NEXTPNR_NAMESPACE_BEGIN

// Read a w

// Apply PCF constraints to a pre-packing design
bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
{
    try {
        if (!in)
            log_error("failed to open PCF file\n");
        std::string line;
        int lineno = 0;
        while (std::getline(in, line)) {
            lineno++;
            size_t cstart = line.find("#");
            if (cstart != std::string::npos)
                line = line.substr(0, cstart);
            std::stringstream ss(line);
            std::vector<std::string> words;
            std::string tmp;
            while (ss >> tmp)
                words.push_back(tmp);
            if (words.size() == 0)
                continue;
            std::string cmd = words.at(0);
            bool nowarn = false;
            if (cmd == "set_io") {
                size_t args_end = 1;
                std::vector<std::pair<IdString, std::string>> extra_attrs;
                while (args_end < words.size() && words.at(args_end).at(0) == '-') {
                    const auto &setting = words.at(args_end);
                    if (setting == "-pullup") {
                        const auto &value = words.at(++args_end);
                        if (value == "yes" || value == "1")
                            extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP"), "1"));
                        else if (value == "no" || value == "0")
                            extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP"), "0"));
                        else
                            log_error("Invalid value '%s' for -pullup (on line %d)\n", value.c_str(), lineno);
                    } else if (setting == "-pullup_resistor") {
                        const auto &value = words.at(++args_end);
                        if (ctx->args.type != ArchArgs::UP5K)
                            log_error("Pullup resistance can only be set on UP5K (on line %d)\n", lineno);
                        if (value != "3P3K" && value != "6P8K" && value != "10K" && value != "100K")
                            log_error("Invalid value '%s' for -pullup_resistor (on line %d)\n", value.c_str(), lineno);
                        extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP_RESISTOR"), value));
                    } else if (setting == "-nowarn") {
                        nowarn = true;
                    } else if (setting == "--warn-no-port") {
                    } else {
                        log_warning("Ignoring PCF setting '%s' (on line %d)\n", setting.c_str(), lineno);
                    }
                    args_end++;
                }
                if (args_end > words.size() - 2)
                    log_error("expected PCF syntax 'set_io cell pin' (on line %d)\n", lineno);
                else if (args_end < words.size() - 2 && !nowarn)
                    log_warning("Ignoring trailing PCF settings (on line %d)\n", lineno);

                std::string cell = words.at(args_end);
                std::string pin = words.at(args_end + 1);
                auto fnd_cell = ctx->cells.find(ctx->id(cell));
                if (fnd_cell == ctx->cells.end()) {
                    if (!nowarn)
                        log_warning("unmatched constraint '%s' (on line %d)\n", cell.c_str(), lineno);
                } else {
                    BelId pin_bel = ctx->getPackagePinBel(pin);
                    if (pin_bel == BelId())
                        log_error("package does not have a pin named '%s' (on line %d)\n", pin.c_str(), lineno);
                    if (fnd_cell->second->attrs.count(ctx->id("BEL")))
                        log_error("duplicate pin constraint on '%s' (on line %d)\n", cell.c_str(), lineno);
                    fnd_cell->second->attrs[ctx->id("BEL")] = ctx->getBelName(pin_bel).str(ctx);
                    log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
                             fnd_cell->second->attrs[ctx->id("BEL")].c_str());
                    for (const auto &attr : extra_attrs)
                        fnd_cell->second->attrs[attr.first] = attr.second;
                }
            } else {
                log_error("unsupported PCF command '%s' (on line %d)\n", cmd.c_str(), lineno);
            }
        }
        for (auto cell : sorted(ctx->cells)) {
            CellInfo *ci = cell.second;
            if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
                ci->type == ctx->id("$nextpnr_iobuf")) {
                if (!ci->attrs.count(ctx->id("BEL"))) {
                    if (bool_or_default(ctx->settings, ctx->id("pcf_allow_unconstrained")))
                        log_warning("IO '%s' is unconstrained in PCF and will be automatically placed\n",
                                    cell.first.c_str(ctx));
                    else
                        log_error("IO '%s' is unconstrained in PCF (override this error with "
                                  "--pcf-allow-unconstrained)\n",
                                  cell.first.c_str(ctx));
                }
            }
        }
        ctx->settings[ctx->id("input/pcf")] = filename;
        return true;
    } catch (log_execution_error_exception) {
        return false;
    }
}

NEXTPNR_NAMESPACE_END
