RISC_V GPU skybox 系列 core 模块之VX_issue.sv

VX_issue_top.sv

// Copyright © 2019-2023
//
// 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.

`include "VX_define.vh"

module VX_issue_top import VX_gpu_pkg::*; #(
    parameter `STRING INSTANCE_ID = "issue"
) (
    // Clock
    input wire                              clk,
    input wire                              reset,

    input wire                              decode_valid,
    input wire [`UUID_WIDTH-1:0]            decode_uuid,
    input wire [`NW_WIDTH-1:0]              decode_wid,
    input wire [`NUM_THREADS-1:0]           decode_tmask,
    input wire [`PC_BITS-1:0]               decode_PC,
    input wire [`EX_BITS-1:0]               decode_ex_type,
    input wire [`INST_OP_BITS-1:0]          decode_op_type,
    input op_args_t                         decode_op_args,
    input wire                              decode_wb,
    input wire [`NR_BITS-1:0]               decode_rd,
    input wire [`NR_BITS-1:0]               decode_rs1,
    input wire [`NR_BITS-1:0]               decode_rs2,
    input wire [`NR_BITS-1:0]               decode_rs3,
    output wire                             decode_ready,

    input wire                              writeback_valid[`ISSUE_WIDTH],
    input wire [`UUID_WIDTH-1:0]            writeback_uuid[`ISSUE_WIDTH],
    input wire [ISSUE_WIS_W-1:0]            writeback_wis[`ISSUE_WIDTH],
    input wire [`NUM_THREADS-1:0]           writeback_tmask[`ISSUE_WIDTH],
    input wire [`PC_BITS-1:0]               writeback_PC[`ISSUE_WIDTH],
    input wire [`NR_BITS-1:0]               writeback_rd[`ISSUE_WIDTH],
    input wire [`NUM_THREADS-1:0][`XLEN-1:0] writeback_data[`ISSUE_WIDTH],
    input wire                              writeback_sop[`ISSUE_WIDTH],
    input wire                              writeback_eop[`ISSUE_WIDTH],

    output wire                             dispatch_valid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`UUID_WIDTH-1:0]           dispatch_uuid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [ISSUE_WIS_W-1:0]           dispatch_wis[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0]          dispatch_tmask[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`PC_BITS-1:0]              dispatch_PC[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`INST_ALU_BITS-1:0]        dispatch_op_type[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output op_args_t                        dispatch_op_args[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire                             dispatch_wb[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NR_BITS-1:0]              dispatch_rd[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NT_WIDTH-1:0]             dispatch_tid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs1_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs2_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs3_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    input wire                             dispatch_ready[`NUM_EX_UNITS * `ISSUE_WIDTH]
);

    VX_decode_if    decode_if();
    VX_dispatch_if  dispatch_if[`NUM_EX_UNITS * `ISSUE_WIDTH]();
    VX_writeback_if writeback_if[`ISSUE_WIDTH]();

    assign decode_if.valid = decode_valid;
    assign decode_if.data.uuid = decode_uuid;
    assign decode_if.data.wid = decode_wid;
    assign decode_if.data.tmask = decode_tmask;
    assign decode_if.data.PC = decode_PC;
    assign decode_if.data.ex_type = decode_ex_type;
    assign decode_if.data.op_type = decode_op_type;
    assign decode_if.data.op_args = decode_op_args;
    assign decode_if.data.wb = decode_wb;
    assign decode_if.data.rd = decode_rd;
    assign decode_if.data.rs1 = decode_rs1;
    assign decode_if.data.rs2 = decode_rs2;
    assign decode_if.data.rs3 = decode_rs3;
    assign decode_ready = decode_if.ready;

    for (genvar i = 0; i < `ISSUE_WIDTH; ++i) begin
        assign writeback_if[i].valid = writeback_valid[i];
        assign writeback_if[i].data.uuid = writeback_uuid[i];
        assign writeback_if[i].data.wis = writeback_wis[i];
        assign writeback_if[i].data.tmask = writeback_tmask[i];
        assign writeback_if[i].data.PC = writeback_PC[i];
        assign writeback_if[i].data.rd = writeback_rd[i];
        assign writeback_if[i].data.data = writeback_data[i];
        assign writeback_if[i].data.sop = writeback_sop[i];
        assign writeback_if[i].data.eop = writeback_eop[i];
    end

    for (genvar i = 0; i < `NUM_EX_UNITS * `ISSUE_WIDTH; ++i) begin
        assign dispatch_valid[i] = dispatch_if[i].valid;
        assign dispatch_uuid[i] = dispatch_if[i].data.uuid;
        assign dispatch_wis[i] = dispatch_if[i].data.wis;
        assign dispatch_tmask[i] = dispatch_if[i].data.tmask;
        assign dispatch_PC[i] = dispatch_if[i].data.PC;
        assign dispatch_op_type[i] = dispatch_if[i].data.op_type;
        assign dispatch_op_args[i] = dispatch_if[i].data.op_args;
        assign dispatch_wb[i] = dispatch_if[i].data.wb;
        assign dispatch_rd[i] = dispatch_if[i].data.rd;
        assign dispatch_tid[i] = dispatch_if[i].data.tid;
        assign dispatch_rs1_data[i] = dispatch_if[i].data.rs1_data;
        assign dispatch_rs2_data[i] = dispatch_if[i].data.rs2_data;
        assign dispatch_rs3_data[i] = dispatch_if[i].data.rs3_data;
        assign dispatch_if[i].ready = dispatch_ready[i];
    end

`ifdef PERF_ENABLE
    issue_perf_t issue_perf = '0;
`endif

    VX_issue #(
        .INSTANCE_ID (INSTANCE_ID)
    ) issue (
        `SCOPE_IO_BIND (0)
        .clk            (clk),
        .reset          (reset),

    `ifdef PERF_ENABLE
        .issue_perf     (issue_perf),
    `endif

        .decode_if      (decode_if),
        .writeback_if   (writeback_if),
        .dispatch_if    (dispatch_if)
    );

endmodule

VX_issue_top.sv 文件是一个名为 VX_issue_top 的模块的实现。这个模块的主要功能是管理指令的解码、写回和分派。以下是详细的分析和解释:

模块接口

输入和输出端口
  • 时钟和复位信号

    input wire clk,
    input wire reset,
    
  • 解码接口

    input wire decode_valid,
    input wire [`UUID_WIDTH-1:0] decode_uuid,
    input wire [`NW_WIDTH-1:0] decode_wid,
    input wire [`NUM_THREADS-1:0] decode_tmask,
    input wire [`PC_BITS-1:0] decode_PC,
    input wire [`EX_BITS-1:0] decode_ex_type,
    input wire [`INST_OP_BITS-1:0] decode_op_type,
    input op_args_t decode_op_args,
    input wire decode_wb,
    input wire [`NR_BITS-1:0] decode_rd,
    input wire [`NR_BITS-1:0] decode_rs1,
    input wire [`NR_BITS-1:0] decode_rs2,
    input wire [`NR_BITS-1:0] decode_rs3,
    output wire decode_ready,
    
  • 写回接口

    input wire writeback_valid[`ISSUE_WIDTH],
    input wire [`UUID_WIDTH-1:0] writeback_uuid[`ISSUE_WIDTH],
    input wire [ISSUE_WIS_W-1:0] writeback_wis[`ISSUE_WIDTH],
    input wire [`NUM_THREADS-1:0] writeback_tmask[`ISSUE_WIDTH],
    input wire [`PC_BITS-1:0] writeback_PC[`ISSUE_WIDTH],
    input wire [`NR_BITS-1:0] writeback_rd[`ISSUE_WIDTH],
    input wire [`NUM_THREADS-1:0][`XLEN-1:0] writeback_data[`ISSUE_WIDTH],
    input wire writeback_sop[`ISSUE_WIDTH],
    input wire writeback_eop[`ISSUE_WIDTH],
    
  • 分派接口

    output wire dispatch_valid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`UUID_WIDTH-1:0] dispatch_uuid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [ISSUE_WIS_W-1:0] dispatch_wis[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0] dispatch_tmask[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`PC_BITS-1:0] dispatch_PC[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`INST_ALU_BITS-1:0] dispatch_op_type[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output op_args_t dispatch_op_args[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire dispatch_wb[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NR_BITS-1:0] dispatch_rd[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NT_WIDTH-1:0] dispatch_tid[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs1_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs2_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    output wire [`NUM_THREADS-1:0][`XLEN-1:0] dispatch_rs3_data[`NUM_EX_UNITS * `ISSUE_WIDTH],
    input wire dispatch_ready[`NUM_EX_UNITS * `ISSUE_WIDTH],
    

内部信号和接口实例化

  • 接口实例化

    VX_decode_if decode_if();
    VX_dispatch_if dispatch_if[`NUM_EX_UNITS * `ISSUE_WIDTH]();
    VX_writeback_if writeback_if[`ISSUE_WIDTH]();
    
  • 解码接口赋值

    assign decode_if.valid = decode_valid;
    assign decode_if.data.uuid = decode_uuid;
    assign decode_if.data.wid = decode_wid;
    assign decode_if.data.tmask = decode_tmask;
    assign decode_if.data.PC = decode_PC;
    assign decode_if.data.ex_type = decode_ex_type;
    assign decode_if.data.op_type = decode_op_type;
    assign decode_if.data.op_args = decode_op_args;
    assign decode_if.data.wb = decode_wb;
    assign decode_if.data.rd = decode_rd;
    assign decode_if.data.rs1 = decode_rs1;
    assign decode_if.data.rs2 = decode_rs2;
    assign decode_if.data.rs3 = decode_rs3;
    assign decode_ready = decode_if.ready;
    
  • 写回接口赋值

    for (genvar i = 0; i < `ISSUE_WIDTH; ++i) begin
        assign writeback_if[i].valid = writeback_valid[i];
        assign writeback_if[i].data.uuid = writeback_uuid[i];
        assign writeback_if[i].data.wis = writeback_wis[i];
        assign writeback_if[i].data.tmask = writeback_tmask[i];
        assign writeback_if[i].data.PC = writeback_PC[i];
        assign writeback_if[i].data.rd = writeback_rd[i];
        assign writeback_if[i].data.data = writeback_data[i];
        assign writeback_if[i].data.sop = writeback_sop[i];
        assign writeback_if[i].data.eop = writeback_eop[i];
    end
    
  • 分派接口赋值

    for (genvar i = 0; i < `NUM_EX_UNITS * `ISSUE_WIDTH; ++i) begin
        assign dispatch_valid[i] = dispatch_if[i].valid;
        assign dispatch_uuid[i] = dispatch_if[i].data.uuid;
        assign dispatch_wis[i] = dispatch_if[i].data.wis;
        assign dispatch_tmask[i] = dispatch_if[i].data.tmask;
        assign dispatch_PC[i] = dispatch_if[i].data.PC;
        assign dispatch_op_type[i] = dispatch_if[i].data.op_type;
        assign dispatch_op_args[i] = dispatch_if[i].data.op_args;
        assign dispatch_wb[i] = dispatch_if[i].data.wb;
        assign dispatch_rd[i] = dispatch_if[i].data.rd;
        assign dispatch_tid[i] = dispatch_if[i].data.tid;
        assign dispatch_rs1_data[i] = dispatch_if[i].data.rs1_data;
        assign dispatch_rs2_data[i] = dispatch_if[i].data.rs2_data;
        assign dispatch_rs3_data[i] = dispatch_if[i].data.rs3_data;
        assign dispatch_if[i].ready = dispatch_ready[i];
    end
    

性能计数器(可选)

`ifdef PERF_ENABLE
    issue_perf_t issue_perf = '0;
`endif

子模块实例化

VX_issue #(
    .INSTANCE_ID (INSTANCE_ID)
) issue (
    `SCOPE_IO_BIND (0)
    .clk            (clk),
    .reset          (reset),

`ifdef PERF_ENABLE
    .issue_perf     (issue_perf),
`endif

    .decode_if      (decode_if),
    .writeback_if   (writeback_if),
    .dispatch_if    (dispatch_if)
);

总结

VX_issue_top 模块的主要功能是处理指令的解码、写回和分派。它通过实例化和配置各种接口模块,管理指令在不同阶段的流动。具体功能包括:

  • 从解码器接收指令并准备好发送到执行单元。
  • 管理指令的写回操作。
  • 将指令分派到适当的执行单元。
  • (可选)记录性能数据。

该模块可以作为VX_issue模块测试的top module。

VX_issue

VX_issue 模块的主要功能是处理指令的解码、写回和分派。

模块接口

输入和输出端口
  • 时钟和复位信号

    input wire clk,
    input wire reset,
    
  • 性能计数器输出(可选)

    `ifdef PERF_ENABLE
        output issue_perf_t issue_perf,
    `endif
    
  • 解码接口

    VX_decode_if.slave decode_if,
    
  • 写回接口

    VX_writeback_if.slave writeback_if [`ISSUE_WIDTH],
    
  • 分派接口

    VX_dispatch_if.master dispatch_if [`NUM_EX_UNITS * `ISSUE_WIDTH]
    

内部信号和性能计数器

  • 性能计数器(可选)
    `ifdef PERF_ENABLE
        issue_perf_t per_issue_perf [`ISSUE_WIDTH];
        `PERF_COUNTER_ADD (issue_perf, per_issue_perf, ibf_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
        `PERF_COUNTER_ADD (issue_perf, per_issue_perf, scb_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
        `PERF_COUNTER_ADD (issue_perf, per_issue_perf, opd_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
        for (genvar i = 0; i < `NUM_EX_UNITS; ++i) begin
            `PERF_COUNTER_ADD (issue_perf, per_issue_perf, units_uses[i], `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
        end
        for (genvar i = 0; i < `NUM_SFU_UNITS; ++i) begin
            `PERF_COUNTER_ADD (issue_perf, per_issue_perf, sfu_uses[i], `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
        end
    `endif
    

这段代码使用了一个条件编译宏 PERF_ENABLE 来启用性能计数器功能。具体分析如下:

条件编译宏 PERF_ENABLE
`ifdef PERF_ENABLE
  • 这行代码检查是否定义了 PERF_ENABLE 宏。如果定义了该宏,则启用性能计数器功能。
性能计数器数组 per_issue_perf
issue_perf_t per_issue_perf [`ISSUE_WIDTH];
  • 声明一个名为 per_issue_perf 的性能计数器数组,类型为 issue_perf_t,大小为 ISSUE_WIDTH
性能计数器增加宏 PERF_COUNTER_ADD
`PERF_COUNTER_ADD (issue_perf, per_issue_perf, ibf_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
`PERF_COUNTER_ADD (issue_perf, per_issue_perf, scb_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
`PERF_COUNTER_ADD (issue_perf, per_issue_perf, opd_stalls, `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
  • 使用 PERF_COUNTER_ADD 宏定义为 issue_perfper_issue_perf 数组中的每个元素增加性能计数器。
  • ibf_stallsscb_stallsopd_stalls 表示不同的性能计数器类型。
  • PERF_CTR_BITS 表示性能计数器的位宽。
  • ISSUE_WIDTH 表示性能计数器的数量。
  • 最后一个参数 (ISSUE_WIDTH > 2) 用于条件编译。
执行单元和特殊功能单元的性能计数器
for (genvar i = 0; i < `NUM_EX_UNITS; ++i) begin
    `PERF_COUNTER_ADD (issue_perf, per_issue_perf, units_uses[i], `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
end
for (genvar i = 0; i < `NUM_SFU_UNITS; ++i) begin
    `PERF_COUNTER_ADD (issue_perf, per_issue_perf, sfu_uses[i], `PERF_CTR_BITS, `ISSUE_WIDTH, (`ISSUE_WIDTH > 2))
end
  • 使用 PERF_COUNTER_ADD 宏定义为每个执行单元 (units_uses[i]) 和特殊功能单元 (sfu_uses[i]) 增加性能计数器。
  • for 循环遍历所有执行单元和特殊功能单元,分别增加性能计数器。
结束条件编译
`endif
  • 结束条件编译块。如果未定义 PERF_ENABLE 宏,则上述代码块不会被编译。

这段代码通过条件编译宏 PERF_ENABLE 来启用性能计数器功能,包括以下几点:

  1. 声明性能计数器数组 per_issue_perf
  2. 使用 PERF_COUNTER_ADD 宏定义为 issue_perfper_issue_perf 增加性能计数器,包括 ibf_stallsscb_stallsopd_stalls 等。
  3. 为每个执行单元和特殊功能单元分别增加性能计数器。

通过这些操作,可以在启用 PERF_ENABLE 宏定义时,统计和监控指令调度过程中的各种性能指标。

  • 解码和分派信号
    wire [ISSUE_ISW_W-1:0] decode_isw = wid_to_isw(decode_if.data.wid);
    wire [ISSUE_WIS_W-1:0] decode_wis = wid_to_wis(decode_if.data.wid);
    
    wire [`ISSUE_WIDTH-1:0] decode_ready_in;
    assign decode_if.ready = decode_ready_in[decode_isw];
    

这段代码 负责处理指令调度过程中的解码和准备信号。以下是详细分析:

信号定义和转换

  1. 定义信号 decode_iswdecode_wis

    wire [ISSUE_ISW_W-1:0] decode_isw = wid_to_isw(decode_if.data.wid);
    wire [ISSUE_WIS_W-1:0] decode_wis = wid_to_wis(decode_if.data.wid);
    
    • decode_iswdecode_wis 是两个信号,分别通过函数 wid_to_iswwid_to_wisdecode_if.data.wid 转换成不同的宽度。
    • wid_to_iswwid_to_wis 通常是用于 Warp ID 转换的函数,在不同的上下文中使用不同的宽度表示。
  2. 准备信号 decode_ready_in

    wire [`ISSUE_WIDTH-1:0] decode_ready_in;
    
  3. decode_if.ready 赋值

    assign decode_if.ready = decode_ready_in[decode_isw];
    
    • decode_ready_in 是一个宽度为 ISSUE_WIDTH 的信号,表示解码阶段的准备状态。
    • decode_if.ready 是解码接口的准备信号,通过索引 decode_iswdecode_ready_in 中获取相应的准备状态。

这段代码的主要功能是:

  1. 转换 Warp ID

    • 使用 wid_to_iswwid_to_wis 函数将 decode_if.data.wid 转换成不同的宽度信号 decode_iswdecode_wis
  2. 分配准备信号

    • 定义 decode_ready_in 信号,表示多个解码通道的准备状态。
    • 通过索引 decode_iswdecode_ready_in 中获取相应的准备状态,并将其赋值给 decode_if.ready,表示当前解码通道是否准备好。

通过这些操作,调度器能够正确地管理和分配解码通道的准备状态,确保多线程计算任务的正确执行。

调度Slice实例化

  • 切换接口

    `SCOPE_IO_SWITCH (`ISSUE_WIDTH)
    
  • 实例化和连接解码、写回和分派Slice

    for (genvar issue_id = 0; issue_id < `ISSUE_WIDTH; ++issue_id) begin : issue_slices
        VX_decode_if #(
            .NUM_WARPS (PER_ISSUE_WARPS)
        ) per_issue_decode_if();
    
        VX_dispatch_if per_issue_dispatch_if[`NUM_EX_UNITS]();
    
        assign per_issue_decode_if.valid = decode_if.valid && (decode_isw == ISSUE_ISW_W'(issue_id));
        assign per_issue_decode_if.data.uuid = decode_if.data.uuid;
        assign per_issue_decode_if.data.wid = decode_wis;
        assign per_issue_decode_if.data.tmask = decode_if.data.tmask;
        assign per_issue_decode_if.data.PC = decode_if.data.PC;
        assign per_issue_decode_if.data.ex_type = decode_if.data.ex_type;
        assign per_issue_decode_if.data.op_type = decode_if.data.op_type;
        assign per_issue_decode_if.data.op_args = decode_if.data.op_args;
        assign per_issue_decode_if.data.wb = decode_if.data.wb;
        assign per_issue_decode_if.data.rd = decode_if.data.rd;
        assign per_issue_decode_if.data.rs1 = decode_if.data.rs1;
        assign per_issue_decode_if.data.rs2 = decode_if.data.rs2;
        assign per_issue_decode_if.data.rs3 = decode_if.data.rs3;
        assign decode_ready_in[issue_id] = per_issue_decode_if.ready;
    `ifndef L1_ENABLE
        assign decode_if.ibuf_pop[issue_id * PER_ISSUE_WARPS +: PER_ISSUE_WARPS] = per_issue_decode_if.ibuf_pop;
    `endif
    
        `RESET_RELAY (slice_reset, reset);
    
        VX_issue_slice #(
            .INSTANCE_ID ($sformatf("%s%0d", INSTANCE_ID, issue_id)),
            .ISSUE_ID (issue_id)
        ) issue_slice (
            `SCOPE_IO_BIND(issue_id)
            .clk          (clk),
            .reset        (slice_reset),
        `ifdef PERF_ENABLE
            .issue_perf   (per_issue_perf[issue_id]),
        `endif
            .decode_if    (per_issue_decode_if),
            .writeback_if (writeback_if[issue_id]),
            .dispatch_if  (per_issue_dispatch_if)
        );
    
        // Assign transposed dispatch_if
        for (genvar ex_id = 0; ex_id < `NUM_EX_UNITS; ++ex_id) begin
            `ASSIGN_VX_IF(dispatch_if[ex_id * `ISSUE_WIDTH + issue_id], per_issue_dispatch_if[ex_id]);
        end
     end
    

这段代码负责处理指令的解码、写回和分派。具体功能包括实例化多个解码、写回和分派子模块,并将它们连接到主模块接口。以下是详细分析:

  1. for 循环实例化多个 issue_slice 子模块

    for (genvar issue_id = 0; issue_id < `ISSUE_WIDTH; ++issue_id) begin : issue_slices
    
  2. 实例化 VX_decode_ifVX_dispatch_if 接口

    VX_decode_if #(
        .NUM_WARPS (PER_ISSUE_WARPS)
    ) per_issue_decode_if();
    
    VX_dispatch_if per_issue_dispatch_if[`NUM_EX_UNITS]();
    
  3. 连接 decode_ifper_issue_decode_if 接口

    assign per_issue_decode_if.valid = decode_if.valid && (decode_isw == ISSUE_ISW_W'(issue_id));
    assign per_issue_decode_if.data.uuid = decode_if.data.uuid;
    assign per_issue_decode_if.data.wid = decode_wis;
    assign per_issue_decode_if.data.tmask = decode_if.data.tmask;
    assign per_issue_decode_if.data.PC = decode_if.data.PC;
    assign per_issue_decode_if.data.ex_type = decode_if.data.ex_type;
    assign per_issue_decode_if.data.op_type = decode_if.data.op_type;
    assign per_issue_decode_if.data.op_args = decode_if.data.op_args;
    assign per_issue_decode_if.data.wb = decode_if.data.wb;
    assign per_issue_decode_if.data.rd = decode_if.data.rd;
    assign per_issue_decode_if.data.rs1 = decode_if.data.rs1;
    assign per_issue_decode_if.data.rs2 = decode_if.data.rs2;
    assign per_issue_decode_if.data.rs3 = decode_if.data.rs3;
    assign decode_ready_in[issue_id] = per_issue_decode_if.ready;
    
  4. 条件编译块

    `ifndef L1_ENABLE
    assign decode_if.ibuf_pop[issue_id * PER_ISSUE_WARPS +: PER_ISSUE_WARPS] = per_issue_decode_if.ibuf_pop;
    `endif
    
  5. 实例化 VX_issue_slice 子模块

    `RESET_RELAY (slice_reset, reset);
    
    VX_issue_slice #(
        .INSTANCE_ID ($sformatf("%s%0d", INSTANCE_ID, issue_id)),
        .ISSUE_ID (issue_id)
    ) issue_slice (
        `SCOPE_IO_BIND(issue_id)
        .clk          (clk),
        .reset        (slice_reset),
    `ifdef PERF_ENABLE
        .issue_perf   (per_issue_perf[issue_id]),
    `endif
        .decode_if    (per_issue_decode_if),
        .writeback_if (writeback_if[issue_id]),
        .dispatch_if  (per_issue_dispatch_if)
    );
    
  6. 连接分派接口

    for (genvar ex_id = 0; ex_id < `NUM_EX_UNITS; ++ex_id) begin
        `ASSIGN_VX_IF(dispatch_if[ex_id * `ISSUE_WIDTH + issue_id], per_issue_dispatch_if[ex_id]);
    end
    

这段代码的主要功能是实例化和连接多个 issue_slice 子模块,每个子模块负责处理一部分指令的解码、写回和分派。具体步骤如下:

  1. 实例化解码和分派接口

    • VX_decode_ifVX_dispatch_if 接口实例化。
  2. 连接解码接口信号

    • 将主模块的 decode_if 信号连接到每个 per_issue_decode_if 接口。
    • 使用 decode_iswdecode_wis 信号进行索引和转换。
  3. 条件编译块

    • 如果未定义 L1_ENABLE,则连接 decode_if.ibuf_pop 信号到 per_issue_decode_if.ibuf_pop
  4. 实例化 VX_issue_slice 子模块

    • 使用 sformatf 函数生成实例ID和索引。
    • clkresetdecode_ifwriteback_ifdispatch_if 信号连接到 issue_slice 子模块。
  5. 连接分派接口信号

    • 使用嵌套的 for 循环将 dispatch_if 信号连接到 per_issue_dispatch_if 接口,实现信号的转置连接。

通过这些操作,VX_issue 模块能够有效地管理和分配解码、写回和分派任务,确保多线程计算任务的正确执行。

总结

VX_issue 模块的主要功能是处理指令的解码、写回和分派。它通过实例化和配置各种接口模块,管理指令在不同阶段的流动。具体功能包括:

  • 将来自解码器的指令分配给各个 issue_slice
  • 管理指令的写回操作。
  • 将指令分派到适当的执行单元。
  • (可选)记录性能数据。

通过这些操作,VX_issue 模块确保指令能够正确地流经处理流水线,从而实现高效的并行计算。

你可能感兴趣的:(skybox,_core,skybox,issue,skybox,core)