2

yosys はモジュール/セルの入出力ポートの順序を保持しますか? RTL の順序は、読み取り/書き込み時に Verilog の順序と一致することが保証されていますか? yosysによって順序が「予期せず」変更されることはありますか?

4

1 に答える 1

2

Yosys は、モジュール ポートが で宣言されている順序を保存しますRTLIL::Wire::port_id。インスタンスの定位置パラメーターの名前が に変更されました$1, $2, $3, ...。このhierarchyコマンドは、このport_idプロパティを使用して、デザイン エラボレーション中にセル インスタンスのポートの名前を正しく変更します。

モジュールを Verilog ファイルとして書き込む場合port_id、モジュール ヘッダーでポートが宣言される順序を決定するためにワイヤ プロパティが使用されます。

そうです: Yosys はモジュールの入力/出力ポートの順序を保持し、セル インスタンス内の位置パラメーターの名前を解決します。

hierarchy実行されていないか、セル タイプの宣言が使用できない場合、これらのセル インスタンスの位置パラメーターは解決されず、デザインが Verilog ファイルとして書き込まれるときに位置パラメーターとして再びダンプされます。

編集:コメントへの応答: 次のサンプル プラグイン (portsigdemo.cc) は、対応するモジュールのポート宣言の順序ですべてのモジュール ポート / セル ポートを含む SigSpec を作成する方法を示しています。

#include "kernel/yosys.h"
#include "kernel/consteval.h"

USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN

SigSpec get_portsig(Module *module, string direction, Cell *cell = nullptr)
{
    if (cell)
        log_assert(cell->type == module->name);

    SigSpec sig;
    dict<int, SigSpec> sigs;

    for (auto wire : module->wires())
    {
        bool selected = false;

        if (direction == "in")
            selected = wire->port_input;
        else if (direction == "out")
            selected = wire->port_output;
        else
            log_abort();

        if (selected) {
            if (cell) {
                if (cell->hasPort(wire->name))
                    sigs[wire->port_id] = cell->getPort(wire->name);
                else if (cell->hasPort(stringf("$%d", wire->port_id)))
                    sigs[wire->port_id] = cell->getPort(stringf("$%d", wire->port_id));
                else
                    log_abort();
            } else {
                sigs[wire->port_id] = wire;
            }
        }
    }

    sigs.sort();
    for (auto &it : sigs)
        sig.append(it.second);

    return sig;
}

struct PortsigDemoPass : public Pass
{
    PortsigDemoPass():Pass("portsigdemo") { }

    virtual void execute(vector < string >, Design * design)
    {
        for (auto module : design->modules())
        {
            log("Module %s:\n", log_id(module));
            log("  Inputs: %s\n", log_signal(get_portsig(module, "in")));
            log("  Outputs: %s\n", log_signal(get_portsig(module, "out")));

            for (auto cell : module->cells())
            {
                auto cell_type_mod = cell->module->design->module(cell->type);
                if (cell_type_mod) {
                    log("  Cell %s (%s):\n", log_id(cell), log_id(cell->type));
                    log("    Inputs: %s\n", log_signal(get_portsig(cell_type_mod, "in", cell)));
                    log("    Outputs: %s\n", log_signal(get_portsig(cell_type_mod, "out", cell)));
                }
            }
        }
    }
} PortsigDemoPass;

PRIVATE_NAMESPACE_END

使用例:

$ cat > portsigdemo.v << EOT
module mod1 (input [3:0] A, B, output [3:0] Y);
  mod2 mod2_inst0 (.P(A[0]), .Q(B[0]), .X(Y[0]));
  mod2 mod2_inst1 (.P(B[1]), .Q(A[1]), .X(Y[1]));
  mod2 mod2_inst2 (A[2], B[2], Y[2]);
  mod2 mod2_inst3 (B[3], A[3], Y[3]);
endmodule

module mod2 (input P, Q, output X);
  assign X = P ^ Q;
endmodule
EOT

$ yosys-config --build portsigdemo.so portsigdemo.cc
$ yosys -m portsigdemo.so -p portsigdemo portsigdemo.v
...
-- Running command `portsigdemo' --
Module mod2:
  Inputs: { \Q \P }
  Outputs: \X
Module mod1:
  Inputs: { \B \A }
  Outputs: \Y
  Cell mod2_inst3 (mod2):
    Inputs: { \A [3] \B [3] }
    Outputs: \Y [3]
  Cell mod2_inst2 (mod2):
    Inputs: { \B [2] \A [2] }
    Outputs: \Y [2]
  Cell mod2_inst1 (mod2):
    Inputs: { \A [1] \B [1] }
    Outputs: \Y [1]
  Cell mod2_inst0 (mod2):
    Inputs: { \B [0] \A [0] }
    Outputs: \Y [0]

PS: ではportsigdemo.v、セル (モジュール インスタンス) mod1.mod2_inst0 および mod1.mod2_inst1 は名前付きパラメーターを使用しており (モジュール ポートの名前が指定されています)、セル mod1.mod2_inst2 および mod1.mod2_inst3 は位置パラメーターを使用しています (モジュール ポートはパラメータの順序によって決定されます)。

于 2015-08-20T10:49:34.680 に答える