/*
 * 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 "kernel/log.h"
#include "kernel/register.h"
#include "kernel/rtlil.h"
#include "kernel/sigtools.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

#define MODE_BITS_BASE_SIZE 80
#define MODE_BITS_EXTENSION_SIZE 13

// ============================================================================

struct QlDspSimdPass : public Pass {

    QlDspSimdPass() : Pass("ql_dsp_simd", "Infers QuickLogic k6n10f DSP pairs that can operate in SIMD mode") {}

    void help() override
    {
        log("\n");
        log("    ql_dsp_simd [selection]\n");
        log("\n");
        log("    This pass identifies k6n10f DSP cells with identical configuration\n");
        log("    and packs pairs of them together into other DSP cells that can\n");
        log("    perform SIMD operation.\n");
    }

    // ..........................................

    /// Describes DSP config unique to a whole DSP cell
    struct DspConfig {

        // Port connections
        dict<RTLIL::IdString, RTLIL::SigSpec> connections;

        // Whether DSPs pass configuration bits through ports of parameters
        bool use_cfg_params;

        // TODO: Possibly include parameters here. For now we have just
        // connections.

        DspConfig() = default;

        DspConfig(const DspConfig &ref) = default;
        DspConfig(DspConfig &&ref) = default;

        unsigned int hash() const { return connections.hash(); }

        bool operator==(const DspConfig &ref) const { return connections == ref.connections && use_cfg_params == ref.use_cfg_params; }
    };

    // ..........................................

    // DSP control and config ports to consider and how to map them to ports
    // of the target DSP cell
    const std::vector<std::pair<std::string, std::string>> m_DspCfgPorts = {std::make_pair("clock_i", "clk"),
                                                                            std::make_pair("reset_i", "reset"),

                                                                            std::make_pair("feedback_i", "feedback"),
                                                                            std::make_pair("load_acc_i", "load_acc"),
                                                                            std::make_pair("unsigned_a_i", "unsigned_a"),
                                                                            std::make_pair("unsigned_b_i", "unsigned_b"),

                                                                            std::make_pair("subtract_i", "subtract")};
    // For QL_DSP2 expand with configuration ports
    const std::vector<std::pair<std::string, std::string>> m_DspCfgPorts_expand = {
      std::make_pair("output_select_i", "output_select"), std::make_pair("saturate_enable_i", "saturate_enable"),
      std::make_pair("shift_right_i", "shift_right"), std::make_pair("round_i", "round"), std::make_pair("register_inputs_i", "register_inputs")};

    // For QL_DSP3 use parameters instead
    const std::vector<std::string> m_DspParams2Mode = {"OUTPUT_SELECT", "SATURATE_ENABLE", "SHIFT_RIGHT", "ROUND", "REGISTER_INPUTS"};

    // DSP data ports and how to map them to ports of the target DSP cell
    const std::vector<std::pair<std::string, std::string>> m_DspDataPorts = {
      std::make_pair("a_i", "a"), std::make_pair("b_i", "b"),         std::make_pair("acc_fir_i", "acc_fir"),
      std::make_pair("z_o", "z"), std::make_pair("dly_b_o", "dly_b"),
    };

    // DSP parameters
    const std::vector<std::string> m_DspParams = {"COEFF_3", "COEFF_2", "COEFF_1", "COEFF_0"};

    // Source DSP cell type (SISD)
    const std::string m_SisdDspType = "dsp_t1_10x9x32";
    // Suffix for DSP cell with configuration parameters
    const std::string m_SisdDspType_cfg_params_suffix = "_cfg_params";

    // Target DSP cell types for the SIMD mode
    const std::string m_SimdDspType_cfg_ports = "QL_DSP2";
    const std::string m_SimdDspType_cfg_params = "QL_DSP3";

    /// Temporary SigBit to SigBit helper map.
    SigMap m_SigMap;

    // ..........................................

    void execute(std::vector<std::string> a_Args, RTLIL::Design *a_Design) override
    {
        log_header(a_Design, "Executing QL_DSP_SIMD pass.\n");

        // Parse args
        extra_args(a_Args, 1, a_Design);

        // Process modules
        for (auto module : a_Design->selected_modules()) {

            // Setup the SigMap
            m_SigMap.clear();
            m_SigMap.set(module);

            // Assemble DSP cell groups
            dict<DspConfig, std::vector<RTLIL::Cell *>> groups;
            for (auto cell : module->selected_cells()) {

                // Check if this is a DSP cell we are looking for (type starts with m_SisdDspType)
                if (strncmp(cell->type.c_str(), RTLIL::escape_id(m_SisdDspType).c_str(), RTLIL::escape_id(m_SisdDspType).size()) != 0) {
                    continue;
                }

                // Skip if it has the (* keep *) attribute set
                if (cell->has_keep_attr()) {
                    continue;
                }

                // Add to a group
                const auto key = getDspConfig(cell);
                groups[key].push_back(cell);
            }

            std::vector<const RTLIL::Cell *> cellsToRemove;

            // Map cell pairs to the target DSP SIMD cell
            for (const auto &it : groups) {
                const auto &group = it.second;
                const auto &config = it.first;

                bool use_cfg_params = config.use_cfg_params;
                // Ensure an even number
                size_t count = group.size();
                if (count & 1)
                    count--;

                // Map SIMD pairs
                for (size_t i = 0; i < count; i += 2) {
                    const RTLIL::Cell *dsp_a = group[i];
                    const RTLIL::Cell *dsp_b = group[i + 1];

                    std::string name = stringf("simd_%s_%s", RTLIL::unescape_id(dsp_a->name).c_str(), RTLIL::unescape_id(dsp_b->name).c_str());
                    std::string SimdDspType;

                    if (use_cfg_params)
                        SimdDspType = m_SimdDspType_cfg_params;
                    else
                        SimdDspType = m_SimdDspType_cfg_ports;

                    log(" SIMD: %s (%s) + %s (%s) => %s (%s)\n", RTLIL::unescape_id(dsp_a->name).c_str(), RTLIL::unescape_id(dsp_a->type).c_str(),
                        RTLIL::unescape_id(dsp_b->name).c_str(), RTLIL::unescape_id(dsp_b->type).c_str(), RTLIL::unescape_id(name).c_str(),
                        SimdDspType.c_str());

                    // Create the new cell
                    RTLIL::Cell *simd = module->addCell(RTLIL::escape_id(name), RTLIL::escape_id(SimdDspType));

                    // Check if the target cell is known (important to know
                    // its port widths)
                    if (!simd->known()) {
                        log_error(" The target cell type '%s' is not known!", SimdDspType.c_str());
                    }

                    std::vector<std::pair<std::string, std::string>> DspCfgPorts = m_DspCfgPorts;
                    if (!use_cfg_params)
                        DspCfgPorts.insert(DspCfgPorts.end(), m_DspCfgPorts_expand.begin(), m_DspCfgPorts_expand.end());

                    // Connect common ports
                    for (const auto &it : DspCfgPorts) {
                        auto sport = RTLIL::escape_id(it.first);
                        auto dport = RTLIL::escape_id(it.second);

                        simd->setPort(dport, config.connections.at(sport));
                    }

                    // Connect data ports
                    for (const auto &it : m_DspDataPorts) {
                        auto sport = RTLIL::escape_id(it.first);
                        auto dport = RTLIL::escape_id(it.second);

                        size_t width;
                        bool isOutput;

                        std::tie(width, isOutput) = getPortInfo(simd, dport);

                        auto getConnection = [&](const RTLIL::Cell *cell) {
                            RTLIL::SigSpec sigspec;
                            if (cell->hasPort(sport)) {
                                const auto &sig = cell->getPort(sport);
                                sigspec.append(sig);
                            }
                            if (sigspec.bits().size() < width / 2) {
                                if (isOutput) {
                                    for (size_t i = 0; i < width / 2 - sigspec.bits().size(); ++i) {
                                        sigspec.append(RTLIL::SigSpec());
                                    }
                                } else {
                                    sigspec.append(RTLIL::SigSpec(RTLIL::Sx, width / 2 - sigspec.bits().size()));
                                }
                            }
                            return sigspec;
                        };

                        RTLIL::SigSpec sigspec;
                        sigspec.append(getConnection(dsp_a));
                        sigspec.append(getConnection(dsp_b));
                        simd->setPort(dport, sigspec);
                    }

                    // Concatenate FIR coefficient parameters into the single
                    // MODE_BITS parameter
                    std::vector<RTLIL::State> mode_bits;
                    for (const auto &it : m_DspParams) {
                        auto val_a = dsp_a->getParam(RTLIL::escape_id(it));
                        auto val_b = dsp_b->getParam(RTLIL::escape_id(it));

                        mode_bits.insert(mode_bits.end(), val_a.begin(), val_a.end());
                        mode_bits.insert(mode_bits.end(), val_b.begin(), val_b.end());
                    }
                    long unsigned int mode_bits_size = MODE_BITS_BASE_SIZE;
                    if (use_cfg_params) {
                        // Add additional config parameters if necessary
                        mode_bits.push_back(RTLIL::S1); // MODE_BITS[80] == F_MODE : Enable fractured mode
                        for (const auto &it : m_DspParams2Mode) {
                            log_assert(dsp_a->getParam(RTLIL::escape_id(it)) == dsp_b->getParam(RTLIL::escape_id(it)));
                            auto param = dsp_a->getParam(RTLIL::escape_id(it));
                            if (param.size() > 1) {
                                mode_bits.insert(mode_bits.end(), param.bits.begin(), param.bits.end());
                            } else {
                                mode_bits.push_back(param.bits[0]);
                            }
                        }
                        mode_bits_size += MODE_BITS_EXTENSION_SIZE;
                    } else {
                        // Enable the fractured mode by connecting the control
                        // port.
                        simd->setPort(RTLIL::escape_id("f_mode"), RTLIL::S1);
                    }
                    simd->setParam(RTLIL::escape_id("MODE_BITS"), RTLIL::Const(mode_bits));
                    log_assert(mode_bits.size() == mode_bits_size);

                    // Mark DSP parts for removal
                    cellsToRemove.push_back(dsp_a);
                    cellsToRemove.push_back(dsp_b);
                }
            }

            // Remove old cells
            for (const auto &cell : cellsToRemove) {
                module->remove(const_cast<RTLIL::Cell *>(cell));
            }
        }

        // Clear
        m_SigMap.clear();
    }

    // ..........................................

    /// Looks up port width and direction in the cell definition and returns it.
    /// Returns (0, false) if it cannot be determined.
    std::pair<size_t, bool> getPortInfo(RTLIL::Cell *a_Cell, RTLIL::IdString a_Port)
    {
        if (!a_Cell->known()) {
            return std::make_pair(0, false);
        }

        // Get the module defining the cell (the previous condition ensures
        // that the pointers are valid)
        RTLIL::Module *mod = a_Cell->module->design->module(a_Cell->type);
        if (mod == nullptr) {
            return std::make_pair(0, false);
        }

        // Get the wire representing the port
        RTLIL::Wire *wire = mod->wire(a_Port);
        if (wire == nullptr) {
            return std::make_pair(0, false);
        }

        return std::make_pair(wire->width, wire->port_output);
    }

    /// Given a DSP cell populates and returns a DspConfig struct for it.
    DspConfig getDspConfig(RTLIL::Cell *a_Cell)
    {
        DspConfig config;

        string cell_type = a_Cell->type.str();
        string suffix = m_SisdDspType_cfg_params_suffix;

        bool use_cfg_params = cell_type.size() >= suffix.size() && 0 == cell_type.compare(cell_type.size() - suffix.size(), suffix.size(), suffix);

        std::vector<std::pair<std::string, std::string>> DspCfgPorts = m_DspCfgPorts;
        if (!use_cfg_params)
            DspCfgPorts.insert(DspCfgPorts.end(), m_DspCfgPorts_expand.begin(), m_DspCfgPorts_expand.end());

        config.use_cfg_params = use_cfg_params;

        for (const auto &it : DspCfgPorts) {
            auto port = RTLIL::escape_id(it.first);

            // Port unconnected
            if (!a_Cell->hasPort(port)) {
                config.connections[port] = RTLIL::SigSpec(RTLIL::Sx);
                continue;
            }

            // Get the port connection and map it to unique SigBits
            const auto &orgSigSpec = a_Cell->getPort(port);
            const auto &orgSigBits = orgSigSpec.bits();

            RTLIL::SigSpec newSigSpec;
            for (size_t i = 0; i < orgSigBits.size(); ++i) {
                auto newSigBit = m_SigMap(orgSigBits[i]);
                newSigSpec.append(newSigBit);
            }

            // Store
            config.connections[port] = newSigSpec;
        }

        return config;
    }

} QlDspSimdPass;

PRIVATE_NAMESPACE_END
