187 lines
5.3 KiB
Verilog
187 lines
5.3 KiB
Verilog
`include "VX_define.vh"
|
|
|
|
module VX_fpu_unit #(
|
|
parameter CORE_ID = 0
|
|
) (
|
|
// inputs
|
|
input wire clk,
|
|
input wire reset,
|
|
|
|
// inputs
|
|
VX_fpu_req_if fpu_req_if,
|
|
|
|
// outputs
|
|
VX_fpu_to_csr_if fpu_to_csr_if,
|
|
VX_commit_if fpu_commit_if,
|
|
|
|
input wire[`NUM_WARPS-1:0] csr_pending,
|
|
output wire[`NUM_WARPS-1:0] pending
|
|
);
|
|
localparam FPUQ_BITS = `LOG2UP(`FPUQ_SIZE);
|
|
|
|
wire ready_in;
|
|
wire valid_out;
|
|
wire ready_out;
|
|
|
|
wire [`NW_BITS-1:0] rsp_wid;
|
|
wire [`NUM_THREADS-1:0] rsp_tmask;
|
|
wire [31:0] rsp_PC;
|
|
wire [`NR_BITS-1:0] rsp_rd;
|
|
wire rsp_wb;
|
|
|
|
wire has_fflags;
|
|
fflags_t [`NUM_THREADS-1:0] fflags;
|
|
wire [`NUM_THREADS-1:0][31:0] result;
|
|
|
|
wire [FPUQ_BITS-1:0] tag_in, tag_out;
|
|
wire fpuq_full;
|
|
|
|
wire fpuq_push = fpu_req_if.valid && fpu_req_if.ready;
|
|
wire fpuq_pop = valid_out && ready_out;
|
|
|
|
VX_index_buffer #(
|
|
.DATAW (`NW_BITS + `NUM_THREADS + 32 + `NR_BITS + 1),
|
|
.SIZE (`FPUQ_SIZE),
|
|
.FASTRAM (1)
|
|
) req_metadata (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.acquire_slot (fpuq_push),
|
|
.write_addr (tag_in),
|
|
.read_addr (tag_out),
|
|
.release_addr (tag_out),
|
|
.write_data ({fpu_req_if.wid, fpu_req_if.tmask, fpu_req_if.PC, fpu_req_if.rd, fpu_req_if.wb}),
|
|
.read_data ({rsp_wid, rsp_tmask, rsp_PC, rsp_rd, rsp_wb}),
|
|
.release_slot (fpuq_pop),
|
|
.full (fpuq_full)
|
|
);
|
|
|
|
// can accept new request?
|
|
assign fpu_req_if.ready = ready_in && ~fpuq_full && !csr_pending[fpu_req_if.wid];
|
|
|
|
wire valid_in = fpu_req_if.valid && ~fpuq_full && !csr_pending[fpu_req_if.wid];
|
|
|
|
// resolve dynamic FRM from CSR
|
|
assign fpu_to_csr_if.read_wid = fpu_req_if.wid;
|
|
wire [`FRM_BITS-1:0] fpu_frm = (fpu_req_if.op_mod == `FRM_DYN) ? fpu_to_csr_if.read_frm : fpu_req_if.op_mod;
|
|
|
|
`ifdef FPU_FAST
|
|
|
|
VX_fp_fpga #(
|
|
.TAGW (FPUQ_BITS)
|
|
) fp_core (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
|
|
.valid_in (valid_in),
|
|
.ready_in (ready_in),
|
|
|
|
.tag_in (tag_in),
|
|
|
|
.op_type (fpu_req_if.op_type),
|
|
.frm (fpu_frm),
|
|
|
|
.dataa (fpu_req_if.rs1_data),
|
|
.datab (fpu_req_if.rs2_data),
|
|
.datac (fpu_req_if.rs3_data),
|
|
.result (result),
|
|
|
|
.has_fflags (has_fflags),
|
|
.fflags (fflags),
|
|
|
|
.tag_out (tag_out),
|
|
|
|
.ready_out (ready_out),
|
|
.valid_out (valid_out)
|
|
);
|
|
|
|
`else
|
|
|
|
VX_fpnew #(
|
|
.FMULADD (1),
|
|
.FDIVSQRT (1),
|
|
.FNONCOMP (1),
|
|
.FCONV (1),
|
|
.TAGW (FPUQ_BITS)
|
|
) fp_core (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
|
|
.valid_in (valid_in),
|
|
.ready_in (ready_in),
|
|
|
|
.tag_in (tag_in),
|
|
|
|
.op_type (fpu_req_if.op_type),
|
|
.frm (fpu_frm),
|
|
|
|
.dataa (fpu_req_if.rs1_data),
|
|
.datab (fpu_req_if.rs2_data),
|
|
.datac (fpu_req_if.rs3_data),
|
|
.result (result),
|
|
|
|
.has_fflags (has_fflags),
|
|
.fflags (fflags),
|
|
|
|
.tag_out (tag_out),
|
|
|
|
.ready_out (ready_out),
|
|
.valid_out (valid_out)
|
|
);
|
|
|
|
`endif
|
|
|
|
reg has_fflags_r;
|
|
fflags_t fflags_r;
|
|
|
|
fflags_t rsp_fflags;
|
|
always @(*) begin
|
|
rsp_fflags = 0;
|
|
for (integer i = 0; i < `NUM_THREADS; i++) begin
|
|
if (rsp_tmask[i]) begin
|
|
rsp_fflags.NX |= fflags[i].NX;
|
|
rsp_fflags.UF |= fflags[i].UF;
|
|
rsp_fflags.OF |= fflags[i].OF;
|
|
rsp_fflags.DZ |= fflags[i].DZ;
|
|
rsp_fflags.NV |= fflags[i].NV;
|
|
end
|
|
end
|
|
end
|
|
|
|
wire stall_out = ~fpu_commit_if.ready && fpu_commit_if.valid;
|
|
|
|
VX_pipe_register #(
|
|
.DATAW (1 + `NW_BITS + `NUM_THREADS + 32 + `NR_BITS + 1 + (`NUM_THREADS * 32) + 1 + `FFG_BITS),
|
|
.RESETW (1)
|
|
) pipe_reg (
|
|
.clk (clk),
|
|
.reset (reset),
|
|
.enable (!stall_out),
|
|
.data_in ({valid_out, rsp_wid, rsp_tmask, rsp_PC, rsp_rd, rsp_wb, result, has_fflags, rsp_fflags}),
|
|
.data_out ({fpu_commit_if.valid, fpu_commit_if.wid, fpu_commit_if.tmask, fpu_commit_if.PC, fpu_commit_if.rd, fpu_commit_if.wb, fpu_commit_if.data, has_fflags_r, fflags_r})
|
|
);
|
|
|
|
assign ready_out = ~stall_out;
|
|
|
|
// CSR fflags Update
|
|
assign fpu_to_csr_if.write_enable = fpu_commit_if.valid && fpu_commit_if.ready && has_fflags_r;
|
|
assign fpu_to_csr_if.write_wid = fpu_commit_if.wid;
|
|
assign fpu_to_csr_if.write_fflags = fflags_r;
|
|
|
|
// pending request
|
|
reg [`NUM_WARPS-1:0] pending_r;
|
|
always @(posedge clk) begin
|
|
if (reset) begin
|
|
pending_r <= 0;
|
|
end else begin
|
|
if (fpu_commit_if.valid && fpu_commit_if.ready) begin
|
|
pending_r[fpu_commit_if.wid] <= 0;
|
|
end
|
|
if (fpu_req_if.valid && fpu_req_if.ready) begin
|
|
pending_r[fpu_req_if.wid] <= 1;
|
|
end
|
|
end
|
|
end
|
|
assign pending = pending_r;
|
|
|
|
endmodule |