2021-05-24 13:28:16 +00:00
|
|
|
///////////////////////////////////////////
|
|
|
|
//
|
2022-07-07 23:01:33 +00:00
|
|
|
// Written: me@KatherineParry.com, 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 (
|
2022-07-20 02:27:39 +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 [`FLEN-1:0] ReadDataW, // Read data (from LSU)
|
|
|
|
input logic [`XLEN-1:0] ForwardedSrcAE, // Integer input (from IEU)
|
|
|
|
input logic StallE, StallM, StallW, // stall signals (from HZU)
|
|
|
|
input logic FlushE, FlushM, FlushW, // flush signals (from HZU)
|
|
|
|
input logic [4:0] RdM, RdW, // which FP register to write to (from IEU)
|
|
|
|
input logic [1:0] STATUS_FS, // Is floating-point enabled? (From privileged unit)
|
|
|
|
output logic FRegWriteM, // FP register write enable (to privileged unit)
|
|
|
|
output logic FpLoadStoreM, // Fp load instruction? (to LSU)
|
|
|
|
output logic FStallD, // Stall the decode stage (To HZU)
|
|
|
|
output logic FWriteIntE, // integer register write enable (to IEU)
|
2022-08-22 20:43:04 +00:00
|
|
|
output logic [`FLEN-1:0] FWriteDataM, // Data to be written to memory (to LSU)
|
2022-07-20 02:27:39 +00:00
|
|
|
output logic [`XLEN-1:0] FIntResM, // data to be written to integer register (to IEU)
|
|
|
|
output logic [`XLEN-1:0] FCvtIntResW, // convert result to to be written to integer register (to IEU)
|
|
|
|
output logic [1:0] FResSelW, // final result selection (to IEU)
|
|
|
|
output logic FDivBusyE, // Is the divide/sqrt unit busy (stall execute stage) (to HZU)
|
|
|
|
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction (to privileged unit)
|
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
|
|
|
// 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
|
2022-08-22 20:43:04 +00:00
|
|
|
|
|
|
|
// LSU interface
|
|
|
|
logic [`FLEN-1:0] FWriteDataE;
|
2021-07-24 18:59:57 +00:00
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// control signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic FRegWriteW; // FP register write enable
|
|
|
|
logic [2:0] FrmM; // FP rounding mode
|
|
|
|
logic [`FMTBITS-1:0] FmtE, FmtM; // FP precision 0-single 1-double
|
|
|
|
logic DivStartE; // Start division or squareroot
|
|
|
|
logic FWriteIntM; // Write to integer register
|
|
|
|
logic [1:0] ForwardXE, ForwardYE, ForwardZE; // forwarding mux control signals
|
|
|
|
logic [2:0] OpCtrlE, OpCtrlM; // Select which opperation to do in each component
|
|
|
|
logic [1:0] FResSelE, FResSelM; // Select one of the results that finish in the memory stage
|
|
|
|
logic [1:0] PostProcSelE, PostProcSelM; // select result in the post processing unit
|
|
|
|
logic [4:0] Adr1E, Adr2E, Adr3E; // adresses of each input
|
2022-07-20 21:57:23 +00:00
|
|
|
logic IllegalFPUInstrM;
|
2022-07-21 01:20:06 +00:00
|
|
|
logic XEnE, YEnE, ZEnE;
|
|
|
|
logic YEnForwardE, ZEnForwardE;
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// regfile signals
|
2022-07-20 02:27:39 +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] XE; // Input 1 to the various units (after forwarding)
|
|
|
|
logic [`XLEN-1:0] IntSrcXE; // Input 1 to the various units (after forwarding)
|
|
|
|
logic [`FLEN-1:0] PreYE, YE; // Input 2 to the various units (after forwarding)
|
|
|
|
logic [`FLEN-1:0] PreZE, ZE; // Input 3 to the various units (after forwarding)
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// unpacking signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic XsE, YsE, ZsE; // input's sign - execute stage
|
|
|
|
logic XsM, YsM; // input's sign - memory stage
|
|
|
|
logic [`NE-1:0] XeE, YeE, ZeE; // input's exponent - execute stage
|
|
|
|
logic [`NE-1:0] ZeM; // input's exponent - memory stage
|
|
|
|
logic [`NF:0] XmE, YmE, ZmE; // input's fraction - execute stage
|
|
|
|
logic [`NF:0] XmM, YmM, ZmM; // input's fraction - memory stage
|
|
|
|
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
|
|
|
|
logic XDenormE, ZDenormE, ZDenormM; // is the input denormalized
|
|
|
|
logic XZeroE, YZeroE, ZZeroE; // is the input zero - execute stage
|
|
|
|
logic XZeroM, YZeroM, ZZeroM; // is the input zero - memory stage
|
|
|
|
logic XInfE, YInfE, ZInfE; // is the input infinity - execute stage
|
|
|
|
logic XInfM, YInfM, ZInfM; // is the input infinity - memory stage
|
|
|
|
logic XExpMaxE; // is the exponent all ones (max value)
|
2022-06-13 22:47:51 +00:00
|
|
|
|
|
|
|
// Fma Signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [3*`NF+5:0] SmE, SmM;
|
|
|
|
logic [`NE+1:0] PeE, PeM;
|
|
|
|
logic ZmStickyE, ZmStickyM;
|
|
|
|
logic [`NE+1:0] SeE,SeM;
|
|
|
|
logic KillProdE, KillProdM;
|
|
|
|
logic InvAE, InvAM;
|
|
|
|
logic NegSumE, NegSumM;
|
|
|
|
logic AsE, AsM;
|
|
|
|
logic PsE, PsM;
|
|
|
|
logic SsE, SsM;
|
|
|
|
logic [$clog2(3*`NF+7)-1:0] SCntE, SCntM;
|
2022-06-13 22:47:51 +00:00
|
|
|
|
|
|
|
// Cvt Signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`NE:0] CeE, CeM; // the calculated expoent
|
|
|
|
logic [`LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
2022-06-23 16:11:50 +00:00
|
|
|
logic CvtResDenormUfE, CvtResDenormUfM;// does the result underflow or is denormalized
|
2022-07-20 02:27:39 +00:00
|
|
|
logic CsE, CsM; // the result's sign
|
2022-06-23 16:11:50 +00:00
|
|
|
logic IntZeroE, IntZeroM; // is the integer zero?
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
|
2022-06-23 16:11:50 +00:00
|
|
|
|
|
|
|
//divide signals
|
2022-07-22 22:02:04 +00:00
|
|
|
logic [`DIVb-(`RADIX/4):0] QmM;
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`NE+1:0] QeE, QeM;
|
|
|
|
logic DivSE, DivSM;
|
|
|
|
logic DivDoneM;
|
|
|
|
logic [`DURLEN-1:0] EarlyTermShiftM;
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// result and flag signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`XLEN-1:0] ClassResE; // classify result
|
|
|
|
logic [`XLEN-1:0] FIntResE; // classify result
|
|
|
|
logic [`FLEN-1:0] FpResM, FpResW; // classify result
|
|
|
|
logic [`FLEN-1:0] PostProcResM; // classify result
|
|
|
|
logic [4:0] PostProcFlgM; // classify result
|
2022-06-13 22:47:51 +00:00
|
|
|
logic [`XLEN-1:0] FCvtIntResM;
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`FLEN-1:0] CmpFpResE; // compare result
|
|
|
|
logic [`XLEN-1:0] CmpIntResE; // compare result
|
|
|
|
logic CmpNVE; // compare invalid flag (Not Valid)
|
|
|
|
logic [`FLEN-1:0] SgnResE; // sign injection result
|
|
|
|
logic [`FLEN-1:0] PreFpResE, PreFpResM; // selected result that is ready in the memory stage
|
|
|
|
logic PreNVE, PreNVM; // selected flag that is ready in the memory stage
|
|
|
|
logic [`FLEN-1:0] FPUResultW; // final FP result being written to the FP register
|
2021-12-20 00:53:41 +00:00
|
|
|
// other signals
|
2022-07-20 02:27:39 +00:00
|
|
|
logic [`FLEN-1:0] AlignedSrcAE; // align SrcA to the floating point format
|
2022-06-02 19:50:28 +00:00
|
|
|
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
|
|
|
|
|
2022-06-13 22:47:51 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// |||||||||||
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// |||||||||||
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// calculate FP control signals
|
2022-07-20 02:27:39 +00:00
|
|
|
fctrl fctrl (.Funct7D(InstrD[31:25]), .OpD(InstrD[6:0]), .Rs2D(InstrD[24:20]), .Funct3D(InstrD[14:12]), .InstrD,
|
|
|
|
.StallE, .StallM, .StallW, .FlushE, .FlushM, .FlushW, .FRM_REGW, .STATUS_FS, .FDivBusyE,
|
2022-07-21 01:20:06 +00:00
|
|
|
.reset, .clk, .IllegalFPUInstrD, .FRegWriteM, .FRegWriteW, .FrmM, .FmtE, .FmtM, .YEnForwardE, .ZEnForwardE,
|
|
|
|
.DivStartE, .FWriteIntE, .FWriteIntM, .OpCtrlE, .OpCtrlM, .IllegalFPUInstrM, .XEnE, .YEnE, .ZEnE,
|
2022-07-20 02:27:39 +00:00
|
|
|
.FResSelE, .FResSelM, .FResSelW, .PostProcSelE, .PostProcSelM, .Adr1E, .Adr2E, .Adr3E);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
|
// EXECUTION STAGE
|
2022-06-13 22:47:51 +00:00
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ||||||||||||
|
|
|
|
// |||
|
|
|
|
// |||
|
|
|
|
// |||||||||
|
|
|
|
// |||
|
|
|
|
// |||
|
|
|
|
// ||||||||||||
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// Hazard unit for FPU
|
|
|
|
// - determines if any forwarding or stalls are needed
|
2022-06-13 22:47:51 +00:00
|
|
|
fhazard fhazard(.Adr1E, .Adr2E, .Adr3E, .FRegWriteM, .FRegWriteW, .RdM, .RdW, .FResSelM,
|
2022-07-21 01:20:06 +00:00
|
|
|
.XEnE, .YEnE(YEnForwardE), .ZEnE(ZEnForwardE), .FStallD, .ForwardXE, .ForwardYE, .ForwardZE);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// forwarding muxs
|
2022-07-20 02:27:39 +00:00
|
|
|
mux3 #(`FLEN) fxemux (FRD1E, FPUResultW, PreFpResM, ForwardXE, XE);
|
|
|
|
mux3 #(`FLEN) fyemux (FRD2E, FPUResultW, PreFpResM, ForwardYE, PreYE);
|
|
|
|
mux3 #(`FLEN) fzemux (FRD3E, FPUResultW, PreFpResM, ForwardZE, PreZE);
|
2022-06-02 19:50:28 +00:00
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
mux2 #(`FLEN) fyaddmux (PreYE, BoxedOneE, OpCtrlE[2]&OpCtrlE[1]&(FResSelE==2'b01)&(PostProcSelE==2'b10), YE); // Force Z to be 0 for multiply instructions
|
2022-06-02 19:50:28 +00:00
|
|
|
|
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
|
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
mux3 #(`FLEN) fzmulmux (PreZE, BoxedZeroE, PreYE, {OpCtrlE[2]&OpCtrlE[1], OpCtrlE[2]&~OpCtrlE[1]}, ZE);
|
2022-06-02 19:50:28 +00:00
|
|
|
|
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-07-20 02:27:39 +00:00
|
|
|
unpack unpack (.X(XE), .Y(YE), .Z(ZE), .Fmt(FmtE), .Xs(XsE), .Ys(YsE), .Zs(ZsE),
|
2022-07-21 01:20:06 +00:00
|
|
|
.Xe(XeE), .Ye(YeE), .Ze(ZeE), .Xm(XmE), .Ym(YmE), .Zm(ZmE), .YEn(YEnE),
|
|
|
|
.XNaN(XNaNE), .YNaN(YNaNE), .ZNaN(ZNaNE), .XSNaN(XSNaNE), .XEn(XEnE),
|
2022-07-20 02:27:39 +00:00
|
|
|
.YSNaN(YSNaNE), .ZSNaN(ZSNaNE), .XDenorm(XDenormE), .ZDenorm(ZDenormE),
|
|
|
|
.XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE), .XInf(XInfE), .YInf(YInfE),
|
2022-07-21 01:20:06 +00:00
|
|
|
.ZEn(ZEnE), .ZInf(ZInfE), .XExpMax(XExpMaxE));
|
2022-06-13 22:47:51 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
// fused multiply add
|
|
|
|
// - fadd/fsub
|
|
|
|
// - fmul
|
|
|
|
// - fmadd/fnmadd/fmsub/fnmsub
|
|
|
|
fma fma (.Xs(XsE), .Ys(YsE), .Zs(ZsE),
|
|
|
|
.Xe(XeE), .Ye(YeE), .Ze(ZeE),
|
|
|
|
.Xm(XmE), .Ym(YmE), .Zm(ZmE),
|
2022-07-07 23:01:33 +00:00
|
|
|
.XZero(XZeroE), .YZero(YZeroE), .ZZero(ZZeroE),
|
2022-07-20 02:27:39 +00:00
|
|
|
.OpCtrl(OpCtrlE), .Fmt(FmtE),
|
|
|
|
.As(AsE), .Ps(PsE), .Ss(SsE), .Se(SeE),
|
|
|
|
.Sm(SmE), .Pe(PeE),
|
|
|
|
.NegSum(NegSumE), .InvA(InvAE), .SCnt(SCntE),
|
|
|
|
.ZmSticky(ZmStickyE), .KillProd(KillProdE));
|
|
|
|
|
|
|
|
// divide and squareroot
|
|
|
|
// - fdiv
|
|
|
|
// - fsqrt
|
|
|
|
// *** add other opperations
|
2022-07-21 19:38:06 +00:00
|
|
|
divsqrt divsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]),
|
2022-07-22 22:02:04 +00:00
|
|
|
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .DivStartE(DivStartE), .XsE,
|
2022-07-20 02:27:39 +00:00
|
|
|
.StallE, .StallM, .DivSM, .DivBusy(FDivBusyE), .QeM, //***change divbusyE to M signal
|
|
|
|
.EarlyTermShiftM, .QmM, .DivDone(DivDoneM));
|
|
|
|
// compare
|
|
|
|
// - fmin/fmax
|
|
|
|
// - flt/fle/feq
|
|
|
|
fcmp fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE),
|
|
|
|
.Xm(XmE), .Ym(YmE), .XZero(XZeroE), .YZero(YZeroE), .XNaN(XNaNE), .YNaN(YNaNE),
|
|
|
|
.XSNaN(XSNaNE), .YSNaN(YSNaNE), .X(XE), .Y(YE), .CmpNV(CmpNVE),
|
|
|
|
.CmpFpRes(CmpFpResE), .CmpIntRes(CmpIntResE));
|
|
|
|
// sign injection
|
|
|
|
// - fsgnj/fsgnjx/fsgnjn
|
|
|
|
fsgninj fsgninj(.OpCtrl(OpCtrlE[1:0]), .Xs(XsE), .Ys(YsE), .X(XE), .Fmt(FmtE), .SgnRes(SgnResE));
|
|
|
|
|
|
|
|
// classify
|
|
|
|
// - fclass
|
|
|
|
fclassify fclassify (.Xs(XsE), .XDenorm(XDenormE), .XZero(XZeroE), .XNaN(XNaNE),
|
|
|
|
.XInf(XInfE), .XSNaN(XSNaNE), .ClassRes(ClassResE));
|
|
|
|
|
|
|
|
// convert
|
|
|
|
// - fcvt.*.*
|
|
|
|
fcvt fcvt (.Xs(XsE), .Xe(XeE), .Xm(XmE), .Int(ForwardedSrcAE), .OpCtrl(OpCtrlE),
|
|
|
|
.ToInt(FWriteIntE), .XZero(XZeroE), .XDenorm(XDenormE), .Fmt(FmtE), .Ce(CeE),
|
|
|
|
.ShiftAmt(CvtShiftAmtE), .ResDenormUf(CvtResDenormUfE), .Cs(CsE), .IntZero(IntZeroE),
|
2022-07-08 19:30:43 +00:00
|
|
|
.LzcIn(CvtLzcInE));
|
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-08-03 22:16:51 +00:00
|
|
|
|
2022-08-22 20:43:04 +00:00
|
|
|
if(`FPSIZES == 1) assign FWriteDataE = YE;
|
|
|
|
else if(`FPSIZES == 2) assign FWriteDataE = FmtE ? YE : {`FLEN/`LEN1{YE[`LEN1-1:0]}};
|
2022-08-22 20:28:51 +00:00
|
|
|
else
|
|
|
|
always_comb
|
|
|
|
case(FmtE)
|
2022-08-22 20:43:04 +00:00
|
|
|
`Q_FMT: FWriteDataE = YE;
|
|
|
|
`D_FMT: FWriteDataE = {`FLEN/`D_LEN{YE[`D_LEN-1:0]}};
|
|
|
|
`S_FMT: FWriteDataE = {`FLEN/`S_LEN{YE[`S_LEN-1:0]}};
|
|
|
|
`H_FMT: FWriteDataE = {`FLEN/`H_LEN{YE[`H_LEN-1:0]}};
|
2022-08-22 20:28:51 +00:00
|
|
|
endcase
|
2022-08-22 20:43:04 +00:00
|
|
|
flopenrc #(`FLEN) FWriteDataMReg (clk, reset, FlushM, ~StallM, FWriteDataE, FWriteDataM);
|
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
|
2022-08-03 22:16:51 +00:00
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// select a result that may be written to the FP register
|
2022-07-20 02:27:39 +00:00
|
|
|
mux3 #(`FLEN) FResMux(SgnResE, AlignedSrcAE, CmpFpResE, {OpCtrlE[2], &OpCtrlE[1:0]}, PreFpResE);
|
|
|
|
assign PreNVE = CmpNVE&(OpCtrlE[2]|FWriteIntE);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// select the result that may be written to the integer register - to IEU
|
2022-08-01 19:56:25 +00:00
|
|
|
|
|
|
|
logic [`FLEN-1:0] SgnExtXE;
|
|
|
|
generate
|
|
|
|
if(`FPSIZES == 1)
|
|
|
|
assign SgnExtXE = XE;
|
|
|
|
else if(`FPSIZES == 2)
|
|
|
|
mux2 #(`FLEN) sgnextmux ({{`FLEN-`LEN1{XsE}}, XE[`LEN1-1:0]}, XE, FmtE, SgnExtXE);
|
|
|
|
else if(`FPSIZES == 3 | `FPSIZES == 4)
|
|
|
|
mux4 #(`FLEN) fmulzeromux ({{`FLEN-`H_LEN{XsE}}, XE[`H_LEN-1:0]},
|
|
|
|
{{`FLEN-`S_LEN{XsE}}, XE[`S_LEN-1:0]},
|
|
|
|
{{`FLEN-`D_LEN{XsE}}, XE[`D_LEN-1:0]},
|
|
|
|
XE, FmtE, SgnExtXE); // NaN boxing zeroes
|
|
|
|
endgenerate
|
2022-06-28 21:33:31 +00:00
|
|
|
if (`FLEN>`XLEN)
|
2022-08-01 19:56:25 +00:00
|
|
|
assign IntSrcXE = SgnExtXE[`XLEN-1:0];
|
2022-06-06 16:06:04 +00:00
|
|
|
else
|
2022-08-01 19:56:25 +00:00
|
|
|
assign IntSrcXE = {{`XLEN-`FLEN{XsE}}, SgnExtXE};
|
2022-06-13 22:47:51 +00:00
|
|
|
|
|
|
|
mux3 #(`XLEN) IntResMux (ClassResE, IntSrcXE, CmpIntResE, {~FResSelE[1], FResSelE[0]}, 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
|
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
// flopenrc #(64) EMFpReg1(clk, reset, FlushM, ~StallM, XE, FSrcXM);
|
|
|
|
flopenrc #(`NF+2) EMFpReg2 (clk, reset, FlushM, ~StallM, {XsE,XmE}, {XsM,XmM});
|
|
|
|
flopenrc #(`NF+2) EMFpReg3 (clk, reset, FlushM, ~StallM, {YsE,YmE}, {YsM,YmM});
|
|
|
|
flopenrc #(`FLEN) EMFpReg4 (clk, reset, FlushM, ~StallM, {ZeE,ZmE}, {ZeM,ZmM});
|
2022-06-13 22:47:51 +00:00
|
|
|
flopenrc #(`XLEN) EMFpReg6 (clk, reset, FlushM, ~StallM, FIntResE, FIntResM);
|
|
|
|
flopenrc #(`FLEN) EMFpReg7 (clk, reset, FlushM, ~StallM, PreFpResE, PreFpResM);
|
|
|
|
flopenrc #(13) EMFpReg5 (clk, reset, FlushM, ~StallM,
|
|
|
|
{XZeroE, YZeroE, ZZeroE, XInfE, YInfE, ZInfE, XNaNE, YNaNE, ZNaNE, XSNaNE, YSNaNE, ZSNaNE, ZDenormE},
|
|
|
|
{XZeroM, YZeroM, ZZeroM, XInfM, YInfM, ZInfM, XNaNM, YNaNM, ZNaNM, XSNaNM, YSNaNM, ZSNaNM, ZDenormM});
|
|
|
|
flopenrc #(1) EMRegCmpFlg (clk, reset, FlushM, ~StallM, PreNVE, PreNVM);
|
2022-07-20 02:27:39 +00:00
|
|
|
flopenrc #(3*`NF+6) EMRegFma2(clk, reset, FlushM, ~StallM, SmE, SmM);
|
|
|
|
flopenrc #(`NE+2) EMRegFma3(clk, reset, FlushM, ~StallM, PeE, PeM);
|
2022-07-19 01:10:10 +00:00
|
|
|
flopenrc #($clog2(3*`NF+7)+9+`NE) EMRegFma4(clk, reset, FlushM, ~StallM,
|
2022-07-20 02:27:39 +00:00
|
|
|
{ZmStickyE, KillProdE, InvAE, SCntE, NegSumE, AsE, PsE, SsE, SeE},
|
|
|
|
{ZmStickyM, KillProdM, InvAM, SCntM, NegSumM, AsM, PsM, SsM, SeM});
|
2022-06-23 00:07:34 +00:00
|
|
|
flopenrc #(`NE+`LOGCVTLEN+`CVTLEN+4) EMRegCvt(clk, reset, FlushM, ~StallM,
|
2022-07-20 02:27:39 +00:00
|
|
|
{CeE, CvtShiftAmtE, CvtResDenormUfE, CsE, IntZeroE, CvtLzcInE},
|
|
|
|
{CeM, CvtShiftAmtM, CvtResDenormUfM, CsM, IntZeroM, CvtLzcInM});
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// BEGIN MEMORY STAGE
|
|
|
|
|
2022-06-13 22:47:51 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ||| |||
|
|
|
|
// |||||| ||||||
|
|
|
|
// ||| ||| ||| |||
|
|
|
|
// ||| ||||| |||
|
|
|
|
// ||| ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2022-06-28 21:33:31 +00:00
|
|
|
assign FpLoadStoreM = FResSelM[1];
|
2022-06-20 22:53:13 +00:00
|
|
|
|
2022-07-20 02:27:39 +00:00
|
|
|
postprocess postprocess(.Xs(XsM), .Ys(YsM), .Ze(ZeM), .Xm(XmM), .Ym(YmM), .Zm(ZmM), .Frm(FrmM), .Fmt(FmtM), .FmaPe(PeM), .DivEarlyTermShift(EarlyTermShiftM),
|
|
|
|
.FmaZmS(ZmStickyM), .FmaKillProd(KillProdM), .XZero(XZeroM), .YZero(YZeroM), .ZZero(ZZeroM), .XInf(XInfM), .YInf(YInfM), .DivQm(QmM), .FmaSs(SsM),
|
|
|
|
.ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM), .FmaSm(SmM), .DivQe(QeM), .DivDone(DivDoneM),
|
|
|
|
.FmaNegSum(NegSumM), .FmaInvA(InvAM), .ZDenorm(ZDenormM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM),
|
|
|
|
.CvtCe(CeM), .CvtResDenormUf(CvtResDenormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM), .ToInt(FWriteIntM), .DivS(DivSM),
|
2022-07-12 01:30:21 +00:00
|
|
|
.CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM), .PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
|
2022-06-13 22:47:51 +00:00
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// FPU flag selection - to privileged
|
2022-06-13 22:47:51 +00:00
|
|
|
mux2 #(5) FPUFlgMux ({PreNVM&~FResSelM[1], 4'b0}, PostProcFlgM, ~FResSelM[1]&FResSelM[0], SetFflagsM);
|
|
|
|
mux2 #(`FLEN) FPUResMux (PreFpResM, PostProcResM, FResSelM[0], FpResM);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// M/W pipe registers
|
2022-06-13 22:47:51 +00:00
|
|
|
flopenrc #(`FLEN) MWRegFp(clk, reset, FlushW, ~StallW, FpResM, FpResW);
|
|
|
|
flopenrc #(`XLEN) MWRegInt(clk, reset, FlushW, ~StallW, FCvtIntResM, FCvtIntResW);
|
2021-12-20 00:53:41 +00:00
|
|
|
|
|
|
|
// BEGIN WRITEBACK STAGE
|
|
|
|
|
2022-06-13 22:47:51 +00:00
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// ||| |||
|
|
|
|
// ||| |||
|
|
|
|
// ||| ||| |||
|
|
|
|
// ||| ||||| |||
|
|
|
|
// ||| ||| ||| |||
|
|
|
|
// |||||| ||||||
|
|
|
|
// ||| |||
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2021-12-20 00:53:41 +00:00
|
|
|
// select the result to be written to the FP register
|
2022-06-20 22:53:13 +00:00
|
|
|
mux2 #(`FLEN) FPUResultMux (FpResW, ReadDataW, FResSelW[1], FPUResultW);
|
2022-06-13 22:47:51 +00:00
|
|
|
|
2021-06-01 19:45:32 +00:00
|
|
|
endmodule // fpu
|