151 lines
5.1 KiB
Verilog
151 lines
5.1 KiB
Verilog
`include "VX_define.vh"
|
|
|
|
module VX_csr_unit #(
|
|
parameter CORE_ID = 0
|
|
) (
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
// PERF: total reads
|
|
`ifdef PERF_ENABLE
|
|
VX_perf_cache_if perf_cache_if,
|
|
VX_perf_pipeline_stall_if perf_pipeline_stall_if,
|
|
`endif
|
|
|
|
VX_cmt_to_csr_if cmt_to_csr_if,
|
|
VX_fpu_to_csr_if fpu_to_csr_if,
|
|
|
|
VX_csr_io_req_if csr_io_req_if,
|
|
VX_csr_io_rsp_if csr_io_rsp_if,
|
|
|
|
VX_csr_req_if csr_req_if,
|
|
VX_commit_if csr_commit_if,
|
|
|
|
input wire busy,
|
|
input wire[`NUM_WARPS-1:0] fpu_pending,
|
|
output wire[`NUM_WARPS-1:0] pending
|
|
);
|
|
VX_csr_pipe_req_if csr_pipe_req_if();
|
|
VX_commit_if csr_pipe_rsp_if();
|
|
|
|
wire select_io_rsp;
|
|
|
|
VX_csr_arb csr_arb (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
|
|
.select_io_rsp (select_io_rsp),
|
|
|
|
.csr_core_req_if (csr_req_if),
|
|
.csr_io_req_if (csr_io_req_if),
|
|
.csr_pipe_req_if (csr_pipe_req_if),
|
|
|
|
.csr_pipe_rsp_if (csr_pipe_rsp_if),
|
|
.csr_io_rsp_if (csr_io_rsp_if),
|
|
.csr_commit_if (csr_commit_if)
|
|
);
|
|
|
|
wire csr_we_s1;
|
|
wire [`CSR_ADDR_BITS-1:0] csr_addr_s1;
|
|
wire [31:0] csr_read_data, csr_read_data_s1;
|
|
wire [31:0] csr_updated_data_s1;
|
|
|
|
wire write_enable = csr_pipe_rsp_if.valid && csr_we_s1;
|
|
|
|
VX_csr_data #(
|
|
.CORE_ID(CORE_ID)
|
|
) csr_data (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
// PERF: total reads
|
|
`ifdef PERF_ENABLE
|
|
.perf_cache_if (perf_cache_if),
|
|
.perf_pipeline_stall_if (perf_pipeline_stall_if),
|
|
`endif
|
|
.cmt_to_csr_if (cmt_to_csr_if),
|
|
.fpu_to_csr_if (fpu_to_csr_if),
|
|
.read_enable (csr_pipe_req_if.valid),
|
|
.read_addr (csr_pipe_req_if.csr_addr),
|
|
.read_wid (csr_pipe_req_if.wid),
|
|
.read_data (csr_read_data),
|
|
.write_enable (write_enable),
|
|
.write_addr (csr_addr_s1),
|
|
.write_wid (csr_pipe_rsp_if.wid),
|
|
.write_data (csr_updated_data_s1[`CSR_WIDTH-1:0]),
|
|
.busy (busy)
|
|
);
|
|
|
|
wire write_hazard = (csr_addr_s1 == csr_pipe_req_if.csr_addr)
|
|
&& (csr_pipe_rsp_if.wid == csr_pipe_req_if.wid)
|
|
&& csr_pipe_rsp_if.valid;
|
|
|
|
wire [31:0] csr_read_data_qual = write_hazard ? csr_updated_data_s1 : csr_read_data;
|
|
|
|
reg [31:0] csr_updated_data;
|
|
|
|
reg csr_we_s0_unqual;
|
|
|
|
always @(*) begin
|
|
csr_we_s0_unqual = 0;
|
|
case (csr_pipe_req_if.op_type)
|
|
`CSR_RW: begin
|
|
csr_updated_data = csr_pipe_req_if.csr_mask;
|
|
csr_we_s0_unqual = 1;
|
|
end
|
|
`CSR_RS: begin
|
|
csr_updated_data = csr_read_data_qual | csr_pipe_req_if.csr_mask;
|
|
csr_we_s0_unqual = (csr_pipe_req_if.csr_mask != 0);
|
|
end
|
|
`CSR_RC: begin
|
|
csr_updated_data = csr_read_data_qual & (32'hFFFFFFFF - csr_pipe_req_if.csr_mask);
|
|
csr_we_s0_unqual = (csr_pipe_req_if.csr_mask != 0);
|
|
end
|
|
default: csr_updated_data = 'x;
|
|
endcase
|
|
end
|
|
|
|
wire stall_in = fpu_pending[csr_pipe_req_if.wid];
|
|
|
|
wire pipe_req_valid_qual = csr_pipe_req_if.valid && !stall_in;
|
|
|
|
wire stall_out = ~csr_pipe_rsp_if.ready && csr_pipe_rsp_if.valid;
|
|
|
|
VX_generic_register #(
|
|
.N(1 + `NW_BITS + `NUM_THREADS + 32 + `NR_BITS + 1 + 1 + `CSR_ADDR_BITS + 1 + 32 + 32),
|
|
.R(1)
|
|
) pipe_reg (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.stall (stall_out),
|
|
.flush (1'b0),
|
|
.data_in ({pipe_req_valid_qual, csr_pipe_req_if.wid, csr_pipe_req_if.tmask, csr_pipe_req_if.PC, csr_pipe_req_if.rd, csr_pipe_req_if.wb, csr_we_s0_unqual, csr_pipe_req_if.csr_addr, csr_pipe_req_if.is_io, csr_read_data_qual, csr_updated_data}),
|
|
.data_out ({csr_pipe_rsp_if.valid, csr_pipe_rsp_if.wid, csr_pipe_rsp_if.tmask, csr_pipe_rsp_if.PC, csr_pipe_rsp_if.rd, csr_pipe_rsp_if.wb, csr_we_s1, csr_addr_s1, select_io_rsp, csr_read_data_s1, csr_updated_data_s1})
|
|
);
|
|
|
|
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
|
assign csr_pipe_rsp_if.data[i] = (csr_addr_s1 == `CSR_LTID) ? i :
|
|
(csr_addr_s1 == `CSR_GTID) ? (csr_read_data_s1 * `NUM_THREADS + i) :
|
|
csr_read_data_s1;
|
|
end
|
|
|
|
// can accept new request?
|
|
assign csr_pipe_req_if.ready = ~(stall_out || stall_in);
|
|
|
|
// pending request
|
|
reg [`NUM_WARPS-1:0] pending_r;
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
pending_r <= 0;
|
|
end else begin
|
|
if (csr_pipe_rsp_if.valid && csr_pipe_rsp_if.ready) begin
|
|
pending_r[csr_pipe_rsp_if.wid] <= 0;
|
|
end
|
|
if (csr_pipe_req_if.valid && csr_pipe_req_if.ready) begin
|
|
pending_r[csr_pipe_req_if.wid] <= 1;
|
|
end
|
|
end
|
|
end
|
|
assign pending = pending_r;
|
|
|
|
endmodule
|