345 lines
10 KiB
Systemverilog
345 lines
10 KiB
Systemverilog
// 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"
|
|
|
|
`ifdef EXT_F_ENABLE
|
|
`include "VX_fpu_define.vh"
|
|
`endif
|
|
|
|
module VX_core import VX_gpu_pkg::*; #(
|
|
parameter CORE_ID = 0
|
|
) (
|
|
`SCOPE_IO_DECL
|
|
|
|
// Clock
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
`ifdef PERF_ENABLE
|
|
VX_mem_perf_if.slave mem_perf_if,
|
|
`endif
|
|
|
|
VX_dcr_bus_if.slave dcr_bus_if,
|
|
|
|
VX_mem_bus_if.master dcache_bus_if [DCACHE_NUM_REQS],
|
|
|
|
VX_mem_bus_if.master icache_bus_if,
|
|
|
|
`ifdef GBAR_ENABLE
|
|
VX_gbar_bus_if.master gbar_bus_if,
|
|
`endif
|
|
|
|
// simulation helper signals
|
|
output wire sim_ebreak,
|
|
output wire [`NUM_REGS-1:0][`XLEN-1:0] sim_wb_value,
|
|
|
|
// Status
|
|
output wire busy
|
|
);
|
|
VX_schedule_if schedule_if();
|
|
VX_fetch_if fetch_if();
|
|
VX_decode_if decode_if();
|
|
VX_sched_csr_if sched_csr_if();
|
|
VX_decode_sched_if decode_sched_if();
|
|
VX_commit_sched_if commit_sched_if();
|
|
VX_commit_csr_if commit_csr_if();
|
|
VX_branch_ctl_if branch_ctl_if[`NUM_ALU_BLOCKS]();
|
|
VX_warp_ctl_if warp_ctl_if();
|
|
|
|
VX_dispatch_if alu_dispatch_if[`ISSUE_WIDTH]();
|
|
VX_commit_if alu_commit_if[`ISSUE_WIDTH]();
|
|
|
|
VX_dispatch_if lsu_dispatch_if[`ISSUE_WIDTH]();
|
|
VX_commit_if lsu_commit_if[`ISSUE_WIDTH]();
|
|
`ifdef EXT_F_ENABLE
|
|
VX_dispatch_if fpu_dispatch_if[`ISSUE_WIDTH]();
|
|
VX_commit_if fpu_commit_if[`ISSUE_WIDTH]();
|
|
`endif
|
|
VX_dispatch_if sfu_dispatch_if[`ISSUE_WIDTH]();
|
|
VX_commit_if sfu_commit_if[`ISSUE_WIDTH]();
|
|
|
|
VX_writeback_if writeback_if[`ISSUE_WIDTH]();
|
|
|
|
VX_mem_bus_if #(
|
|
.DATA_SIZE (DCACHE_WORD_SIZE),
|
|
.TAG_WIDTH (DCACHE_TAG_WIDTH)
|
|
) dcache_bus_tmp_if[DCACHE_NUM_REQS]();
|
|
|
|
`ifdef PERF_ENABLE
|
|
VX_pipeline_perf_if pipeline_perf_if();
|
|
VX_mem_perf_if mem_perf_tmp_if();
|
|
|
|
assign mem_perf_tmp_if.icache = mem_perf_if.icache;
|
|
assign mem_perf_tmp_if.dcache = mem_perf_if.dcache;
|
|
assign mem_perf_tmp_if.l2cache = mem_perf_if.l2cache;
|
|
assign mem_perf_tmp_if.l3cache = mem_perf_if.l3cache;
|
|
`ifdef SM_ENABLE
|
|
cache_perf_t smem_perf;
|
|
assign mem_perf_tmp_if.smem = smem_perf;
|
|
`else
|
|
assign mem_perf_tmp_if.smem = '0;
|
|
`endif
|
|
assign mem_perf_tmp_if.mem = mem_perf_if.mem;
|
|
`endif
|
|
|
|
`RESET_RELAY (dcr_data_reset, reset);
|
|
`RESET_RELAY (schedule_reset, reset);
|
|
`RESET_RELAY (fetch_reset, reset);
|
|
`RESET_RELAY (decode_reset, reset);
|
|
`RESET_RELAY (issue_reset, reset);
|
|
`RESET_RELAY (execute_reset, reset);
|
|
`RESET_RELAY (commit_reset, reset);
|
|
|
|
base_dcrs_t base_dcrs;
|
|
|
|
VX_dcr_data dcr_data (
|
|
.clk (clk),
|
|
.reset (dcr_data_reset),
|
|
.dcr_bus_if (dcr_bus_if),
|
|
.base_dcrs (base_dcrs)
|
|
);
|
|
|
|
`SCOPE_IO_SWITCH (3)
|
|
|
|
VX_schedule #(
|
|
.CORE_ID (CORE_ID)
|
|
) schedule (
|
|
.clk (clk),
|
|
.reset (schedule_reset),
|
|
|
|
`ifdef PERF_ENABLE
|
|
.perf_schedule_if (pipeline_perf_if.schedule),
|
|
`endif
|
|
|
|
.base_dcrs (base_dcrs),
|
|
|
|
.warp_ctl_if (warp_ctl_if),
|
|
.branch_ctl_if (branch_ctl_if),
|
|
.decode_sched_if(decode_sched_if),
|
|
.commit_sched_if(commit_sched_if),
|
|
|
|
.schedule_if (schedule_if),
|
|
`ifdef GBAR_ENABLE
|
|
.gbar_bus_if (gbar_bus_if),
|
|
`endif
|
|
.sched_csr_if (sched_csr_if),
|
|
|
|
.busy (busy)
|
|
);
|
|
|
|
VX_fetch #(
|
|
.CORE_ID (CORE_ID)
|
|
) fetch (
|
|
`SCOPE_IO_BIND (0)
|
|
.clk (clk),
|
|
.reset (fetch_reset),
|
|
.icache_bus_if (icache_bus_if),
|
|
.schedule_if (schedule_if),
|
|
.fetch_if (fetch_if)
|
|
);
|
|
|
|
VX_decode #(
|
|
.CORE_ID (CORE_ID)
|
|
) decode (
|
|
.clk (clk),
|
|
.reset (decode_reset),
|
|
.fetch_if (fetch_if),
|
|
.decode_if (decode_if),
|
|
.decode_sched_if(decode_sched_if)
|
|
);
|
|
|
|
VX_issue #(
|
|
.CORE_ID (CORE_ID)
|
|
) issue (
|
|
`SCOPE_IO_BIND (1)
|
|
|
|
.clk (clk),
|
|
.reset (issue_reset),
|
|
|
|
`ifdef PERF_ENABLE
|
|
.perf_issue_if (pipeline_perf_if.issue),
|
|
`endif
|
|
|
|
.decode_if (decode_if),
|
|
.writeback_if (writeback_if),
|
|
|
|
.alu_dispatch_if(alu_dispatch_if),
|
|
.lsu_dispatch_if(lsu_dispatch_if),
|
|
`ifdef EXT_F_ENABLE
|
|
.fpu_dispatch_if(fpu_dispatch_if),
|
|
`endif
|
|
.sfu_dispatch_if(sfu_dispatch_if)
|
|
);
|
|
|
|
VX_execute #(
|
|
.CORE_ID (CORE_ID)
|
|
) execute (
|
|
`SCOPE_IO_BIND (2)
|
|
|
|
.clk (clk),
|
|
.reset (execute_reset),
|
|
|
|
.base_dcrs (base_dcrs),
|
|
|
|
`ifdef PERF_ENABLE
|
|
.mem_perf_if (mem_perf_tmp_if),
|
|
.pipeline_perf_if(pipeline_perf_if),
|
|
`endif
|
|
|
|
.dcache_bus_if (dcache_bus_tmp_if),
|
|
|
|
`ifdef EXT_F_ENABLE
|
|
.fpu_dispatch_if(fpu_dispatch_if),
|
|
.fpu_commit_if (fpu_commit_if),
|
|
`endif
|
|
|
|
.commit_csr_if (commit_csr_if),
|
|
.sched_csr_if (sched_csr_if),
|
|
|
|
.alu_dispatch_if(alu_dispatch_if),
|
|
.lsu_dispatch_if(lsu_dispatch_if),
|
|
.sfu_dispatch_if(sfu_dispatch_if),
|
|
|
|
.warp_ctl_if (warp_ctl_if),
|
|
.branch_ctl_if (branch_ctl_if),
|
|
|
|
.alu_commit_if (alu_commit_if),
|
|
.lsu_commit_if (lsu_commit_if),
|
|
.sfu_commit_if (sfu_commit_if),
|
|
|
|
.sim_ebreak (sim_ebreak)
|
|
);
|
|
|
|
VX_commit #(
|
|
.CORE_ID (CORE_ID)
|
|
) commit (
|
|
.clk (clk),
|
|
.reset (commit_reset),
|
|
|
|
.alu_commit_if (alu_commit_if),
|
|
.lsu_commit_if (lsu_commit_if),
|
|
`ifdef EXT_F_ENABLE
|
|
.fpu_commit_if (fpu_commit_if),
|
|
`endif
|
|
.sfu_commit_if (sfu_commit_if),
|
|
|
|
.writeback_if (writeback_if),
|
|
|
|
.commit_csr_if (commit_csr_if),
|
|
.commit_sched_if(commit_sched_if),
|
|
|
|
.sim_wb_value (sim_wb_value)
|
|
);
|
|
|
|
`ifdef SM_ENABLE
|
|
|
|
VX_smem_unit #(
|
|
.CORE_ID (CORE_ID)
|
|
) smem_unit (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
`ifdef PERF_ENABLE
|
|
.cache_perf (smem_perf),
|
|
`endif
|
|
.dcache_bus_in_if (dcache_bus_tmp_if),
|
|
.dcache_bus_out_if (dcache_bus_if)
|
|
);
|
|
|
|
`else
|
|
|
|
for (genvar i = 0; i < DCACHE_NUM_REQS; ++i) begin
|
|
`ASSIGN_VX_MEM_BUS_IF (dcache_bus_if[i], dcache_bus_tmp_if[i]);
|
|
end
|
|
|
|
`endif
|
|
|
|
`ifdef PERF_ENABLE
|
|
|
|
wire [`CLOG2(DCACHE_NUM_REQS+1)-1:0] perf_dcache_rd_req_per_cycle;
|
|
wire [`CLOG2(DCACHE_NUM_REQS+1)-1:0] perf_dcache_wr_req_per_cycle;
|
|
wire [`CLOG2(DCACHE_NUM_REQS+1)-1:0] perf_dcache_rsp_per_cycle;
|
|
|
|
wire [1:0] perf_icache_pending_read_cycle;
|
|
wire [`CLOG2(DCACHE_NUM_REQS+1)+1-1:0] perf_dcache_pending_read_cycle;
|
|
|
|
reg [`PERF_CTR_BITS-1:0] perf_icache_pending_reads;
|
|
reg [`PERF_CTR_BITS-1:0] perf_dcache_pending_reads;
|
|
|
|
reg [`PERF_CTR_BITS-1:0] perf_ifetches;
|
|
reg [`PERF_CTR_BITS-1:0] perf_loads;
|
|
reg [`PERF_CTR_BITS-1:0] perf_stores;
|
|
|
|
wire perf_icache_req_fire = icache_bus_if.req_valid & icache_bus_if.req_ready;
|
|
wire perf_icache_rsp_fire = icache_bus_if.rsp_valid & icache_bus_if.rsp_ready;
|
|
|
|
wire [DCACHE_NUM_REQS-1:0] perf_dcache_rd_req_fire, perf_dcache_rd_req_fire_r;
|
|
wire [DCACHE_NUM_REQS-1:0] perf_dcache_wr_req_fire, perf_dcache_wr_req_fire_r;
|
|
wire [DCACHE_NUM_REQS-1:0] perf_dcache_rsp_fire;
|
|
|
|
for (genvar i = 0; i < DCACHE_NUM_REQS; ++i) begin
|
|
assign perf_dcache_rd_req_fire[i] = dcache_bus_if[i].req_valid && ~dcache_bus_if[i].req_data.rw && dcache_bus_if[i].req_ready;
|
|
assign perf_dcache_wr_req_fire[i] = dcache_bus_if[i].req_valid && dcache_bus_if[i].req_data.rw && dcache_bus_if[i].req_ready;
|
|
assign perf_dcache_rsp_fire[i] = dcache_bus_if[i].rsp_valid && dcache_bus_if[i].rsp_ready;
|
|
end
|
|
|
|
`BUFFER(perf_dcache_rd_req_fire_r, perf_dcache_rd_req_fire);
|
|
`BUFFER(perf_dcache_wr_req_fire_r, perf_dcache_wr_req_fire);
|
|
|
|
`POP_COUNT(perf_dcache_rd_req_per_cycle, perf_dcache_rd_req_fire_r);
|
|
`POP_COUNT(perf_dcache_wr_req_per_cycle, perf_dcache_wr_req_fire_r);
|
|
`POP_COUNT(perf_dcache_rsp_per_cycle, perf_dcache_rsp_fire);
|
|
|
|
assign perf_icache_pending_read_cycle = perf_icache_req_fire - perf_icache_rsp_fire;
|
|
assign perf_dcache_pending_read_cycle = perf_dcache_rd_req_per_cycle - perf_dcache_rsp_per_cycle;
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
perf_icache_pending_reads <= '0;
|
|
perf_dcache_pending_reads <= '0;
|
|
end else begin
|
|
perf_icache_pending_reads <= $signed(perf_icache_pending_reads) + `PERF_CTR_BITS'($signed(perf_icache_pending_read_cycle));
|
|
perf_dcache_pending_reads <= $signed(perf_dcache_pending_reads) + `PERF_CTR_BITS'($signed(perf_dcache_pending_read_cycle));
|
|
end
|
|
end
|
|
|
|
reg [`PERF_CTR_BITS-1:0] perf_icache_lat;
|
|
reg [`PERF_CTR_BITS-1:0] perf_dcache_lat;
|
|
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
perf_ifetches <= '0;
|
|
perf_loads <= '0;
|
|
perf_stores <= '0;
|
|
perf_icache_lat <= '0;
|
|
perf_dcache_lat <= '0;
|
|
end else begin
|
|
perf_ifetches <= perf_ifetches + `PERF_CTR_BITS'(perf_icache_req_fire);
|
|
perf_loads <= perf_loads + `PERF_CTR_BITS'(perf_dcache_rd_req_per_cycle);
|
|
perf_stores <= perf_stores + `PERF_CTR_BITS'(perf_dcache_wr_req_per_cycle);
|
|
perf_icache_lat <= perf_icache_lat + perf_icache_pending_reads;
|
|
perf_dcache_lat <= perf_dcache_lat + perf_dcache_pending_reads;
|
|
end
|
|
end
|
|
|
|
assign pipeline_perf_if.ifetches = perf_ifetches;
|
|
assign pipeline_perf_if.loads = perf_loads;
|
|
assign pipeline_perf_if.stores = perf_stores;
|
|
assign pipeline_perf_if.load_latency = perf_dcache_lat;
|
|
assign pipeline_perf_if.ifetch_latency = perf_icache_lat;
|
|
assign pipeline_perf_if.load_latency = perf_dcache_lat;
|
|
|
|
`endif
|
|
|
|
endmodule
|