/*
 * Copyright 2020-2022 F4PGA Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 */

#include "UhdmAst.h"
#include "frontends/ast/ast.h"
#include "kernel/yosys.h"
#include "uhdmcommonfrontend.h"

#if defined(_MSC_VER)
#include <direct.h>
#include <process.h>
#else
#include <sys/param.h>
#include <unistd.h>
#endif
#include <memory>

#include <list>

#include "Surelog/ErrorReporting/Report.h"
#include "Surelog/surelog.h"

namespace UHDM
{
extern void visit_object(vpiHandle obj_h, int indent, const char *relation, std::set<const BaseClass *> *visited, std::ostream &out,
                         bool shallowVisit = false);
}

namespace systemverilog_plugin
{

using namespace ::Yosys;

// Store systemverilog defaults to be passed for every invocation of read_systemverilog
static std::vector<std::string> systemverilog_defaults;
static std::list<std::vector<std::string>> systemverilog_defaults_stack;

// Store global definitions for top-level defines
static std::vector<std::string> systemverilog_defines;

// SURELOG::scompiler wrapper.
// Owns UHDM/VPI resources used by designs returned from `execute`
class Compiler
{
  public:
    Compiler() = default;
    ~Compiler()
    {
        if (this->scompiler) {
            SURELOG::shutdown_compiler(this->scompiler);
        }
    }

    const std::vector<vpiHandle> &execute(std::unique_ptr<SURELOG::ErrorContainer> errors, std::unique_ptr<SURELOG::CommandLineParser> clp)
    {
        log_assert(!this->errors && !this->clp && !this->scompiler);

        bool success = true;
        bool noFatalErrors = true;
        unsigned int codedReturn = 0;
        clp->setWriteUhdm(false);
        errors->printMessages(clp->muteStdout());
        if (success && (!clp->help())) {
            this->scompiler = SURELOG::start_compiler(clp.get());
            if (!this->scompiler)
                codedReturn |= 1;
            this->designs.push_back(SURELOG::get_uhdm_design(this->scompiler));
        }
        SURELOG::ErrorContainer::Stats stats;
        if (!clp->help()) {
            stats = errors->getErrorStats();
            if (stats.nbFatal)
                codedReturn |= 1;
            if (stats.nbSyntax)
                codedReturn |= 2;
        }
        bool noFErrors = true;
        if (!clp->help())
            noFErrors = errors->printStats(stats, clp->muteStdout());
        if (noFErrors == false) {
            noFatalErrors = false;
        }
        if ((!noFatalErrors) || (!success) || (errors->getErrorStats().nbError))
            codedReturn |= 1;
        if (codedReturn) {
            log_error("Error when parsing design. Aborting!\n");
        }

        this->clp = std::move(clp);
        this->errors = std::move(errors);

        return this->designs;
    }

  private:
    std::unique_ptr<SURELOG::ErrorContainer> errors = nullptr;
    std::unique_ptr<SURELOG::CommandLineParser> clp = nullptr;
    SURELOG::scompiler *scompiler = nullptr;
    std::vector<vpiHandle> designs = {};
};

struct UhdmSurelogAstFrontend : public UhdmCommonFrontend {
    UhdmSurelogAstFrontend(std::string name, std::string short_help) : UhdmCommonFrontend(name, short_help) {}
    UhdmSurelogAstFrontend() : UhdmCommonFrontend("verilog_with_uhdm", "generate/read UHDM file") {}

    void help() override
    {
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
        log("\n");
        log("    read_verilog_with_uhdm [options] [filenames]\n");
        log("\n");
        log("Read SystemVerilog files using Surelog into the current design\n");
        log("\n");
        this->print_read_options();
    }

    AST::AstNode *parse(std::string filename) override
    {
        std::vector<const char *> cstrings;
        bool link = false;
        if (this->shared.formal) {
            systemverilog_defines.push_back("-DFORMAL=1");
        } else {
            systemverilog_defines.push_back("-DSYNTHESIS=1");
        }
        cstrings.reserve(this->args.size() + systemverilog_defaults.size() + systemverilog_defines.size());
        for (size_t i = 0; i < this->args.size(); ++i) {
            cstrings.push_back(const_cast<char *>(this->args[i].c_str()));
            if (this->args[i] == "-link")
                link = true;
        }

        if (!link) {
            // Add systemverilog defaults args
            for (size_t i = 0; i < systemverilog_defaults.size(); ++i) {
                // Convert args to surelog compatible
                if (systemverilog_defaults[i] == "-defer")
                    this->shared.defer = true;
                // Pass any remainings args directly to surelog
                else
                    cstrings.push_back(const_cast<char *>(systemverilog_defaults[i].c_str()));
            }

            // Add systemverilog defines args
            for (size_t i = 0; i < systemverilog_defines.size(); ++i)
                cstrings.push_back(const_cast<char *>(systemverilog_defines[i].c_str()));
        }

        auto symbolTable = std::make_unique<SURELOG::SymbolTable>();
        auto errors = std::make_unique<SURELOG::ErrorContainer>(symbolTable.get());
        auto clp = std::make_unique<SURELOG::CommandLineParser>(errors.get(), symbolTable.get(), false, false);
        bool success = clp->parseCommandLine(cstrings.size(), &cstrings[0]);
        if (!success) {
            log_error("Error parsing Surelog arguments!\n");
        }
        // Force -parse flag settings even if it wasn't specified
        clp->setwritePpOutput(true);
        clp->setParse(true);
        clp->fullSVMode(true);
        clp->setCacheAllowed(true);
        if (this->shared.defer) {
            clp->setCompile(false);
            clp->setElaborate(false);
            clp->setSepComp(true);
        } else {
            clp->setCompile(true);
            clp->setElaborate(true);
        }
        if (this->shared.link) {
            clp->setLink(true);
        }

        Compiler compiler;
        const auto &uhdm_designs = compiler.execute(std::move(errors), std::move(clp));

        if (this->shared.debug_flag || !this->report_directory.empty()) {
            for (auto design : uhdm_designs) {
                std::ofstream null_stream;
                UHDM::visit_object(design, 1, "", &this->shared.report.unhandled, this->shared.debug_flag ? std::cout : null_stream);
            }
        }

        // on parse_only mode, don't try to load design
        // into yosys
        if (this->shared.parse_only)
            return nullptr;

        if (this->shared.defer && !this->shared.link)
            return nullptr;

        // FIXME: SynthSubset annotation is incompatible with separate compilation
        // `-defer` turns elaboration off, so check for it
        // Should be called 1. for normal flow 2. after finishing with `-link`
        if (!this->shared.defer) {
            UHDM::Serializer serializer;
            UHDM::SynthSubset *synthSubset =
              make_new_object_with_optional_extra_true_arg<UHDM::SynthSubset>(&serializer, this->shared.nonSynthesizableObjects, false);
            synthSubset->listenDesigns(uhdm_designs);
            delete synthSubset;
        }

        UhdmAst uhdm_ast(this->shared);
        AST::AstNode *current_ast = uhdm_ast.visit_designs(uhdm_designs);
        if (!this->report_directory.empty()) {
            this->shared.report.write(this->report_directory);
        }

        // FIXME: Check and reset remaining shared data
        this->shared.top_nodes.clear();
        this->shared.nonSynthesizableObjects.clear();
        return current_ast;
    }
    void call_log_header(RTLIL::Design *design) override { log_header(design, "Executing Verilog with UHDM frontend.\n"); }
} UhdmSurelogAstFrontend;

struct UhdmSystemVerilogFrontend : public UhdmSurelogAstFrontend {
    UhdmSystemVerilogFrontend() : UhdmSurelogAstFrontend("systemverilog", "read SystemVerilog files") {}
    void help() override
    {
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
        log("\n");
        log("    read_systemverilog [options] [filenames]\n");
        log("\n");
        log("Read SystemVerilog files using Surelog into the current design\n");
        log("\n");
        this->print_read_options();
        log("    -Ipath\n");
        log("        add include path.\n");
        log("\n");
        log("    -Pparameter=value\n");
        log("        define parameter as value.\n");
        log("\n");
    }
} UhdmSystemVerilogFrontend;

struct SystemVerilogDefaults : public Pass {
    SystemVerilogDefaults() : Pass("systemverilog_defaults", "set default options for read_systemverilog") {}
    void help() override
    {
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
        log("\n");
        log("    systemverilog_defaults -add [options]\n");
        log("\n");
        log("Add the specified options to the list of default options to read_systemverilog.\n");
        log("\n");
        log("\n");
        log("    systemverilog_defaults -clear\n");
        log("\n");
        log("Clear the list of Systemverilog default options.\n");
        log("\n");
        log("\n");
        log("    systemverilog_defaults -push\n");
        log("    systemverilog_defaults -pop\n");
        log("\n");
        log("Push or pop the list of default options to a stack. Note that -push does\n");
        log("not imply -clear.\n");
        log("\n");
    }
    void execute(std::vector<std::string> args, RTLIL::Design *) override
    {
        if (args.size() < 2)
            cmd_error(args, 1, "Missing argument.");

        if (args[1] == "-add") {
            systemverilog_defaults.insert(systemverilog_defaults.end(), args.begin() + 2, args.end());
            return;
        }

        if (args.size() != 2)
            cmd_error(args, 2, "Extra argument.");

        if (args[1] == "-clear") {
            systemverilog_defaults.clear();
            return;
        }

        if (args[1] == "-push") {
            systemverilog_defaults_stack.push_back(systemverilog_defaults);
            return;
        }

        if (args[1] == "-pop") {
            if (systemverilog_defaults_stack.empty()) {
                systemverilog_defaults.clear();
            } else {
                systemverilog_defaults.swap(systemverilog_defaults_stack.back());
                systemverilog_defaults_stack.pop_back();
            }
            return;
        }
    }
} SystemVerilogDefaults;

struct SystemVerilogDefines : public Pass {
    SystemVerilogDefines() : Pass("systemverilog_defines", "define and undefine systemverilog defines")
    {
        systemverilog_defines.push_back("-DYOSYS=1");
    }
    void help() override
    {
        //   |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|
        log("\n");
        log("    systemverilog_defines [options]\n");
        log("\n");
        log("Define and undefine systemverilog preprocessor macros.\n");
        log("\n");
        log("    -Dname[=definition]\n");
        log("        define the preprocessor symbol 'name' and set its optional value\n");
        log("        'definition'\n");
        log("\n");
        log("    -Uname[=definition]\n");
        log("        undefine the preprocessor symbol 'name'\n");
        log("\n");
        log("    -reset\n");
        log("        clear list of defined preprocessor symbols\n");
        log("\n");
        log("    -list\n");
        log("        list currently defined preprocessor symbols\n");
        log("\n");
    }
    void remove(const std::string name)
    {
        auto it = systemverilog_defines.begin();
        while (it != systemverilog_defines.end()) {
            std::string nm;
            size_t equal = (*it).find('=', 2);
            if (equal == std::string::npos)
                nm = (*it).substr(2, std::string::npos);
            else
                nm = (*it).substr(2, equal - 2);
            if (name == nm)
                systemverilog_defines.erase(it);
            else
                it++;
        }
    }
    void dump(void)
    {
        for (size_t i = 0; i < systemverilog_defines.size(); ++i) {
            std::string name, value = "";
            size_t equal = systemverilog_defines[i].find('=', 2);
            name = systemverilog_defines[i].substr(2, equal - 2);
            if (equal != std::string::npos)
                value = systemverilog_defines[i].substr(equal + 1, std::string::npos);
            Yosys::log("`define %s %s\n", name.c_str(), value.c_str());
        }
    }
    void execute(std::vector<std::string> args, RTLIL::Design *design) override
    {
        size_t argidx;
        for (argidx = 1; argidx < args.size(); argidx++) {
            std::string arg = args[argidx];
            if (arg == "-D" && argidx + 1 < args.size()) {
                systemverilog_defines.push_back("-D" + args[++argidx]);
                continue;
            }
            if (arg.compare(0, 2, "-D") == 0) {
                systemverilog_defines.push_back(arg);
                continue;
            }
            if (arg == "-U" && argidx + 1 < args.size()) {
                std::string name = args[++argidx];
                this->remove(name);
                continue;
            }
            if (arg.compare(0, 2, "-U") == 0) {
                std::string name = arg.substr(2);
                this->remove(name);
                continue;
            }
            if (arg == "-reset") {
                systemverilog_defines.erase(systemverilog_defines.begin() + 1, systemverilog_defines.end());
                continue;
            }
            if (arg == "-list") {
                this->dump();
                continue;
            }
            break;
        }

        if (args.size() != argidx)
            cmd_error(args, argidx, "Extra argument.");
    }
} SystemVerilogDefines;

} // namespace systemverilog_plugin
