/*
 * 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/API/Surelog.h"
#include "Surelog/CommandLine/CommandLineParser.h"
#include "Surelog/ErrorReporting/ErrorContainer.h"
#include "Surelog/SourceCompile/SymbolTable.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
