2021-05-24 13:28:16 +00:00
|
|
|
///////////////////////////////////////////
|
|
|
|
//
|
2021-10-06 13:26:09 +00:00
|
|
|
// Written: Katherine Parry, James Stine, Brett Mathis
|
2021-06-23 20:42:40 +00:00
|
|
|
// Modified: 6/23/2021
|
2021-05-24 13:28:16 +00:00
|
|
|
//
|
|
|
|
// Purpose: FPU
|
|
|
|
//
|
|
|
|
// A component of the Wally configurable RISC-V project.
|
|
|
|
//
|
|
|
|
// Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
|
|
|
|
//
|
2022-01-07 12:58:40 +00:00
|
|
|
// MIT LICENSE
|
|
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
|
|
|
|
// software and associated documentation files (the "Software"), to deal in the Software
|
|
|
|
// without restriction, including without limitation the rights to use, copy, modify, merge,
|
|
|
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
|
|
|
|
// to whom the Software is furnished to do so, subject to the following conditions:
|
2021-05-24 13:28:16 +00:00
|
|
|
//
|
2022-01-07 12:58:40 +00:00
|
|
|
// The above copyright notice and this permission notice shall be included in all copies or
|
|
|
|
// substantial portions of the Software.
|
2021-05-24 13:28:16 +00:00
|
|
|
//
|
2022-01-07 12:58:40 +00:00
|
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
|
|
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
|
|
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
|
|
|
// BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
|
|
|
|
// OR OTHER DEALINGS IN THE SOFTWARE.
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
2021-04-08 18:03:21 +00:00
|
|
|
|
|
|
|
`include "wally-config.vh"
|
2021-04-04 18:09:13 +00:00
|
|
|
|
|
|
|
module fpu (
|
2021-10-06 13:26:09 +00:00
|
|
|
input logic clk,
|
|
|
|
input logic reset,
|
|
|
|
input logic [2:0] FRM_REGW, // Rounding mode from CSR
|
|
|
|
input logic [31:0] InstrD, // instruction from IFU
|
|
|
|
input logic [`XLEN-1:0] ReadDataW,// Read data from memory
|
2021-12-08 20:33:53 +00:00
|
|
|
input logic [`XLEN-1:0] ForwardedSrcAE, // Integer input being processed (from IEU)
|
2021-10-06 13:26:09 +00:00
|
|
|
input logic StallE, StallM, StallW, // stall signals from HZU
|
|
|
|
input logic FlushE, FlushM, FlushW, // flush signals from HZU
|
2021-10-23 18:13:28 +00:00
|
|
|
input logic [4:0] RdM, RdW, // which FP register to write to (from IEU)
|
2022-05-03 11:56:31 +00:00
|
|
|
input logic [1:0] STATUS_FS, // Is floating-point enabled?
|
2021-10-06 13:26:09 +00:00
|
|
|
output logic FRegWriteM, // FP register write enable
|
|
|
|
output logic FStallD, // Stall the decode stage
|
2021-12-18 13:36:32 +00:00
|
|
|
output logic FWriteIntE, // integer register write enables
|
2021-10-06 13:26:09 +00:00
|
|
|
output logic [`XLEN-1:0] FWriteDataE, // Data to be written to memory
|
|
|
|
output logic [`XLEN-1:0] FIntResM, // data to be written to integer register
|
|
|
|
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage)
|
|
|
|
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
2021-10-27 18:02:42 +00:00
|
|
|
output logic [4:0] SetFflagsM // FPU flags (to privileged unit)
|
2021-07-24 18:59:57 +00:00
|
|
|
);
|
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
//*** make everything FLEN at some point
|
|
|
|
//*** add the 128 bit support to the if statement when needed
|
|
|
|
//*** make new tests for fp using testfloat that include flag checking and all rounding modes
|
|
|
|
//*** what is the format for 16-bit - finding conflicting info online can't find anything specified in spec
|
|
|
|
//*** only fma/mul and fp <-> int convert flags have been tested. test the others.
|
|
|
|
|
|
|
|
// FPU specifics:
|
|
|
|
// - uses NaN-blocking format
|
|
|
|
// - if there are any unsused bits the most significant bits are filled with 1s
|
|
|
|
// single stored in a double: | 32 1s | single precision value |
|
|
|
|
// - sets the underflow after rounding
|
2021-07-24 18:59:57 +00:00
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// control signals
|
|
|
|
logic FRegWriteD, FRegWriteE, FRegWriteW; // FP register write enable
|
|
|
|
logic [2:0] FrmD, FrmE, FrmM; // FP rounding mode
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FMTBITS-1:0] FmtD, FmtE, FmtM, FmtW; // FP precision 0-single 1-double
|
2021-12-20 00:53:41 +00:00
|
|
|
logic FDivStartD, FDivStartE; // Start division or squareroot
|
|
|
|
logic FWriteIntD; // Write to integer register
|
|
|
|
logic [1:0] FForwardXE, FForwardYE, FForwardZE; // forwarding mux control signals
|
|
|
|
logic [1:0] FResultSelD, FResultSelE; // Select the result written to FP register
|
|
|
|
logic [1:0] FResultSelM, FResultSelW; // Select the result written to FP register
|
|
|
|
logic [2:0] FOpCtrlD, FOpCtrlE; // Select which opperation to do in each component
|
2022-05-25 23:02:02 +00:00
|
|
|
logic [1:0] FResSelD, FResSelE; // Select one of the results that finish in the memory stage
|
2021-12-20 00:53:41 +00:00
|
|
|
logic [1:0] FIntResSelD, FIntResSelE; // Select the result written to the integer resister
|
|
|
|
logic [4:0] Adr1E, Adr2E, Adr3E; // adresses of each input
|
|
|
|
|
|
|
|
// regfile signals
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] FRD1D, FRD2D, FRD3D; // Read Data from FP register - decode stage
|
|
|
|
logic [`FLEN-1:0] FRD1E, FRD2E, FRD3E; // Read Data from FP register - execute stage
|
|
|
|
logic [`FLEN-1:0] FSrcXE; // Input 1 to the various units (after forwarding)
|
|
|
|
logic [`FLEN-1:0] FPreSrcYE, FSrcYE; // Input 2 to the various units (after forwarding)
|
|
|
|
logic [`FLEN-1:0] FPreSrcZE, FSrcZE; // Input 3 to the various units (after forwarding)
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// unpacking signals
|
|
|
|
logic XSgnE, YSgnE, ZSgnE; // input's sign - execute stage
|
|
|
|
logic XSgnM, YSgnM; // input's sign - memory stage
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`NE-1:0] XExpE, YExpE, ZExpE; // input's exponent - execute stage
|
|
|
|
logic [`NE-1:0] ZExpM; // input's exponent - memory stage
|
|
|
|
logic [`NF:0] XManE, YManE, ZManE; // input's fraction - execute stage
|
|
|
|
logic [`NF:0] XManM, YManM, ZManM; // input's fraction - memory stage
|
2021-12-20 00:53:41 +00:00
|
|
|
logic XNaNE, YNaNE, ZNaNE; // is the input a NaN - execute stage
|
|
|
|
logic XNaNM, YNaNM, ZNaNM; // is the input a NaN - memory stage
|
|
|
|
logic XNaNQ, YNaNQ; // is the input a NaN - divide
|
|
|
|
logic XSNaNE, YSNaNE, ZSNaNE; // is the input a signaling NaN - execute stage
|
|
|
|
logic XSNaNM, YSNaNM, ZSNaNM; // is the input a signaling NaN - memory stage
|
2022-06-01 16:52:21 +00:00
|
|
|
logic XDenormE, ZDenormE; // is the input denormalized
|
2021-12-20 00:53:41 +00:00
|
|
|
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
|
|
|
logic XZeroM, YZeroM, ZZeroM; // is the input zero - memory stage
|
|
|
|
logic XZeroQ, YZeroQ; // is the input zero - divide
|
|
|
|
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
|
|
|
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
|
|
|
logic XInfQ, YInfQ; // is the input infinity - divide
|
|
|
|
logic XExpMaxE; // is the exponent all ones (max value)
|
|
|
|
logic FmtQ;
|
|
|
|
logic FOpCtrlQ;
|
|
|
|
|
|
|
|
// result and flag signals
|
2022-06-06 16:06:04 +00:00
|
|
|
logic [63:0] FDivResM, FDivResW; // divide/squareroot result
|
2021-12-20 00:53:41 +00:00
|
|
|
logic [4:0] FDivFlgM; // divide/squareroot flags
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] FMAResM, FMAResW; // FMA/multiply result
|
2021-12-20 00:53:41 +00:00
|
|
|
logic [4:0] FMAFlgM; // FMA/multiply result
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] ReadResW; // read result (load instruction)
|
|
|
|
logic [`FLEN-1:0] CvtResE; // FP <-> int convert result
|
2022-05-25 23:02:02 +00:00
|
|
|
logic [`XLEN-1:0] CvtIntResE; // FP <-> int convert result
|
2021-12-20 00:53:41 +00:00
|
|
|
logic [4:0] CvtFlgE; // FP <-> int convert flags //*** trim this
|
2022-06-01 23:34:29 +00:00
|
|
|
logic [`XLEN-1:0] ClassResE; // classify result
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] CmpResE; // compare result
|
2021-12-20 00:53:41 +00:00
|
|
|
logic CmpNVE; // compare invalid flag (Not Valid)
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] SgnResE; // sign injection result
|
|
|
|
logic [`FLEN-1:0] FResE, FResM, FResW; // selected result that is ready in the memory stage
|
2021-12-20 00:53:41 +00:00
|
|
|
logic [4:0] FFlgE, FFlgM; // selected flag that is ready in the memory stage
|
|
|
|
logic [`XLEN-1:0] FIntResE;
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] FPUResultW; // final FP result being written to the FP register
|
2021-12-20 00:53:41 +00:00
|
|
|
// other signals
|
|
|
|
logic FDivSqrtDoneE; // is divide done
|
2022-06-06 16:06:04 +00:00
|
|
|
logic [63:0] DivInput1E, DivInput2E; // inputs to divide/squareroot unit
|
2021-12-20 00:53:41 +00:00
|
|
|
logic load_preload; // enable for FF on fpdivsqrt
|
2022-06-02 19:50:28 +00:00
|
|
|
logic [`FLEN-1:0] AlignedSrcAE; // align SrcA to the floating point format
|
|
|
|
logic [`FLEN-1:0] BoxedZeroE; // Zero value for Z for multiplication, with NaN boxing if needed
|
|
|
|
logic [`FLEN-1:0] BoxedOneE; // Zero value for Z for multiplication, with NaN boxing if needed
|
2022-01-06 23:03:29 +00:00
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// DECODE STAGE
|
|
|
|
|
|
|
|
// calculate FP control signals
|
2022-05-03 11:56:31 +00:00
|
|
|
fctrl fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]), .FRM_REGW, .STATUS_FS,
|
2021-12-20 00:53:41 +00:00
|
|
|
.IllegalFPUInstrD, .FRegWriteD, .FDivStartD, .FResultSelD, .FOpCtrlD, .FResSelD,
|
|
|
|
.FIntResSelD, .FmtD, .FrmD, .FWriteIntD);
|
|
|
|
|
|
|
|
// FP register file
|
|
|
|
fregfile fregfile (.clk, .reset, .we4(FRegWriteW),
|
|
|
|
.a1(InstrD[19:15]), .a2(InstrD[24:20]), .a3(InstrD[31:27]),
|
|
|
|
.a4(RdW), .wd4(FPUResultW),
|
|
|
|
.rd1(FRD1D), .rd2(FRD2D), .rd3(FRD3D));
|
|
|
|
|
|
|
|
// D/E pipeline registers
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(`FLEN) DEReg1(clk, reset, FlushE, ~StallE, FRD1D, FRD1E);
|
|
|
|
flopenrc #(`FLEN) DEReg2(clk, reset, FlushE, ~StallE, FRD2D, FRD2E);
|
|
|
|
flopenrc #(`FLEN) DEReg3(clk, reset, FlushE, ~StallE, FRD3D, FRD3E);
|
2021-12-20 00:53:41 +00:00
|
|
|
flopenrc #(15) DEAdrReg(clk, reset, FlushE, ~StallE, {InstrD[19:15], InstrD[24:20], InstrD[31:27]},
|
|
|
|
{Adr1E, Adr2E, Adr3E});
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(16+int'(`FMTBITS-1)) DECtrlReg3(clk, reset, FlushE, ~StallE,
|
2021-12-20 00:53:41 +00:00
|
|
|
{FRegWriteD, FResultSelD, FResSelD, FIntResSelD, FrmD, FmtD, FOpCtrlD, FWriteIntD, FDivStartD},
|
|
|
|
{FRegWriteE, FResultSelE, FResSelE, FIntResSelE, FrmE, FmtE, FOpCtrlE, FWriteIntE, FDivStartE});
|
|
|
|
|
|
|
|
// EXECUTION STAGE
|
|
|
|
// Hazard unit for FPU
|
|
|
|
// - determines if any forwarding or stalls are needed
|
|
|
|
fhazard fhazard(.Adr1E, .Adr2E, .Adr3E, .FRegWriteM, .FRegWriteW, .RdM, .RdW, .FResultSelM,
|
|
|
|
.FStallD, .FForwardXE, .FForwardYE, .FForwardZE);
|
|
|
|
|
|
|
|
// forwarding muxs
|
2022-06-02 19:50:28 +00:00
|
|
|
mux3 #(`FLEN) fxemux (FRD1E, FPUResultW, FResM, FForwardXE, FSrcXE);
|
|
|
|
mux3 #(`FLEN) fyemux (FRD2E, FPUResultW, FResM, FForwardYE, FPreSrcYE);
|
|
|
|
mux3 #(`FLEN) fzemux (FRD3E, FPUResultW, FResM, FForwardZE, FPreSrcZE);
|
|
|
|
|
|
|
|
|
|
|
|
generate
|
|
|
|
if(`FPSIZES == 1) assign BoxedOneE = {2'b0, {`NE-1{1'b1}}, (`NF)'(0)};
|
|
|
|
else if(`FPSIZES == 2)
|
|
|
|
mux2 #(`FLEN) fonemux ({{`FLEN-`LEN1{1'b1}}, 2'b0, {`NE1-1{1'b1}}, (`NF1)'(0)}, {2'b0, {`NE-1{1'b1}}, (`NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
|
|
|
else if(`FPSIZES == 3 | `FPSIZES == 4)
|
|
|
|
mux4 #(`FLEN) fonemux ({{`FLEN-`S_LEN{1'b1}}, 2'b0, {`S_NE-1{1'b1}}, (`S_NF)'(0)},
|
|
|
|
{{`FLEN-`D_LEN{1'b1}}, 2'b0, {`D_NE-1{1'b1}}, (`D_NF)'(0)},
|
|
|
|
{{`FLEN-`H_LEN{1'b1}}, 2'b0, {`H_NE-1{1'b1}}, (`H_NF)'(0)},
|
|
|
|
{2'b0, {`NE-1{1'b1}}, (`NF)'(0)}, FmtE, BoxedOneE); // NaN boxing zeroes
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
|
|
|
|
mux2 #(`FLEN) fyaddmux (FPreSrcYE, BoxedOneE, FOpCtrlE[2]&FOpCtrlE[1]&(FResultSelE==2'b01), FSrcYE); // Force Z to be 0 for multiply instructions
|
|
|
|
|
2022-01-06 23:03:29 +00:00
|
|
|
// Force Z to be 0 for multiply instructions
|
2022-06-02 19:50:28 +00:00
|
|
|
generate
|
|
|
|
if(`FPSIZES == 1) assign BoxedZeroE = 0;
|
|
|
|
else if(`FPSIZES == 2)
|
2022-06-06 16:06:04 +00:00
|
|
|
mux2 #(`FLEN) fmulzeromux ({{`FLEN-`LEN1{1'b1}}, {`LEN1{1'b0}}}, (`FLEN)'(0), FmtE, BoxedZeroE); // NaN boxing zeroes
|
2022-06-02 19:50:28 +00:00
|
|
|
else if(`FPSIZES == 3 | `FPSIZES == 4)
|
2022-06-06 16:06:04 +00:00
|
|
|
mux4 #(`FLEN) fmulzeromux ({{`FLEN-`S_LEN{1'b1}}, {`S_LEN{1'b0}}},
|
|
|
|
{{`FLEN-`D_LEN{1'b1}}, {`D_LEN{1'b0}}},
|
|
|
|
{{`FLEN-`H_LEN{1'b1}}, {`H_LEN{1'b0}}},
|
2022-06-02 19:50:28 +00:00
|
|
|
(`FLEN)'(0), FmtE, BoxedZeroE); // NaN boxing zeroes
|
|
|
|
endgenerate
|
|
|
|
|
|
|
|
mux3 #(`FLEN) fzmulmux (FPreSrcZE, BoxedZeroE, FPreSrcYE, {FOpCtrlE[2]&FOpCtrlE[1], FOpCtrlE[2]&~FOpCtrlE[1]}, FSrcZE);
|
|
|
|
|
2022-02-28 20:50:51 +00:00
|
|
|
// unpack unit
|
2021-12-20 00:53:41 +00:00
|
|
|
// - splits FP inputs into their various parts
|
|
|
|
// - does some classifications (SNaN, NaN, Denorm, Norm, Zero, Infifnity)
|
2022-05-27 21:37:10 +00:00
|
|
|
unpack unpack (.X(FSrcXE), .Y(FSrcYE), .Z(FSrcZE), .FmtE,
|
2021-12-20 00:53:41 +00:00
|
|
|
.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE, .XManE, .YManE, .ZManE,
|
2022-06-01 16:52:21 +00:00
|
|
|
.XNaNE, .YNaNE, .ZNaNE, .XSNaNE, .YSNaNE, .ZSNaNE, .XDenormE, .ZDenormE,
|
2022-05-31 21:32:31 +00:00
|
|
|
.XZeroE, .YZeroE, .ZZeroE, .XInfE, .YInfE, .ZInfE, .XExpMaxE);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// FMA
|
|
|
|
// - two stage FMA
|
|
|
|
// - execute stage - multiplication and addend shifting
|
|
|
|
// - memory stage - addition and rounding
|
|
|
|
// - handles FMA and multiply instructions
|
|
|
|
fma fma (.clk, .reset, .FlushM, .StallM,
|
|
|
|
.XSgnE, .YSgnE, .ZSgnE, .XExpE, .YExpE, .ZExpE, .XManE, .YManE, .ZManE,
|
2022-05-27 21:37:10 +00:00
|
|
|
.ZDenormE, .XZeroE, .YZeroE, .ZZeroE,
|
2022-05-12 14:36:15 +00:00
|
|
|
.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM,
|
2021-12-20 00:53:41 +00:00
|
|
|
.XNaNM, .YNaNM, .ZNaNM, .XZeroM, .YZeroM, .ZZeroM,
|
|
|
|
.XInfM, .YInfM, .ZInfM, .XSNaNM, .YSNaNM, .ZSNaNM,
|
2022-05-27 21:37:10 +00:00
|
|
|
.FOpCtrlE,
|
2021-12-20 00:53:41 +00:00
|
|
|
.FmtE, .FmtM, .FrmM,
|
|
|
|
.FMAFlgM, .FMAResM);
|
|
|
|
|
|
|
|
// fpdivsqrt using Goldschmidt's iteration
|
2022-06-06 16:06:04 +00:00
|
|
|
if(`FLEN == 64) begin
|
|
|
|
flopenrc #(64) reg_input1 (.d({FSrcXE[63:0]}), .q(DivInput1E),
|
2021-12-20 00:53:41 +00:00
|
|
|
.clear(FDivSqrtDoneE), .en(load_preload),
|
|
|
|
.reset(reset), .clk(clk));
|
2022-06-06 16:06:04 +00:00
|
|
|
flopenrc #(64) reg_input2 (.d({FSrcYE[63:0]}), .q(DivInput2E),
|
2021-12-20 00:53:41 +00:00
|
|
|
.clear(FDivSqrtDoneE), .en(load_preload),
|
|
|
|
.reset(reset), .clk(clk));
|
2022-06-06 16:06:04 +00:00
|
|
|
end
|
|
|
|
else if (`FLEN == 32) begin
|
|
|
|
flopenrc #(64) reg_input1 (.d({32'b0, FSrcXE[31:0]}), .q(DivInput1E),
|
|
|
|
.clear(FDivSqrtDoneE), .en(load_preload),
|
|
|
|
.reset(reset), .clk(clk));
|
|
|
|
flopenrc #(64) reg_input2 (.d({32'b0, FSrcYE[31:0]}), .q(DivInput2E),
|
|
|
|
.clear(FDivSqrtDoneE), .en(load_preload),
|
|
|
|
.reset(reset), .clk(clk));
|
|
|
|
end
|
|
|
|
flopenrc #(8) reg_input3 (.d({XNaNE, YNaNE, XInfE, YInfE, XZeroE, YZeroE, FmtE[0], FOpCtrlE[0]}),
|
2021-12-20 00:53:41 +00:00
|
|
|
.q({XNaNQ, YNaNQ, XInfQ, YInfQ, XZeroQ, YZeroQ, FmtQ, FOpCtrlQ}),
|
|
|
|
.clear(FDivSqrtDoneE), .en(load_preload),
|
|
|
|
.reset(reset), .clk(clk));
|
2022-06-06 16:06:04 +00:00
|
|
|
fpdiv_pipe fdivsqrt (.op1(DivInput1E[63:0]), .op2(DivInput2E[63:0]), .rm(FrmE[1:0]), .op_type(FOpCtrlQ),
|
2021-12-20 00:53:41 +00:00
|
|
|
.reset, .clk(clk), .start(FDivStartE), .P(~FmtQ), .OvEn(1'b1), .UnEn(1'b1),
|
|
|
|
.XNaNQ, .YNaNQ, .XInfQ, .YInfQ, .XZeroQ, .YZeroQ, .load_preload,
|
|
|
|
.FDivBusyE, .done(FDivSqrtDoneE), .AS_Result(FDivResM), .Flags(FDivFlgM));
|
|
|
|
|
2022-05-12 15:15:30 +00:00
|
|
|
// other FP execution units
|
2022-01-01 23:50:23 +00:00
|
|
|
fcmp fcmp (.FmtE, .FOpCtrlE, .XSgnE, .YSgnE, .XExpE, .YExpE, .XManE, .YManE,
|
|
|
|
.XZeroE, .YZeroE, .XNaNE, .YNaNE, .XSNaNE, .YSNaNE, .FSrcXE, .FSrcYE, .CmpNVE, .CmpResE);
|
2022-05-29 23:07:56 +00:00
|
|
|
fsgninj fsgninj(.SgnOpCodeE(FOpCtrlE[1:0]), .XSgnE, .YSgnE, .FSrcXE, .FmtE, .SgnResE);
|
2022-05-31 21:32:31 +00:00
|
|
|
fclassify fclassify (.XSgnE, .XDenormE, .XZeroE, .XNaNE, .XInfE, .XSNaNE, .ClassResE);
|
2022-05-27 21:37:10 +00:00
|
|
|
fcvt fcvt (.XSgnE, .XExpE, .XManE, .ForwardedSrcAE, .FOpCtrlE, .FWriteIntE, .XZeroE, .XDenormE,
|
2022-05-25 23:02:02 +00:00
|
|
|
.XInfE, .XNaNE, .XSNaNE, .FrmE, .FmtE, .CvtResE, .CvtIntResE, .CvtFlgE);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// data to be stored in memory - to IEU
|
|
|
|
// - FP uses NaN-blocking format
|
|
|
|
// - if there are any unsused bits the most significant bits are filled with 1s
|
2022-06-06 16:06:04 +00:00
|
|
|
if (`FLEN>`XLEN) assign FWriteDataE = FSrcYE[`XLEN-1:0];
|
|
|
|
else assign FWriteDataE = {{`XLEN-`FLEN{FSrcYE[`FLEN-1]}}, FSrcYE};
|
2021-12-20 00:53:41 +00:00
|
|
|
|
2022-06-02 19:50:28 +00:00
|
|
|
// NaN Block SrcA
|
|
|
|
generate
|
|
|
|
if(`FPSIZES == 1) assign AlignedSrcAE = {{`FLEN-`XLEN{1'b1}}, ForwardedSrcAE};
|
|
|
|
else if(`FPSIZES == 2)
|
|
|
|
mux2 #(`FLEN) SrcAMux ({{`FLEN-`LEN1{1'b1}}, ForwardedSrcAE[`LEN1-1:0]}, {{`FLEN-`XLEN{1'b1}}, ForwardedSrcAE}, FmtE, AlignedSrcAE);
|
|
|
|
else if(`FPSIZES == 3 | `FPSIZES == 4)
|
|
|
|
mux4 #(`FLEN) SrcAMux ({{`FLEN-`S_LEN{1'b1}}, ForwardedSrcAE[`S_LEN-1:0]},
|
|
|
|
{{`FLEN-`D_LEN{1'b1}}, ForwardedSrcAE[`D_LEN-1:0]},
|
|
|
|
{{`FLEN-`H_LEN{1'b1}}, ForwardedSrcAE[`H_LEN-1:0]},
|
|
|
|
{{`FLEN-`XLEN{1'b1}}, ForwardedSrcAE}, FmtE, AlignedSrcAE); // NaN boxing zeroes
|
|
|
|
endgenerate
|
2021-12-20 00:53:41 +00:00
|
|
|
// select a result that may be written to the FP register
|
2022-06-02 19:50:28 +00:00
|
|
|
mux4 #(`FLEN) FResMux(AlignedSrcAE, SgnResE, CmpResE, CvtResE, FResSelE, FResE);
|
2022-05-25 23:02:02 +00:00
|
|
|
mux4 #(5) FFlgMux(5'b0, 5'b0, {CmpNVE, 4'b0}, CvtFlgE, FResSelE, FFlgE);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// select the result that may be written to the integer register - to IEU
|
2022-06-06 16:06:04 +00:00
|
|
|
if (`FLEN>`XLEN)
|
|
|
|
mux4 #(`XLEN) IntResMux(CmpResE[`XLEN-1:0], FSrcXE[`XLEN-1:0], ClassResE,
|
|
|
|
CvtIntResE, FIntResSelE, FIntResE);
|
|
|
|
else
|
|
|
|
mux4 #(`XLEN) IntResMux({{`XLEN-`FLEN{CmpResE[`FLEN-1:0]}}, CmpResE}, {{`XLEN-`FLEN{FSrcXE[`FLEN-1:0]}}, FSrcXE}, ClassResE,
|
|
|
|
CvtIntResE, FIntResSelE, FIntResE);
|
2022-05-28 09:41:48 +00:00
|
|
|
// *** DH 5/25/22: CvtRes will move to mem stage. Premux in execute to save area, then make sure stalls are ok
|
2022-05-28 09:44:55 +00:00
|
|
|
// *** make sure the fpu matches the chapter diagram
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// E/M pipe registers
|
|
|
|
|
|
|
|
// flopenrc #(64) EMFpReg1(clk, reset, FlushM, ~StallM, FSrcXE, FSrcXM);
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(`NF+2) EMFpReg2 (clk, reset, FlushM, ~StallM, {XSgnE,XManE}, {XSgnM,XManM});
|
|
|
|
flopenrc #(`NF+2) EMFpReg3 (clk, reset, FlushM, ~StallM, {YSgnE,YManE}, {YSgnM,YManM});
|
|
|
|
flopenrc #(`FLEN) EMFpReg4 (clk, reset, FlushM, ~StallM, {ZExpE,ZManE}, {ZExpM,ZManM});
|
2021-12-20 00:53:41 +00:00
|
|
|
flopenrc #(12) EMFpReg5 (clk, reset, FlushM, ~StallM,
|
|
|
|
{XZeroE, YZeroE, ZZeroE, XInfE, YInfE, ZInfE, XNaNE, YNaNE, ZNaNE, XSNaNE, YSNaNE, ZSNaNE},
|
|
|
|
{XZeroM, YZeroM, ZZeroM, XInfM, YInfM, ZInfM, XNaNM, YNaNM, ZNaNM, XSNaNM, YSNaNM, ZSNaNM});
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(`FLEN) EMRegCmpRes (clk, reset, FlushM, ~StallM, FResE, FResM);
|
2021-12-20 00:53:41 +00:00
|
|
|
flopenrc #(5) EMRegCmpFlg (clk, reset, FlushM, ~StallM, FFlgE, FFlgM);
|
|
|
|
flopenrc #(`XLEN) EMRegSgnRes (clk, reset, FlushM, ~StallM, FIntResE, FIntResM);
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(7+int'(`FMTBITS-1)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
2021-12-20 00:53:41 +00:00
|
|
|
{FRegWriteE, FResultSelE, FrmE, FmtE},
|
|
|
|
{FRegWriteM, FResultSelM, FrmM, FmtM});
|
|
|
|
|
|
|
|
// BEGIN MEMORY STAGE
|
|
|
|
|
|
|
|
// FPU flag selection - to privileged
|
|
|
|
mux4 #(5) FPUFlgMux (5'b0, FMAFlgM, FDivFlgM, FFlgM, FResultSelM, SetFflagsM);
|
|
|
|
|
|
|
|
// M/W pipe registers
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(`FLEN) MWRegFma(clk, reset, FlushW, ~StallW, FMAResM, FMAResW);
|
2022-06-06 16:06:04 +00:00
|
|
|
flopenrc #(64) MWRegDiv(clk, reset, FlushW, ~StallW, FDivResM, FDivResW);
|
2022-06-02 19:50:28 +00:00
|
|
|
flopenrc #(`FLEN) MWRegClass(clk, reset, FlushW, ~StallW, FResM, FResW);
|
|
|
|
flopenrc #(4+int'(`FMTBITS-1)) MWCtrlReg(clk, reset, FlushW, ~StallW,
|
2021-12-20 00:53:41 +00:00
|
|
|
{FRegWriteM, FResultSelM, FmtM},
|
|
|
|
{FRegWriteW, FResultSelW, FmtW});
|
|
|
|
|
|
|
|
// BEGIN WRITEBACK STAGE
|
|
|
|
|
|
|
|
// put ReadData into NaN-blocking format
|
|
|
|
// - if there are any unsused bits the most significant bits are filled with 1s
|
|
|
|
// - for load instruction
|
2022-06-02 19:50:28 +00:00
|
|
|
generate
|
|
|
|
if(`FPSIZES == 1) assign ReadResW = {{`FLEN-`XLEN{1'b1}}, ReadDataW};
|
|
|
|
else if(`FPSIZES == 2)
|
|
|
|
mux2 #(`FLEN) SrcAMux ({{`FLEN-`LEN1{1'b1}}, ReadDataW[`LEN1-1:0]}, {{`FLEN-`XLEN{1'b1}}, ReadDataW}, FmtW, ReadResW);
|
|
|
|
else if(`FPSIZES == 3 | `FPSIZES == 4)
|
|
|
|
mux4 #(`FLEN) SrcAMux ({{`FLEN-`S_LEN{1'b1}}, ReadDataW[`S_LEN-1:0]},
|
|
|
|
{{`FLEN-`D_LEN{1'b1}}, ReadDataW[`D_LEN-1:0]},
|
|
|
|
{{`FLEN-`H_LEN{1'b1}}, ReadDataW[`H_LEN-1:0]},
|
|
|
|
{{`FLEN-`XLEN{1'b1}}, ReadDataW}, FmtW, ReadResW); // NaN boxing zeroes
|
|
|
|
endgenerate
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// select the result to be written to the FP register
|
2022-06-06 16:06:04 +00:00
|
|
|
if(`FLEN>=64)
|
|
|
|
mux4 #(`FLEN) FPUResultMux (ReadResW, FMAResW, {{`FLEN-64{1'b0}},FDivResW}, FResW, FResultSelW, FPUResultW);
|
2021-06-01 19:45:32 +00:00
|
|
|
endmodule // fpu
|