以下の内容はhttps://msyksphinz.hatenablog.com/entry/2025/12/26/040000より取得しました。


common_cells リポジトリに含まれる stream_モジュールの構成分析 (3. ストリーム・インタフェースのルーティング・接続モジュール)

stream_mux.sv

複数の入力ストリームから1つの出力ストリームへ選択的に接続するマルチプレクサモジュールである。

/// Stream multiplexer: connects the output to one of `N_INP` data streams with valid-ready
/// handshaking.

module stream_mux #(
  parameter type DATA_T = logic,  // Vivado requires a default value for type parameters.
  parameter integer N_INP = 0,    // Synopsys DC requires a default value for value parameters.
  /// Dependent parameters, DO NOT OVERRIDE!
  parameter integer LOG_N_INP = $clog2(N_INP)
) (
  input  DATA_T [N_INP-1:0]     inp_data_i,
  input  logic  [N_INP-1:0]     inp_valid_i,
  output logic  [N_INP-1:0]     inp_ready_o,

  input  logic  [LOG_N_INP-1:0] inp_sel_i,

  output DATA_T                 oup_data_o,
  output logic                  oup_valid_o,
  input  logic                  oup_ready_i
);

  always_comb begin
    inp_ready_o = '0;
    inp_ready_o[inp_sel_i] = oup_ready_i;
  end
  assign oup_data_o   = inp_data_i[inp_sel_i];
  assign oup_valid_o  = inp_valid_i[inp_sel_i];

`ifndef COMMON_CELLS_ASSERTS_OFF
  `ASSERT_INIT(n_inp_0, N_INP >= 1, "The number of inputs must be at least 1!")
`endif

endmodule

選択された入力のみがready信号を受け取り、それ以外の入力はready信号が0になる。

stream_demux.sv

1つの入力ストリームを複数の出力ストリームへ選択的に分配するデマルチプレクサモジュールである。 データポートを持たないため、データは外部で複数の出力に接続される必要がある。

/// Connects the input stream (valid-ready) handshake to one of `N_OUP` output stream handshakes.
///
/// This module has no data ports because stream data does not need to be demultiplexed: the data of
/// the input stream can just be applied at all output streams.
module stream_demux #(
  /// Number of connected outputs.
  parameter int unsigned N_OUP     = 32'd1,
  /// Dependent parameters, DO NOT OVERRIDE!
  parameter int unsigned LOG_N_OUP = (N_OUP > 32'd1) ? unsigned'($clog2(N_OUP)) : 1'b1
) (
  input  logic                 inp_valid_i,
  output logic                 inp_ready_o,

  input  logic [LOG_N_OUP-1:0] oup_sel_i,

  output logic [N_OUP-1:0]     oup_valid_o,
  input  logic [N_OUP-1:0]     oup_ready_i
);

  always_comb begin
    oup_valid_o = '0;
    oup_valid_o[oup_sel_i] = inp_valid_i;
  end
  assign inp_ready_o = oup_ready_i[oup_sel_i];

endmodule

選択された出力のみがvalid信号をアサートし、選択された出力のready信号が入力のready信号になる。

stream_xbar.sv

完全結合型のストリームクロスバーモジュールである。 複数の入力から複数の出力への任意の接続を実現し、各出力に対してrr_arb_treeを使用したアービトレーションを提供する。

/// Fully connected stream crossbar.
///
/// Handshaking rules as defined by the `AMBA AXI` standard on default.
module stream_xbar #(
  /// Number of inputs into the crossbar (`> 0`).
  parameter int unsigned NumInp      = 32'd0,
  /// Number of outputs from the crossbar (`> 0`).
  parameter int unsigned NumOut      = 32'd0,
  /// Data width of the stream. Can be overwritten by defining the type parameter `payload_t`.
  parameter int unsigned DataWidth   = 32'd1,
  /// Payload type of the data ports, only usage of parameter `DataWidth`.
  parameter type         payload_t   = logic [DataWidth-1:0],
  /// Adds a spill register stage at each output.
  parameter bit          OutSpillReg = 1'b0,
  /// Use external priority for the individual `rr_arb_trees`.
  parameter int unsigned ExtPrio     = 1'b0,
  /// Use strict AXI valid ready handshaking.
  /// To be protocol conform also the parameter `LockIn` has to be set.
  parameter int unsigned AxiVldRdy   = 1'b1,
  /// Lock in the arbitration decision of the `rr_arb_tree`.
  /// When this is set, valids have to be asserted until the corresponding transaction is indicated
  /// by ready.
  parameter int unsigned LockIn      = 1'b1,
  /// If `AxiVldReady` is 1, which bits of the payload to check for stability on valid inputs.
  /// In some cases, we may want to allow parts of the payload to change depending on the value of
  /// other parts (e.g. write data in read requests), requiring more nuanced external assertions.
  parameter payload_t    AxiVldMask  = '1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Width of the output selection signal.
  parameter int unsigned SelWidth = (NumOut > 32'd1) ? unsigned'($clog2(NumOut)) : 32'd1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Signal type definition for selecting the output at the inputs.
  parameter type sel_oup_t = logic[SelWidth-1:0],
  /// Derived parameter, do **not** overwrite!
  ///
  /// Width of the input index signal.
  parameter int unsigned IdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Signal type definition indicating from which input the output came.
  parameter type idx_inp_t = logic[IdxWidth-1:0]
) (
  /// Clock, positive edge triggered.
  input  logic                  clk_i,
  /// Asynchronous reset, active low.
  input  logic                  rst_ni,
  /// Flush the state of the internal `rr_arb_tree` modules.
  /// If not used set to `0`.
  /// Flush should only be used if there are no active `valid_i`, otherwise it will
  /// not adhere to the AXI handshaking.
  input  logic                  flush_i,
  /// Provide an external state for the `rr_arb_tree` models.
  /// Will only do something if ExtPrio is `1` otherwise tie to `0`.
  input  idx_inp_t [NumOut-1:0] rr_i,
  /// Input data ports.
  /// Has to be stable as long as `valid_i` is asserted when parameter `AxiVldRdy` is set.
  input  payload_t [NumInp-1:0] data_i,
  /// Selection of the output port where the data should be routed.
  /// Has to be stable as long as `valid_i` is asserted and parameter `AxiVldRdy` is set.
  input  sel_oup_t [NumInp-1:0] sel_i,
  /// Input is valid.
  input  logic     [NumInp-1:0] valid_i,
  /// Input is ready to accept data.
  output logic     [NumInp-1:0] ready_o,
  /// Output data ports. Valid if `valid_o = 1`
  output payload_t [NumOut-1:0] data_o,
  /// Index of the input port where data came from.
  output idx_inp_t [NumOut-1:0] idx_o,
  /// Output is valid.
  output logic     [NumOut-1:0] valid_o,
  /// Output can be accepted.
  input  logic     [NumOut-1:0] ready_i
);
  typedef struct packed {
    payload_t data;
    idx_inp_t idx;
  } spill_data_t;

  logic     [NumInp-1:0][NumOut-1:0] inp_valid;
  logic     [NumInp-1:0][NumOut-1:0] inp_ready;

  payload_t [NumOut-1:0][NumInp-1:0] out_data;
  logic     [NumOut-1:0][NumInp-1:0] out_valid;
  logic     [NumOut-1:0][NumInp-1:0] out_ready;

  // Generate the input selection
  for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_inps
    stream_demux #(
      .N_OUP ( NumOut )
    ) i_stream_demux (
      .inp_valid_i ( valid_i[i]   ),
      .inp_ready_o ( ready_o[i]   ),
      .oup_sel_i   ( sel_i[i]     ),
      .oup_valid_o ( inp_valid[i] ),
      .oup_ready_i ( inp_ready[i] )
    );

    // Do the switching cross of the signals.
    for (genvar j = 0; unsigned'(j) < NumOut; j++) begin : gen_cross
      // Propagate the data from this input to all outputs.
      assign out_data[j][i]  = data_i[i];
      // switch handshaking
      assign out_valid[j][i] = inp_valid[i][j];
      assign inp_ready[i][j] = out_ready[j][i];
    end
  end

  // Generate the output arbitration.
  for (genvar j = 0; unsigned'(j) < NumOut; j++) begin : gen_outs
    spill_data_t arb;
    logic        arb_valid, arb_ready;

    rr_arb_tree #(
      .NumIn     ( NumInp    ),
      .DataType  ( payload_t ),
      .ExtPrio   ( ExtPrio   ),
      .AxiVldRdy ( AxiVldRdy ),
      .LockIn    ( LockIn    )
    ) i_rr_arb_tree (
      .clk_i,
      .rst_ni,
      .flush_i,
      .rr_i    ( rr_i[j]      ),
      .req_i   ( out_valid[j] ),
      .gnt_o   ( out_ready[j] ),
      .data_i  ( out_data[j]  ),
      .req_o   ( arb_valid    ),
      .gnt_i   ( arb_ready    ),
      .data_o  ( arb.data     ),
      .idx_o   ( arb.idx      )
    );

    spill_data_t spill;

    spill_register #(
      .T      ( spill_data_t ),
      .Bypass ( !OutSpillReg )
    ) i_spill_register (
      .clk_i,
      .rst_ni,
      .valid_i ( arb_valid  ),
      .ready_o ( arb_ready  ),
      .data_i  ( arb        ),
      .valid_o ( valid_o[j] ),
      .ready_i ( ready_i[j] ),
      .data_o  ( spill      )
    );
    // Assign the outputs (deaggregate the data).
    always_comb begin
      data_o[j] = spill.data;
      idx_o[j]  = spill.idx;
    end
  end

  // Assertions
  // Make sure that the handshake and payload is stable
  `ifndef COMMON_CELLS_ASSERTS_OFF
  for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_sel_assertions
    `ASSERT(non_existing_output, valid_i[i] |-> sel_i[i] < NumOut, clk_i, !rst_ni,
            "Non-existing output is selected!")
  end

  if (AxiVldRdy) begin : gen_handshake_assertions
    for (genvar i = 0; unsigned'(i) < NumInp; i++) begin : gen_inp_assertions
      `ASSERT(input_data_unstable, valid_i[i] && !ready_o[i] |=> $stable(data_i[i] & AxiVldMask),
              clk_i, !rst_ni, $sformatf("data_i is unstable at input: %0d", i))
      `ASSERT(input_sel_unstable, valid_i[i] && !ready_o[i] |=> $stable(sel_i[i]), clk_i, !rst_ni,
              $sformatf("sel_i is unstable at input: %0d", i))
      `ASSERT(input_valid_taken, valid_i[i] && !ready_o[i] |=> valid_i[i], clk_i, !rst_ni,
              $sformatf("valid_i at input %0d has been taken away without a ready.", i))
    end
    for (genvar i = 0; unsigned'(i) < NumOut; i++) begin : gen_out_assertions
      `ASSERT(output_data_unstable, valid_o[i] && !ready_i[i] |=> $stable(data_o[i] & AxiVldMask),
              clk_i, !rst_ni,
              $sformatf("data_o is unstable at output: %0d Check that parameter LockIn is set.", i))
      `ASSERT(output_idx_unstable, valid_o[i] && !ready_i[i] |=> $stable(idx_o[i]), clk_i, !rst_ni,
              $sformatf("idx_o is unstable at output: %0d Check that parameter LockIn is set.", i))
      `ASSERT(output_valid_taken, valid_o[i] && !ready_i[i] |=> valid_o[i], clk_i, !rst_ni,
              $sformatf("valid_o at output %0d has been taken away without a ready.", i))
    end
  end

  `ASSERT_INIT(numinp_0, NumInp > 32'd0, "NumInp has to be > 0!")
  `ASSERT_INIT(numout_0, NumOut > 32'd0, "NumOut has to be > 0!")
  `endif
endmodule

主要パラメータの説明:

  • NumInp (Number of inputs): クロスバーへの入力ポート数を指定する。この値は0より大きい必要がある。各入力に対してstream_demuxモジュールが生成され、入力データを選択された出力ポートへルーティングする。入力ポート数に応じて、IdxWidthパラメータ(入力インデックス信号の幅)が自動的に計算される($clog2(NumInp))。

  • NumOut (Number of outputs): クロスバーからの出力ポート数を指定する。この値は0より大きい必要がある。各出力に対してrr_arb_treeモジュールが生成され、複数の入力からの要求をアービトレーションする。出力ポート数に応じて、SelWidthパラメータ(出力選択信号の幅)が自動的に計算される($clog2(NumOut))。

クロスバーは完全結合型であるため、NumInp個の入力からNumOut個の出力への任意の接続が可能である。各入力はsel_i信号により、どの出力ポートへデータを送信するかを指定する。

その他のパラメータ:

  • DataWidth: ストリームのデータ幅を指定する。デフォルト値は1。payload_tパラメータで型を指定した場合は、このパラメータは使用されない。

  • payload_t: ストリームで転送するデータの型を指定する。デフォルト値はlogic [DataWidth-1:0]。カスタム型(構造体など)を指定することで、任意のデータ構造を転送できる。

  • OutSpillReg: 各出力にスピルレジスタステージを追加するかどうかを指定する。デフォルト値は0(追加しない)。1に設定すると、各出力にレジスタステージが追加され、タイミング特性が改善されるが、レイテンシが1クロックサイクル増加する。

  • ExtPrio: 各出力のrr_arb_treeで外部優先度を使用するかどうかを指定する。デフォルト値は0(使用しない)。1に設定すると、rr_i信号により外部から優先度を制御できる。

  • AxiVldRdy: 厳密なAXI準拠のready/validハンドシェイクを使用するかどうかを指定する。デフォルト値は1(使用する)。1の場合、valid_iがアサートされている間、data_isel_iが安定している必要がある。プロトコル準拠のためには、LockInパラメータも1に設定する必要がある。

  • LockIn: アービトレーション決定をロックするかどうかを指定する。デフォルト値は1(ロックする)。1の場合、valid_iは対応するトランザクションがready_oで示されるまでアサートされ続ける必要がある。これにより、AXI準拠の動作が保証される。

  • AxiVldMask: AxiVldRdy1の場合、ペイロードのどのビットを安定性チェックの対象とするかを指定する。デフォルト値は'1(すべてのビット)。一部のビットのみをチェック対象としたい場合(例: リードリクエスト内のライトデータなど)に使用する。

  • SelWidth, sel_oup_t: 派生パラメータ(上書き禁止)。SelWidthは出力選択信号の幅($clog2(NumOut))、sel_oup_tはその型定義。各入力のsel_i信号の型として使用される。

  • IdxWidth, idx_inp_t: 派生パラメータ(上書き禁止)。IdxWidthは入力インデックス信号の幅($clog2(NumInp))、idx_inp_tはその型定義。各出力のidx_o信号(データがどの入力から来たかを示す)の型として使用される。

クロスバーの構成図 (NumInp=3, NumOut=3の例):

入力側                    クロス接続部                    出力側
┌───────────┐                                         ┌───────────┐
│ Input 0   │───┐                                     │Output 0   │
│           │   │  ┌──────────┐      ┌──────────┐     │           │
│ sel_i[0]  │───┼──┤          │      │          │──┼──┤           │
│ data_i[0] │   │  │          │      │          │  │  │ data_o[0] │
│ valid_i[0]│   │  │          │      │          │  │  │ valid_o[0]│
│ ready_o[0]│   │  │          │      │          │  │  │ ready_i[0]│
└───────────┘   │  │          │      │          │  │  └───────────┘
                │  │          │      │          │  │
┌───────────┐   │  │ stream_  │      │ rr_arb_  │  │  ┌───────────┐
│ Input 1   │───┼──┤ demux[0] │      │ tree[0]  │──┼──│Output 1   │
│           │   │  │          │      │          │  │  │           │
│ sel_i[1]  │───┼──┤          │      │          │──┼──┤           │
│ data_i[1] │   │  │          │      │          │  │  │ data_o[1] │
│ valid_i[1]│   │  │          │      │          │  │  │ valid_o[1]│
│ ready_o[1]│   │  │          │      │          │  │  │ ready_i[1]│
└───────────┘   │  │          │      │          │  │  └───────────┘
                │  │          │      │          │  │
┌───────────┐   │  │          │      │          │  │  ┌───────────┐
│ Input 2   │───┼──┤          │      │          │──┼──│Output 2   │
│           │   │  │          │      │          │  │  │           │
│ sel_i[2]  │───┼──┤          │      │          │──┼──┤           │
│ data_i[2] │   │  │          │      │          │  │  │ data_o[2] │
│ valid_i[2]│   │  │          │      │          │  │  │ valid_o[2]│
│ ready_o[2]│   │  │          │      │          │  │  │ ready_i[2]│
└───────────┘   │  └──────────┘      └──────────┘  │  └───────────┘
                │                                  │
                └──────────────────────────────────┘
                         (完全結合型の接続)

データフローの詳細:

各入力はstream_demuxにより、sel_i信号で指定された出力へルーティングされる。 すべての入力のデータはすべての出力に接続されており、各出力のrr_arb_treeが複数の入力からの要求をアービトレーションする。

例: Input 0がOutput 2へ、Input 1がOutput 0へ、Input 2がOutput 1へ送信する場合

Input 0 ──[sel_i=2]──> stream_demux[0] ──> すべての出力へ接続
                                                      │
                                                      ├─> Output 0 (rr_arb_tree[0]でアービトレーション)
                                                      ├─> Output 1 (rr_arb_tree[1]でアービトレーション)
                                                      └─> Output 2 (rr_arb_tree[2]でアービトレーション) ← 選択

Input 1 ──[sel_i=0]──> stream_demux[1] ──> すべての出力へ接続
                                                      │
                                                      ├─> Output 0 (rr_arb_tree[0]でアービトレーション) ← 選択
                                                      ├─> Output 1 (rr_arb_tree[1]でアービトレーション)
                                                      └─> Output 2 (rr_arb_tree[2]でアービトレーション)

Input 2 ──[sel_i=1]──> stream_demux[2] ──> すべての出力へ接続
                                                      │
                                                      ├─> Output 0 (rr_arb_tree[0]でアービトレーション)
                                                      ├─> Output 1 (rr_arb_tree[1]でアービトレーション) ← 選択
                                                      └─> Output 2 (rr_arb_tree[2]でアービトレーション)

アービトレーションの仕組み:

各出力にはrr_arb_treeが接続されており、複数の入力からの同時要求を処理する。 ラウンドロビン方式で公平にアービトレーションが行われる。

Output 0への要求:
  Input 0 ──[valid]──> rr_arb_tree[0] ──> Output 0
  Input 1 ──[valid]──> rr_arb_tree[0] ──> Output 0
  Input 2 ──[valid]──> rr_arb_tree[0] ──> Output 0
                    │
                    └─> ラウンドロビンで1つを選択

オプション: スピルレジスタ (OutSpillReg=1の場合):

各出力にスピルレジスタが追加され、タイミング特性が改善される。

rr_arb_tree[0] ──> spill_register ──> Output 0
rr_arb_tree[1] ──> spill_register ──> Output 1
rr_arb_tree[2] ──> spill_register ──> Output 2

クロスバーは以下のように動作する: 1. 各入力はstream_demuxにより選択された出力へルーティングされる 2. 各出力に対して、複数の入力からの要求をrr_arb_treeでアービトレーションする 3. オプションで出力にスピルレジスタを追加可能

stream_omega_net.sv

オメガネットワーク(バタフライネットワークと同型)を実装したモジュールである。 複数のstream_xbarをスイッチとして使用し、大規模な接続を効率的に実現する。

/// Omega network using multiple `stream_xbar` as switches.
///
/// An omega network is isomorphic to a butterfly network.
///
/// Handshaking rules as defined by the `AMBA AXI` standard on default.
module stream_omega_net #(
  /// Number of inputs into the network (`> 0`).
  parameter int unsigned NumInp      = 32'd0,
  /// Number of outputs from the network (`> 0`).
  parameter int unsigned NumOut      = 32'd0,
  /// Radix of the individual switch points of the network.
  /// Currently supported are `32'd2` and `32'd4`.
  parameter int unsigned Radix       = 32'd2,
  /// Data width of the stream. Can be overwritten by defining the type parameter `payload_t`.
  parameter int unsigned DataWidth   = 32'd1,
  /// Payload type of the data ports, only usage of parameter `DataWidth`.
  parameter type         payload_t   = logic [DataWidth-1:0],
  /// Adds a spill register stage at each output.
  parameter bit          SpillReg = 1'b0,
  /// Use external priority for the individual `rr_arb_trees`.
  parameter int unsigned ExtPrio     = 1'b0,
  /// Use strict AXI valid ready handshaking.
  /// To be protocol conform also the parameter `LockIn` has to be set.
  parameter int unsigned AxiVldRdy   = 1'b1,
  /// Lock in the arbitration decision of the `rr_arb_tree`.
  /// When this is set, valids have to be asserted until the corresponding transaction is indicated
  /// by ready.
  parameter int unsigned LockIn      = 1'b1,
  /// If `AxiVldReady` is 1, which bits of the payload to check for stability on valid inputs.
  /// In some cases, we may want to allow parts of the payload to change depending on the value of
  /// other parts (e.g. write data in read requests), requiring more nuanced external assertions.
  parameter payload_t    AxiVldMask  = '1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Width of the output selection signal.
  parameter int unsigned SelWidth = (NumOut > 32'd1) ? unsigned'($clog2(NumOut)) : 32'd1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Signal type definition for selecting the output at the inputs.
  parameter type sel_oup_t = logic[SelWidth-1:0],
  /// Derived parameter, do **not** overwrite!
  ///
  /// Width of the input index signal.
  parameter int unsigned IdxWidth = (NumInp > 32'd1) ? unsigned'($clog2(NumInp)) : 32'd1,
  /// Derived parameter, do **not** overwrite!
  ///
  /// Signal type definition indicating from which input the output came.
  parameter type idx_inp_t = logic[IdxWidth-1:0]
) (
  /// Clock, positive edge triggered.
  input  logic                  clk_i,
  /// Asynchronous reset, active low.
  input  logic                  rst_ni,
  /// Flush the state of the internal `rr_arb_tree` modules.
  /// If not used set to `0`.
  /// Flush should only be used if there are no active `valid_i`, otherwise it will
  /// not adhere to the AXI handshaking.
  input  logic                  flush_i,
  /// Provide an external state for the `rr_arb_tree` models.
  /// Will only do something if ExtPrio is `1` otherwise tie to `0`.
  input  idx_inp_t [NumOut-1:0] rr_i,
  /// Input data ports.
  /// Has to be stable as long as `valid_i` is asserted when parameter `AxiVldRdy` is set.
  input  payload_t [NumInp-1:0] data_i,
  /// Selection of the output port where the data should be routed.
  /// Has to be stable as long as `valid_i` is asserted and parameter `AxiVldRdy` is set.
  input  sel_oup_t [NumInp-1:0] sel_i,
  /// Input is valid.
  input  logic     [NumInp-1:0] valid_i,
  /// Input is ready to accept data.
  output logic     [NumInp-1:0] ready_o,
  /// Output data ports. Valid if `valid_o = 1`
  output payload_t [NumOut-1:0] data_o,
  /// Index of the input port where data came from.
  output idx_inp_t [NumOut-1:0] idx_o,
  /// Output is valid.
  output logic     [NumOut-1:0] valid_o,
  /// Output can be accepted.
  input  logic     [NumOut-1:0] ready_i
);

主要パラメータの説明:

  • NumInp (Number of inputs): ネットワークへの入力ポート数を指定する。この値は0より大きい必要がある。

  • NumOut (Number of outputs): ネットワークからの出力ポート数を指定する。この値は0より大きい必要がある。

  • Radix: ネットワーク内の各スイッチポイントのラディクス(基数)を指定する。現在サポートされている値は24のみ。ラディクスは、各スイッチが同時に処理できる入出力の数を決定する。Radix=2の場合、各スイッチは2入力×2出力、Radix=4の場合は4入力×4出力となる。ラディクスが大きいほど、より多くの接続を効率的に処理できるが、ハードウェアリソースも増加する。

動作の特徴:

1. 縮退ケース (NumInp <= Radix && NumOut <= Radix):

入力数と出力数がラディクス以下の場合は、stream_xbarに縮退する。これは、単一のクロスバーで十分に接続を実現できるためである。

例: NumInp=2, NumOut=2, Radix=2の場合

Input 0 ──┐
          ├──> stream_xbar ──┬──> Output 0
Input 1 ──┘                  └──> Output 1

2. 多段ネットワーク (それ以外の場合):

複数段のルーターを構成する。各段でperfect shuffle(完全シャッフル)を行い、パケットを目的地へルーティングする。

オメガネットワークの構造図 (NumInp=8, NumOut=8, Radix=2の例):

en.wikipedia.org

Perfect Shuffleの概念:

各段の間でperfect shuffleが行われ、パケットが再配置される。これにより、任意の入力から任意の出力への接続が可能になる。

Perfect Shuffle (Radix=2の場合):
段0の出力 → 段1の入力への接続パターン

Router 0, Output 0 ──> Router 0, Input 0
Router 0, Output 1 ──> Router 1, Input 0
Router 1, Output 0 ──> Router 0, Input 1
Router 1, Output 1 ──> Router 1, Input 1
...

各スイッチの構造:

各段の各ルーターは、stream_xbarで実装されたRadix×Radixのクロスバーである。

各ルーター (Radix=2の場合):
         ┌─────────────┐
Input 0 ─┤             ├──> Output 0
         │ stream_xbar │
Input 1 ─┤  (2×2)      ├──> Output 1
         └─────────────┘

ルーティングの仕組み:

各パケットは、目的地の出力アドレスのビットを使用して、各段でルーティングされる。 - 段0: 最上位ビットを使用 - 段1: 次のビットを使用 - 段2: 最下位ビットを使用

これにより、段数はceil(log_Radix(NumLanes))となる。

オメガネットワークは、バタフライネットワークと同型であり、大規模な接続を効率的に実現するための多段ネットワークトポロジーを提供する。




以上の内容はhttps://msyksphinz.hatenablog.com/entry/2025/12/26/040000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14