mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-06-27 17:01:20 -04:00
Merge branch 'openhwgroup:main' into main
This commit is contained in:
commit
8369e8679e
180 changed files with 443 additions and 443 deletions
6
src/cache/cachefsm.sv
vendored
6
src/cache/cachefsm.sv
vendored
|
@ -62,7 +62,7 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
|
|||
output logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||
output logic SelWriteback, // Overrides cached tag check to select a specific way and set for writeback
|
||||
output logic LRUWriteEn, // Update the LRU state
|
||||
output logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
output logic SelVictim, // Overrides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
output logic FlushAdrCntEn, // Enable the counter for Flush Adr
|
||||
output logic FlushWayCntEn, // Enable the way counter during a flush
|
||||
output logic FlushCntRst, // Reset both flush counters
|
||||
|
@ -83,7 +83,7 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
|
|||
STATE_FETCH,
|
||||
STATE_WRITEBACK,
|
||||
STATE_WRITE_LINE,
|
||||
STATE_ADDRESS_SETUP, // required for back to back reads. structural hazard on writting SRAM
|
||||
STATE_ADDRESS_SETUP, // required for back to back reads. structural hazard on writing SRAM
|
||||
// flush cache
|
||||
STATE_FLUSH,
|
||||
STATE_FLUSH_WRITEBACK
|
||||
|
@ -165,7 +165,7 @@ module cachefsm #(parameter READ_ONLY_CACHE = 0) (
|
|||
(CurrState == STATE_WRITE_LINE & (CacheRW[0])) |
|
||||
(CurrState == STATE_WRITEBACK & (CMOpM[3] & CacheBusAck));
|
||||
assign ClearDirty = (CurrState == STATE_WRITE_LINE & ~(CacheRW[0])) | // exclusion-tag: icache ClearDirty
|
||||
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocal. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
|
||||
(CurrState == STATE_FLUSH & LineDirty) | // This is wrong in a multicore snoop cache protocol. Dirty must be cleared concurrently and atomically with writeback. For single core cannot clear after writeback on bus ack and change flushadr. Clears the wrong set.
|
||||
// Flush and eviction controls
|
||||
CurrState == STATE_WRITEBACK & (CMOpM[1] | CMOpM[2]) & CacheBusAck;
|
||||
assign SelVictim = (CurrState == STATE_WRITEBACK & ((~CacheBusAck & ~(CMOpM[1] | CMOpM[2])) | (CacheBusAck & CMOpM[3]))) |
|
||||
|
|
2
src/cache/cacheway.sv
vendored
2
src/cache/cacheway.sv
vendored
|
@ -42,7 +42,7 @@ module cacheway import cvw::*; #(parameter cvw_t P,
|
|||
input logic SetValid, // Set the valid bit in the selected way and set
|
||||
input logic ClearValid, // Clear the valid bit in the selected way and set
|
||||
input logic SetDirty, // Set the dirty bit in the selected way and set
|
||||
input logic SelVictim, // Overides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
input logic SelVictim, // Overrides HitWay Tag matching. Selects selects the victim tag/data regardless of hit
|
||||
input logic ClearDirty, // Clear the dirty bit in the selected way and set
|
||||
input logic FlushCache, // [0] Use SelAdr, [1] SRAM reads/writes from FlushAdr
|
||||
input logic VictimWay, // LRU selected this way as victim to evict
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Usiing global `define statements isn't ideal in a large SystemVerilog system because
|
||||
// Using global `define statements isn't ideal in a large SystemVerilog system because
|
||||
// of the risk of `define name conflicts across different subsystems.
|
||||
// Instead, CORE-V-Wally loads the appropriate configuration one time and places it in a package
|
||||
// that is referenced by all Wally modules but not by other subsystems.
|
||||
|
|
|
@ -53,7 +53,7 @@ module ahbcacheinterface import cvw::*; #(
|
|||
input logic [P.PA_BITS-1:0] CacheBusAdr, // Address of cache line
|
||||
input logic [P.LLEN-1:0] CacheReadDataWordM, // One word of cache line during a writeback
|
||||
input logic CacheableOrFlushCacheM, // Memory operation is cacheable or flushing D$
|
||||
input logic Cacheable, // Memory operation is cachable
|
||||
input logic Cacheable, // Memory operation is cacheable
|
||||
input logic [1:0] CacheBusRW, // Cache bus operation, 01: writeback, 10: fetch
|
||||
output logic CacheBusAck, // Handshake to $ indicating bus transaction completed
|
||||
output logic [LINELEN-1:0] FetchBuffer, // Register to hold beats of cache line as the arrive from bus
|
||||
|
|
|
@ -91,7 +91,7 @@ module ebu import cvw::*; #(parameter cvw_t P) (
|
|||
assign HRESETn = ~reset;
|
||||
|
||||
// if two requests come in at once pick one to select and save the others Address phase
|
||||
// inputs. Abritration scheme is LSU always goes first.
|
||||
// inputs. Arbitration scheme is LSU always goes first.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// input stages and muxing for IFU and LSU
|
||||
|
|
|
@ -59,7 +59,7 @@ module ebufsmarb (
|
|||
logic [3:0] Threshold; // Number of beats derived from HBURST
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Aribtration scheme
|
||||
// Arbitration scheme
|
||||
// FSM decides if arbitration needed. Arbitration is held until the last beat of
|
||||
// a burst is completed.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -87,7 +87,7 @@ module ebufsmarb (
|
|||
// Once the LSU request is done the fsm returns to IDLE. To prevent the LSU from regaining
|
||||
// priority and re-issuing the same memory operation, the delayed IFUReqDelay squashes the LSU request.
|
||||
// This is necessary because the pipeline is stalled for the entire duration of both transactions,
|
||||
// and the LSU memory request will stil be active.
|
||||
// and the LSU memory request will still be active.
|
||||
flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqDelay);
|
||||
assign LSUDisable = (CurrState == ARBITRATE) ? 1'b0 : (IFUReqDelay & ~(HREADY & FinalBeatD));
|
||||
assign LSUSelect = (NextState == ARBITRATE) ? 1'b1: LSUReq;
|
||||
|
|
|
@ -60,8 +60,8 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||
// register control signals
|
||||
output logic FRegWriteE, FRegWriteM, FRegWriteW, // FP register write enable
|
||||
output logic FWriteIntE, FWriteIntM, // Write to integer register
|
||||
output logic [4:0] Adr1D, Adr2D, Adr3D, // adresses of each input
|
||||
output logic [4:0] Adr1E, Adr2E, Adr3E, // adresses of each input
|
||||
output logic [4:0] Adr1D, Adr2D, Adr3D, // addresses of each input
|
||||
output logic [4:0] Adr1E, Adr2E, Adr3E, // addresses of each input
|
||||
// other control signals
|
||||
output logic IllegalFPUInstrD, // Is the instruction an illegal fpu instruction
|
||||
output logic FDivStartE, IDivStartE // Start division or squareroot
|
||||
|
@ -355,12 +355,12 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||
// 01 - negate sign
|
||||
// 10 - xor sign
|
||||
|
||||
// rename input adresses for readability
|
||||
// rename input addresses for readability
|
||||
assign Adr1D = InstrD[19:15];
|
||||
assign Adr2D = InstrD[24:20];
|
||||
assign Adr3D = InstrD[31:27];
|
||||
|
||||
// D/E pipleine register
|
||||
// D/E pipeline register
|
||||
flopenrc #(`FCTRLW+2+P.FMTBITS) DECtrlReg3(clk, reset, FlushE, ~StallE,
|
||||
{FRegWriteD, PostProcSelD, FResSelD, FrmD, FmtD, OpCtrlD, FWriteIntD, FCvtIntD, ZfaD, ZfaFRoundNXD, ~IllegalFPUInstrD},
|
||||
{FRegWriteE, PostProcSelE, FResSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE, ZfaE, ZfaFRoundNXE, FPUActiveE});
|
||||
|
@ -372,7 +372,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||
if (P.M_SUPPORTED & P.IDIV_ON_FPU) assign IDivStartE = IntDivE;
|
||||
else assign IDivStartE = 1'b0;
|
||||
|
||||
// E/M pipleine register
|
||||
// E/M pipeline register
|
||||
flopenrc #(14+int'(P.FMTBITS)) EMCtrlReg (clk, reset, FlushM, ~StallM,
|
||||
{FRegWriteE, FResSelE, PostProcSelE, FrmE, FmtE, OpCtrlE, FWriteIntE, FCvtIntE, ZfaE},
|
||||
{FRegWriteM, FResSelM, PostProcSelM, FrmM, FmtM, OpCtrlM, FWriteIntM, FCvtIntM, ZfaM});
|
||||
|
@ -380,7 +380,7 @@ module fctrl import cvw::*; #(parameter cvw_t P) (
|
|||
// renameing for readability
|
||||
assign FpLoadStoreM = FResSelM[1];
|
||||
|
||||
// M/W pipleine register
|
||||
// M/W pipeline register
|
||||
flopenrc #(4) MWCtrlReg(clk, reset, FlushW, ~StallW,
|
||||
{FRegWriteM, FResSelM, FCvtIntM},
|
||||
{FRegWriteW, FResSelW, FCvtIntW});
|
||||
|
|
|
@ -32,10 +32,10 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [P.NF:0] Xm, // input's fraction
|
||||
input logic [P.XLEN-1:0] Int, // integer input - from IEU
|
||||
input logic [2:0] OpCtrl, // choose which operation (look below for values)
|
||||
input logic ToInt, // is fp->int (since it's writting to the integer register)
|
||||
input logic ToInt, // is fp->int (since it's writing to the integer register)
|
||||
input logic XZero, // is the input zero
|
||||
input logic [P.FMTBITS-1:0] Fmt, // the input's precision (11=quad 01=double 00=single 10=half)
|
||||
output logic [P.NE:0] Ce, // the calculated expoent
|
||||
output logic [P.NE:0] Ce, // the calculated exponent
|
||||
output logic [P.LOGCVTLEN-1:0] ShiftAmt, // how much to shift by
|
||||
output logic ResSubnormUf, // does the result underflow or is subnormal
|
||||
output logic Cs, // the result's sign
|
||||
|
@ -64,7 +64,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||
logic [P.CVTLEN:0] LzcInFull; // input to the Leading Zero Counter (priority encoder)
|
||||
logic [P.LOGCVTLEN-1:0] LeadingZeros; // output from the LZC
|
||||
|
||||
// seperate OpCtrl for code readability
|
||||
// separate OpCtrl for code readability
|
||||
assign Signed = OpCtrl[0];
|
||||
assign Int64 = OpCtrl[1];
|
||||
assign IntToFp = OpCtrl[2];
|
||||
|
@ -80,7 +80,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||
///////////////////////////////////////////////////////////////////////////
|
||||
// negation
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// 1) negate the input if the input is a negative singed integer
|
||||
// 1) negate the input if the input is a negative signed integer
|
||||
// 2) trim the input to the proper size (kill the 32 most significant zeroes if needed)
|
||||
|
||||
assign PosInt = Cs ? -Int : Int;
|
||||
|
@ -150,20 +150,20 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||
// - XExp - Largest bias + new bias - (LeadingZeros+1)
|
||||
// only do ^ if the input was subnormal
|
||||
// - convert the expoenent to the final preciaion (Exp - oldBias + newBias)
|
||||
// - correct the expoent when there is a normalization shift ( + LeadingZeros+1)
|
||||
// - correct the exponent when there is a normalization shift ( + LeadingZeros+1)
|
||||
// - the plus 1 is built into the leading zeros by counting the leading zeroes in the mantissa rather than the fraction
|
||||
// fp -> int : XExp - Largest Bias + 1 - (LeadingZeros+1)
|
||||
// | P.XLEN zeros | Mantissa | 0's if nessisary | << CalcExp
|
||||
// | P.XLEN zeros | Mantissa | 0's if necessary | << CalcExp
|
||||
// process:
|
||||
// - start
|
||||
// | P.XLEN zeros | Mantissa | 0's if nessisary |
|
||||
// | P.XLEN zeros | Mantissa | 0's if necessary |
|
||||
//
|
||||
// - shift left 1 (1)
|
||||
// | P.XLEN-1 zeros |bit| frac | 0's if nessisary |
|
||||
// | P.XLEN-1 zeros |bit| frac | 0's if necessary |
|
||||
// . <- binary point
|
||||
//
|
||||
// - shift left till unbiased exponent is 0 (XExp - Largest Bias)
|
||||
// | 0's | Mantissa | 0's if nessisary |
|
||||
// | 0's | Mantissa | 0's if necessary |
|
||||
// | keep |
|
||||
//
|
||||
// - if the input is subnormal then we dont shift... so the "- LeadingZeros" is just leftovers from other options
|
||||
|
@ -199,7 +199,7 @@ module fcvt import cvw::*; #(parameter cvw_t P) (
|
|||
// - shift left by NF-1+CalcExp - to shift till the biased expoenent is 0
|
||||
// ??? -> fp:
|
||||
// - shift left by LeadingZeros - to shift till the result is normalized
|
||||
// - only shift fp -> fp if the intital value is subnormal
|
||||
// - only shift fp -> fp if the initial value is subnormal
|
||||
// - this is a problem because the input to the lzc was the fraction rather than the mantissa
|
||||
// - rather have a few and-gates than an extra bit in the priority encoder???
|
||||
always_comb
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Written: David_Harris@hmc.edu, me@KatherineParry.com, cturek@hmc.edu
|
||||
// Modified:13 January 2022
|
||||
//
|
||||
// Purpose: Exponent caclulation for divide and square root
|
||||
// Purpose: Exponent calculation for divide and square root
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design
|
||||
//
|
||||
|
|
|
@ -88,7 +88,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
|||
assign AsE = AE[P.XLEN-1] & SignedDivE;
|
||||
assign BsE = BE[P.XLEN-1] & SignedDivE;
|
||||
|
||||
// Force integer inputs to be postiive
|
||||
// Force integer inputs to be positive
|
||||
mux2 #(P.XLEN) posamux(AE, -AE, AsE, PosA);
|
||||
mux2 #(P.XLEN) posbmux(BE, -BE, BsE, PosB);
|
||||
|
||||
|
@ -165,7 +165,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
|||
// Then multiply by R is left shift by r (1 or 2 for radix 2 or 4)
|
||||
// This is optimized in hardware by first right shifting by 0 or 1 bit (instead of 1 or 2), then left shifting by (r-1), then subtracting 2 or 4
|
||||
// Subtracting 2 is equivalent to adding 1110. Subtracting 4 is equivalent to adding 1100. Prepend leading 1s to do a free subtraction.
|
||||
// This also means only one extra fractional bit is needed becaue we never shift right by more than 1.
|
||||
// This also means only one extra fractional bit is needed because we never shift right by more than 1.
|
||||
// Radix Exponent odd Exponent Even
|
||||
// 2 x-2 = 2(x/2 - 1) x/2 - 2 = 2(x/4 - 1)
|
||||
// 4 2(x)-4 = 4(x/2 - 1)) 2(x/2)-4 = 4(x/4 - 1)
|
||||
|
@ -194,7 +194,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
|||
mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Selet integer or floating-point operands
|
||||
// Select integer or floating-point operands
|
||||
//////////////////////////////////////////////////////
|
||||
|
||||
if (P.IDIV_ON_FPU) begin
|
||||
|
@ -203,7 +203,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
|||
assign X = PreShiftX;
|
||||
end
|
||||
|
||||
// Divisior register
|
||||
// Divisor register
|
||||
flopen #(P.DIVb+4) dreg(clk, IFDivStartE, {3'b000, Dnorm}, D);
|
||||
|
||||
// Floating-point exponent
|
||||
|
|
|
@ -28,10 +28,10 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module fhazard(
|
||||
input logic [4:0] Adr1D, Adr2D, Adr3D, // read data adresses
|
||||
input logic [4:0] Adr1E, Adr2E, Adr3E, // read data adresses
|
||||
input logic [4:0] Adr1D, Adr2D, Adr3D, // read data addresses
|
||||
input logic [4:0] Adr1E, Adr2E, Adr3E, // read data addresses
|
||||
input logic FRegWriteE, FRegWriteM, FRegWriteW, // is the fp register being written to
|
||||
input logic [4:0] RdE, RdM, RdW, // the adress being written to
|
||||
input logic [4:0] RdE, RdM, RdW, // the address being written to
|
||||
input logic [1:0] FResSelM, // the result being selected
|
||||
input logic XEnD, YEnD, ZEnD, // are the inputs needed
|
||||
output logic FPUStallD, // stall the decode stage
|
||||
|
|
|
@ -31,11 +31,11 @@ module fmaadd import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [3*P.NF+5:0] Am, // aligned addend's mantissa for addition in U(NF+5.2NF+1)
|
||||
input logic [P.NE-1:0] Ze, // exponent of Z
|
||||
input logic Ps, // the product sign and the alligend addeded's sign (Modified Z sign for other operations)
|
||||
input logic [P.NE+1:0] Pe, // product's exponet
|
||||
input logic [P.NE+1:0] Pe, // product's exponent
|
||||
input logic [2*P.NF+1:0] Pm, // the product's mantissa
|
||||
input logic InvA, // invert the aligned addend
|
||||
input logic KillProd, // should the product be set to 0
|
||||
input logic ASticky, // Alighed addend's sticky bit
|
||||
input logic ASticky, // Aligned addend's sticky bit
|
||||
output logic [3*P.NF+5:0] AmInv, // aligned addend possibly inverted
|
||||
output logic [2*P.NF+1:0] PmKilled, // the product's mantissa possibly killed
|
||||
output logic Ss, // sum's sign
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Written: 6/23/2021 me@KatherineParry.com, David_Harris@hmc.edu
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: FMA alginment shift
|
||||
// Purpose: FMA alignment shift
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design
|
||||
//
|
||||
|
@ -32,7 +32,7 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [P.NF:0] Zm, // significand in U(0.NF) format]
|
||||
input logic XZero, YZero, ZZero, // is the input zero
|
||||
output logic [P.FMALEN-1:0] Am, // addend aligned for addition in U(NF+5.2NF+1)
|
||||
output logic ASticky, // Sticky bit calculated from the aliged addend
|
||||
output logic ASticky, // Sticky bit calculated from the aligned addend
|
||||
output logic KillProd // should the product be set to zero
|
||||
);
|
||||
|
||||
|
@ -51,7 +51,7 @@ module fmaalign import cvw::*; #(parameter cvw_t P) (
|
|||
// This could have been done using Pe, but ACnt is on the critical path so we replicate logic for speed
|
||||
assign ACnt = {2'b0, Xe} + {2'b0, Ye} - {2'b0, (P.NE)'(P.BIAS)} + (P.NE+2)'(P.NF+3) - {2'b0, Ze};
|
||||
|
||||
// Default Addition with only inital left shift
|
||||
// Default Addition with only initial left shift
|
||||
// extra bit at end and beginning so the correct guard bit is calculated when subtracting
|
||||
// | 54'b0 | 106'b(product) | 2'b0 |
|
||||
// | addnend |
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module fmasign(
|
||||
input logic [2:0] OpCtrl, // operation contol
|
||||
input logic [2:0] OpCtrl, // operation control
|
||||
input logic Xs, Ys, Zs, // sign of the inputs
|
||||
output logic Ps, // the product's sign - takes operation into account
|
||||
output logic As, // aligned addend sign used in fma - takes operation into account
|
||||
|
|
|
@ -78,8 +78,8 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||
logic [2:0] OpCtrlE, OpCtrlM; // Select which operation to do in each component
|
||||
logic [1:0] FResSelE, FResSelM, FResSelW; // 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] Adr1D, Adr2D, Adr3D; // register adresses of each input
|
||||
logic [4:0] Adr1E, Adr2E, Adr3E; // register adresses of each input
|
||||
logic [4:0] Adr1D, Adr2D, Adr3D; // register addresses of each input
|
||||
logic [4:0] Adr1E, Adr2E, Adr3E; // register addresses of each input
|
||||
logic XEnD, YEnD, ZEnD; // X, Y, Z inputs used for current operation
|
||||
logic XEnE, YEnE, ZEnE; // X, Y, Z inputs used for current operation
|
||||
logic FRegWriteE; // Write floating-point register
|
||||
|
@ -129,7 +129,7 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
|||
logic [$clog2(P.FMALEN+1)-1:0] SCntE, SCntM; // LZA sum leading zero count
|
||||
|
||||
// Cvt Signals
|
||||
logic [P.NE:0] CeE, CeM; // convert intermediate expoent
|
||||
logic [P.NE:0] CeE, CeM; // convert intermediate exponent
|
||||
logic [P.LOGCVTLEN-1:0] CvtShiftAmtE, CvtShiftAmtM; // how much to shift by
|
||||
logic CvtResSubnormUfE, CvtResSubnormUfM; // does the result underflow or is subnormal
|
||||
logic CsE, CsM; // convert result sign
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
module fregfile #(parameter FLEN) (
|
||||
input logic clk, reset,
|
||||
input logic we4, // write enable
|
||||
input logic [4:0] a1, a2, a3, a4, // adresses
|
||||
input logic [4:0] a1, a2, a3, a4, // addresses
|
||||
input logic [FLEN-1:0] wd4, // write data
|
||||
output logic [FLEN-1:0] rd1, rd2, rd3 // read data
|
||||
);
|
||||
|
|
|
@ -30,12 +30,12 @@
|
|||
module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic XZero, // is the input zero?
|
||||
input logic ToInt, // to integer conversion?
|
||||
input logic IntToFp, // interger to floating point conversion?
|
||||
input logic IntToFp, // integer to floating point conversion?
|
||||
input logic [P.FMTBITS-1:0] OutFmt, // output format
|
||||
input logic [P.NE:0] CvtCe, // the calculated expoent
|
||||
input logic [P.NE:0] CvtCe, // the calculated exponent
|
||||
input logic [P.NF:0] Xm, // input mantissas
|
||||
input logic [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
|
||||
input logic CvtResSubnormUf, // is the conversion result subnormal or underlows
|
||||
input logic CvtResSubnormUf, // is the conversion result subnormal or underflows
|
||||
output logic CvtResUf, // does the cvt result unerflow
|
||||
output logic [P.CVTLEN+P.NF:0] CvtShiftIn // number to be shifted
|
||||
);
|
||||
|
@ -51,12 +51,12 @@ module cvtshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||
// | P.XLEN zeros | mantissa | 0's if necessary |
|
||||
// .
|
||||
// Other problems:
|
||||
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later durring rounding)
|
||||
// - if shifting to the right (neg CalcExp) then don't a 1 in the round bit (to prevent an incorrect plus 1 later during rounding)
|
||||
// - we do however want to keep the one in the sticky bit so set one of bits in the sticky bit area to 1
|
||||
// - ex: for the case 0010000.... (double)
|
||||
// ??? -> fp:
|
||||
// - if result is subnormal or underflowed then we want to shift right i.e. shift right then shift left:
|
||||
// | P.NF-1 zeros | mantissa | 0's if nessisary |
|
||||
// | P.NF-1 zeros | mantissa | 0's if necessary |
|
||||
// .
|
||||
// - otherwise:
|
||||
// | LzcInM | 0's if necessary |
|
||||
|
|
|
@ -57,8 +57,8 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||
// 00000000.xxxxxxx... << NF Exp = DivUe+1
|
||||
// 00000000x.xxxxxx... << NF Exp = DivUe (extra shift done afterwards)
|
||||
// 00000000xx.xxxxx... << 1? Exp = DivUe-1 (determined after)
|
||||
// inital Left shift amount = NF
|
||||
// shift one more if the it's a minimally redundent radix 4 - one entire cycle needed for integer bit
|
||||
// initial Left shift amount = NF
|
||||
// shift one more if the it's a minimally redundant radix 4 - one entire cycle needed for integer bit
|
||||
assign NormShift = (P.LOGNORMSHIFTSZ)'(P.NF);
|
||||
|
||||
// if the shift amount is negative then don't shift (keep sticky bit)
|
||||
|
|
|
@ -47,7 +47,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
input logic IntToFp, // convert integer to floating point
|
||||
input logic Int64, // convert to 64 bit integer
|
||||
input logic Signed, // convert to a signed integer
|
||||
input logic [P.NE:0] CvtCe, // the calculated expoent - Cvt
|
||||
input logic [P.NE:0] CvtCe, // the calculated exponent - Cvt
|
||||
input logic [1:0] CvtNegResMsbs, // the negative integer result's most significant bits
|
||||
// divsqrt
|
||||
input logic DivOp, // conversion operation?
|
||||
|
@ -70,7 +70,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
logic FmaInvalid; // integer invalid flag
|
||||
logic DivInvalid; // integer invalid flag
|
||||
logic Underflow; // Underflow flag
|
||||
logic ResExpGteMax; // is the result greater than or equal to the maximum floating point expoent
|
||||
logic ResExpGteMax; // is the result greater than or equal to the maximum floating point exponent
|
||||
logic ShiftGtIntSz; // is the shift greater than the the integer size (use Re to account for possible rounding "shift")
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -81,7 +81,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
// the shift amount is greater than the integers size (for cvt to int)
|
||||
// ShiftGtIntSz calculation:
|
||||
// a left shift of intlen+1 is still in range but any more than that is an overflow
|
||||
// inital: | 64 0's | XLEN |
|
||||
// initial: | 64 0's | XLEN |
|
||||
// | 64 0's | XLEN | << 64
|
||||
// | XLEN | 00000... |
|
||||
// 65 = ...0 0 0 0 0 1 0 0 0 0 0 1
|
||||
|
@ -89,8 +89,8 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
// 33 = ...0 0 0 0 0 0 1 0 0 0 0 1
|
||||
// | or | | or |
|
||||
// larger or equal if:
|
||||
// - any of the bits after the most significan 1 is one
|
||||
// - the most signifcant in 65 or 33 is still a one in the number and
|
||||
// - any of the bits after the most significant 1 is one
|
||||
// - the most significant in 65 or 33 is still a one in the number and
|
||||
// one of the later bits is one
|
||||
if (P.FPSIZES == 1) begin
|
||||
assign ResExpGteMax = &FullRe[P.NE-1:0] | FullRe[P.NE];
|
||||
|
@ -121,7 +121,7 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
assign ShiftGtIntSz = (|FullRe[P.Q_NE:7]|(FullRe[6]&~Int64)) | ((|FullRe[4:0]|(FullRe[5]&Int64))&((FullRe[5]&~Int64) | FullRe[6]&Int64));
|
||||
end
|
||||
|
||||
// calulate overflow flag:
|
||||
// calculate overflow flag:
|
||||
// if the result is greater than or equal to the max exponent(not taking into account sign)
|
||||
// | and the exponent isn't negative
|
||||
// | | if the input isnt infinity or NaN
|
||||
|
@ -146,8 +146,8 @@ module flags import cvw::*; #(parameter cvw_t P) (
|
|||
// Inexact
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Set Inexact flag if the result is diffrent from what would be outputed given infinite precision
|
||||
// - Don't set the underflow flag if an underflowed res isn't outputed
|
||||
// Set Inexact flag if the result is different from what would be outputted given infinite precision
|
||||
// - Don't set the underflow flag if an underflowed res isn't outputted
|
||||
assign FpInexact = (Sticky|Guard|Overflow|Round)&~(InfIn|NaNIn|DivByZero|Invalid);
|
||||
|
||||
// if the res is too small to be represented and not 0
|
||||
|
|
|
@ -34,7 +34,7 @@ module fmashiftcalc import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [$clog2(P.FMALEN+1)-1:0] FmaSCnt, // normalization shift count
|
||||
output logic [P.NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results
|
||||
output logic FmaSZero, // is the sum zero
|
||||
output logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
|
||||
output logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA correction
|
||||
output logic [$clog2(P.FMALEN+1)-1:0] FmaShiftAmt // normalization shift count
|
||||
);
|
||||
logic [P.NE+1:0] PreNormSumExp; // the exponent of the normalized sum with the P.FLEN bias
|
||||
|
|
|
@ -56,7 +56,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [P.NE:0] CvtCe, // the calculated exponent
|
||||
input logic CvtResSubnormUf, // the convert result is subnormal or underflows
|
||||
input logic [P.LOGCVTLEN-1:0] CvtShiftAmt, // how much to shift by
|
||||
input logic ToInt, // is fp->int (since it's writting to the integer register)
|
||||
input logic ToInt, // is fp->int (since it's writing to the integer register)
|
||||
input logic Zfa, // Zfa operation (fcvtmod.w.d)
|
||||
input logic [P.CVTLEN-1:0] CvtLzcIn, // input to the Leading Zero Counter (without msb)
|
||||
input logic IntZero, // is the integer input zero
|
||||
|
@ -77,7 +77,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
|||
logic UfPlus1; // do you add one (for determining underflow flag)
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] ShiftAmt; // normalization shift amount
|
||||
logic [P.NORMSHIFTSZ-1:0] ShiftIn; // input to normalization shift
|
||||
logic [P.NORMSHIFTSZ-1:0] Shifted; // the ouput of the normalized shifter (before shift correction)
|
||||
logic [P.NORMSHIFTSZ-1:0] Shifted; // the output of the normalized shifter (before shift correction)
|
||||
logic Plus1; // add one to the final result?
|
||||
logic Overflow; // overflow flag used to select results
|
||||
logic Invalid; // invalid flag used to select results
|
||||
|
@ -87,14 +87,14 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
|||
logic [P.NE+1:0] FmaMe; // exponent of the normalized sum
|
||||
logic FmaSZero; // is the sum zero
|
||||
logic [P.NE+1:0] NormSumExp; // exponent of the normalized sum not taking into account Subnormal or zero results
|
||||
logic FmaPreResultSubnorm; // is the result subnormal - calculated before LZA corection
|
||||
logic FmaPreResultSubnorm; // is the result subnormal - calculated before LZA correction
|
||||
logic [$clog2(P.FMALEN+1)-1:0] FmaShiftAmt; // normalization shift amount for fma
|
||||
// division signals
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount
|
||||
logic [P.NE+1:0] Ue; // divsqrt corrected exponent after corretion shift
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shift amount
|
||||
logic [P.NE+1:0] Ue; // divsqrt corrected exponent after correction shift
|
||||
logic DivByZero; // divide by zero flag
|
||||
logic DivResSubnorm; // is the divsqrt result subnormal
|
||||
logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed)
|
||||
logic DivSubnormShiftPos; // is the divsqrt subnorm shift amount positive (not underflowed)
|
||||
// conversion signals
|
||||
logic [P.CVTLEN+P.NF:0] CvtShiftIn; // number to be shifted for converter
|
||||
logic [1:0] CvtNegResMsbs; // most significant bits of possibly negated int result
|
||||
|
@ -107,7 +107,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
|||
logic Int64; // is the integer 64 bits?
|
||||
logic Signed; // is the operation with a signed integer?
|
||||
logic IntToFp; // is the operation an int->fp conversion?
|
||||
logic CvtOp; // convertion operation
|
||||
logic CvtOp; // conversion operation
|
||||
logic FmaOp; // fma operation
|
||||
logic DivOp; // divider operation
|
||||
logic InfIn; // are any of the inputs infinity
|
||||
|
@ -187,7 +187,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
|||
// round to infinity
|
||||
// round to nearest max magnitude
|
||||
|
||||
// calulate result sign used in rounding unit
|
||||
// calculate result sign used in rounding unit
|
||||
roundsign roundsign(.FmaOp, .DivOp, .CvtOp, .Sqrt, .FmaSs, .Xs, .Ys, .CvtCs, .Ms);
|
||||
|
||||
round #(P) round(.OutFmt, .Frm, .FmaASticky, .Plus1, .PostProcSel, .CvtCe, .Ue,
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
module resultsign(
|
||||
input logic [2:0] Frm, // rounding mode
|
||||
input logic FmaOp, // is the operation an Fma
|
||||
input logic Mult, // is the fma operation multipy
|
||||
input logic Mult, // is the fma operation multiply
|
||||
input logic ZInf, // is Z infinity
|
||||
input logic InfIn, // are any of the inputs infinity
|
||||
input logic FmaSZero, // is the fma sum zero
|
||||
|
@ -48,12 +48,12 @@ module resultsign(
|
|||
|
||||
// determine the sign for a result of 0
|
||||
// The IEEE754-2019 standard specifies:
|
||||
// - the sign of an exact zero sum (with operands of diffrent signs) should be positive unless rounding toward negative infinity
|
||||
// - the sign of an exact zero sum (with operands of different signs) should be positive unless rounding toward negative infinity
|
||||
// - when the exact result of an FMA operation is non-zero, but is zero due to rounding, use the sign of the exact result
|
||||
// - if x = +0 or -0 then x+x=x and x-(-x)=x
|
||||
// - the sign of a product is the exclisive or or the opperand's signs
|
||||
// Zero sign will only be selected if:
|
||||
// - P=Z and a cancelation occurs - exact zero
|
||||
// - P=Z and a cancellation occurs - exact zero
|
||||
// - Z is zero and P is zero - exact zero
|
||||
// - P is killed and Z is zero - Psgn
|
||||
// - Z is killed and P is zero - impossible
|
||||
|
|
|
@ -40,13 +40,13 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||
// divsqrt
|
||||
input logic DivOp, // is a division operation being done
|
||||
input logic DivSticky, // divsqrt sticky bit
|
||||
input logic [P.NE+1:0] Ue, // the divsqrt calculated expoent
|
||||
input logic [P.NE+1:0] Ue, // the divsqrt calculated exponent
|
||||
// cvt
|
||||
input logic CvtOp, // is a convert operation being done
|
||||
input logic ToInt, // is the cvt op a cvt to integer
|
||||
input logic CvtResSubnormUf, // is the cvt result subnormal or underflow
|
||||
input logic CvtResUf, // does the cvt result underflow
|
||||
input logic [P.NE:0] CvtCe, // the cvt calculated expoent
|
||||
input logic [P.NE:0] CvtCe, // the cvt calculated exponent
|
||||
// outputs
|
||||
output logic [P.NE+1:0] Me, // normalied fraction
|
||||
output logic UfPlus1, // do you add one to the result if given an unbounded exponent
|
||||
|
@ -172,7 +172,7 @@ module round import cvw::*; #(parameter cvw_t P) (
|
|||
(|Mf[P.NORMSHIFTSZ-P.XLEN-2:P.NORMSHIFTSZ-P.Q_NF-1]&(~(OutFmt==P.Q_FMT)|IntRes)) |
|
||||
(|Mf[P.NORMSHIFTSZ-P.Q_NF-2:0]);
|
||||
// 3: NF > NF1 > XLEN
|
||||
// The extra XLEN bit will be ored later when caculating the final sticky bit - the ufplus1 not needed for integer
|
||||
// The extra XLEN bit will be ored later when calculating the final sticky bit - the ufplus1 not needed for integer
|
||||
if (XLENPOS == 3) assign NormSticky = (|Mf[P.NORMSHIFTSZ-P.H_NF-2:P.NORMSHIFTSZ-P.S_NF-1]&FpRes&(OutFmt==P.H_FMT)) |
|
||||
(|Mf[P.NORMSHIFTSZ-P.S_NF-2:P.NORMSHIFTSZ-P.XLEN-1]&FpRes&((OutFmt==P.S_FMT)|(OutFmt==P.H_FMT))) |
|
||||
(|Mf[P.NORMSHIFTSZ-P.XLEN-2:P.NORMSHIFTSZ-P.D_NF-1]&((OutFmt==P.S_FMT)|(OutFmt==P.H_FMT)|IntRes)) |
|
||||
|
|
|
@ -44,7 +44,7 @@ module roundsign(
|
|||
// calculate divsqrt sign
|
||||
assign Qs = Xs^(Ys&~Sqrt);
|
||||
|
||||
// Select sign for rounding calulation
|
||||
// Select sign for rounding calculation
|
||||
assign Ms = (FmaSs&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp);
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -37,7 +37,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
|||
//fma
|
||||
input logic FmaOp, // is it an fma operation
|
||||
input logic [P.NE+1:0] NormSumExp, // exponent of the normalized sum not taking into account Subnormal or zero results
|
||||
input logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA corection
|
||||
input logic FmaPreResultSubnorm, // is the result subnormal - calculated before LZA correction
|
||||
input logic FmaSZero,
|
||||
// output
|
||||
output logic [P.NE+1:0] FmaMe, // exponent of the normalized sum
|
||||
|
@ -61,10 +61,10 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
|||
assign LZAPlus1 = Shifted[P.NORMSHIFTSZ-1];
|
||||
|
||||
// correct the shifting of the divsqrt caused by producing a result in (0.5, 2) range
|
||||
// condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm)
|
||||
// condition: if the msb is 1 or the exponent was one, but the shifted quotient was < 1 (Subnorm)
|
||||
assign LeftShiftQm = (LZAPlus1|(DivUe==1&~LZAPlus1));
|
||||
|
||||
// Determine the shif for either FMA or divsqrt
|
||||
// Determine the shift for either FMA or divsqrt
|
||||
assign RightShift = FmaOp ? LZAPlus1 : LeftShiftQm;
|
||||
|
||||
// possible one bit right shift for FMA or division
|
||||
|
@ -79,8 +79,8 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
|||
// main exponent issues:
|
||||
// - LZA was one too large
|
||||
// - LZA was two too large
|
||||
// - if the result was calulated to be subnorm but it's norm and the LZA was off by 1
|
||||
// - if the result was calulated to be subnorm but it's norm and the LZA was off by 2
|
||||
// - if the result was calculated to be subnorm but it's norm and the LZA was off by 1
|
||||
// - if the result was calculated to be subnorm but it's norm and the LZA was off by 2
|
||||
// if plus1 If plus2 kill if the result Zero or actually subnormal
|
||||
// | | |
|
||||
assign FmaMe = (NormSumExp+{{P.NE+1{1'b0}}, LZAPlus1} +{{P.NE+1{1'b0}}, FmaPreResultSubnorm}) & {P.NE+2{~(FmaSZero|ResSubnorm)}};
|
||||
|
@ -88,8 +88,8 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
|||
// recalculate if the result is subnormal after LZA correction
|
||||
assign ResSubnorm = FmaPreResultSubnorm&~Shifted[P.NORMSHIFTSZ-2]&~Shifted[P.NORMSHIFTSZ-1];
|
||||
|
||||
// the quotent is in the range (.5,2) if there is no early termination
|
||||
// if the quotent < 1 and not Subnormal then subtract 1 to account for the normalization shift
|
||||
// the quotient is in the range (.5,2) if there is no early termination
|
||||
// if the quotient < 1 and not Subnormal then subtract 1 to account for the normalization shift
|
||||
assign Ue = (DivResSubnorm & DivSubnormShiftPos) ? 0 : DivUe - {(P.NE+1)'(0), ~LZAPlus1};
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
|||
input logic Int64, // is the integer 64 bits
|
||||
input logic Signed, // is the integer signed
|
||||
input logic Zfa, // Zfa conversion operation: fcvtmod.w.d
|
||||
input logic [P.NE:0] CvtCe, // the calculated expoent for cvt
|
||||
input logic [P.NE:0] CvtCe, // the calculated exponent for cvt
|
||||
input logic IntInvalid, // integer invalid flag to choose the result
|
||||
input logic CvtResUf, // does the convert result underflow
|
||||
input logic [P.XLEN+1:0] CvtNegRes, // the possibly negated of the integer result
|
||||
|
@ -240,7 +240,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
|||
endcase
|
||||
end
|
||||
|
||||
// determine if you shoould kill the res - Cvt
|
||||
// determine if you should kill the res - Cvt
|
||||
// - do so if the res underflows, is zero (the exp doesnt calculate correctly). or the integer input is 0
|
||||
// - dont set to zero if fp input is zero but not using the fp input
|
||||
// - dont set to zero if int input is zero but not using the int input
|
||||
|
@ -334,7 +334,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
|||
end
|
||||
|
||||
// fcvtmod.w.d logic
|
||||
// fcvtmod.w.d is like fcvt.w.d excep thtat it takes bits [31:0] and sign extends the rest,
|
||||
// fcvtmod.w.d is like fcvt.w.d excep that it takes bits [31:0] and sign extends the rest,
|
||||
// and converts +/-inf and NaN to zero.
|
||||
|
||||
if (P.ZFA_SUPPORTED & P.D_SUPPORTED) // fcvtmod.w.d support
|
||||
|
@ -358,7 +358,7 @@ module specialcase import cvw::*; #(parameter cvw_t P) (
|
|||
// - if the input underflows
|
||||
// - if rounding and signed operation and negative input, output -1
|
||||
// - otherwise output a rounded 0
|
||||
// - otherwise output the normal res (trmined and sign extended if nessisary)
|
||||
// - otherwise output the normal res (trmined and sign extended if necessary)
|
||||
always_comb
|
||||
if(SelCvtOfRes) FCvtIntRes = OfIntRes2;
|
||||
else if(CvtCe[P.NE])
|
||||
|
|
|
@ -88,10 +88,10 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||
end else
|
||||
PostBox = In;
|
||||
|
||||
// choose sign bit depending on format - 1=larger precsion 0=smaller precision
|
||||
// choose sign bit depending on format - 1=larger precision 0=smaller precision
|
||||
assign Sgn = Fmt ? In[P.FLEN-1] : (BadNaNBox ? 0 : In[P.LEN1-1]); // improperly boxed NaNs are treated as positive
|
||||
|
||||
// extract the fraction, add trailing zeroes to the mantissa if nessisary
|
||||
// extract the fraction, add trailing zeroes to the mantissa if necessary
|
||||
assign Frac = Fmt ? In[P.NF-1:0] : {In[P.NF1-1:0], (P.NF-P.NF1)'(0)};
|
||||
|
||||
// is the exponent non-zero
|
||||
|
@ -105,14 +105,14 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||
// dexp = 0bdd dbbb bbbb
|
||||
// also need to take into account possible zero/Subnorm/inf/NaN values
|
||||
|
||||
// extract the exponent, converting the smaller exponent into the larger precision if nessisary
|
||||
// extract the exponent, converting the smaller exponent into the larger precision if necessary
|
||||
// - if the original precision had a Subnormal number convert the exponent value 1
|
||||
assign Exp = Fmt ? {In[P.FLEN-2:P.NF+1], In[P.NF]|~ExpNonZero} : {In[P.LEN1-2], {P.NE-P.NE1{~In[P.LEN1-2]}}, In[P.LEN1-3:P.NF1+1], In[P.NF1]|~ExpNonZero};
|
||||
|
||||
// is the exponent all 1's
|
||||
assign ExpMax = Fmt ? &In[P.FLEN-2:P.NF] : &In[P.LEN1-2:P.NF1];
|
||||
|
||||
end else if (P.FPSIZES == 3) begin // three floating point precsions supported
|
||||
end else if (P.FPSIZES == 3) begin // three floating point precisions supported
|
||||
|
||||
// largest format | larger format | smallest format
|
||||
//---------------------------------------------------
|
||||
|
@ -171,8 +171,8 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||
always_comb
|
||||
case (Fmt)
|
||||
P.FMT: ExpNonZero = |In[P.FLEN-2:P.NF]; // if input is largest precision (P.FLEN - ie quad or double)
|
||||
P.FMT1: ExpNonZero = |In[P.LEN1-2:P.NF1]; // if input is larger precsion (P.LEN1 - double or single)
|
||||
P.FMT2: ExpNonZero = |In[P.LEN2-2:P.NF2]; // if input is smallest precsion (P.LEN2 - single or half)
|
||||
P.FMT1: ExpNonZero = |In[P.LEN1-2:P.NF1]; // if input is larger precision (P.LEN1 - double or single)
|
||||
P.FMT2: ExpNonZero = |In[P.LEN2-2:P.NF2]; // if input is smallest precision (P.LEN2 - single or half)
|
||||
default: ExpNonZero = 1'bx;
|
||||
endcase
|
||||
|
||||
|
@ -269,7 +269,7 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||
// dexp = 0bdd dbbb bbbb
|
||||
// also need to take into account possible zero/Subnorm/inf/NaN values
|
||||
|
||||
// convert the double precsion exponent into quad precsion
|
||||
// convert the double precision exponent into quad precision
|
||||
// 1 is added to the exponent if the input is zero or subnormal
|
||||
always_comb
|
||||
case (Fmt)
|
||||
|
@ -294,7 +294,7 @@ module unpackinput import cvw::*; #(parameter cvw_t P) (
|
|||
assign FracZero = ~|Frac & ~BadNaNBox; // is the fraction zero?
|
||||
assign Man = {ExpNonZero, Frac}; // add the assumed one (or zero if Subnormal or zero) to create the significand
|
||||
assign NaN = ((ExpMax & ~FracZero)|BadNaNBox)&En; // is the input a NaN?
|
||||
assign SNaN = NaN&~Frac[P.NF-1]&~BadNaNBox; // is the input a singnaling NaN?
|
||||
assign SNaN = NaN&~Frac[P.NF-1]&~BadNaNBox; // is the input a signaling NaN?
|
||||
assign Inf = ExpMax & FracZero & En; // is the input infinity?
|
||||
assign Zero = ~ExpNonZero & FracZero; // is the input zero?
|
||||
assign Subnorm = ~ExpNonZero & ~FracZero & ~BadNaNBox; // is the input subnormal
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
///////////////////////////////////////////
|
||||
// ram1p1rwbe_64x22.sv
|
||||
//
|
||||
// Written: james.stine@okstate.edu 2 Feburary 2023
|
||||
// Written: james.stine@okstate.edu 2 February 2023
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: RAM wrapper for instantiating RAM IP
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
//
|
||||
// Written: tfleming@hmc.edu & jtorrey@hmc.edu 7 April 2021
|
||||
// Modified: Teo Ene 15 Apr 2021:
|
||||
// Temporarily removed paramterized priority encoder for non-parameterized one
|
||||
// Temporarily removed parameterized priority encoder for non-parameterized one
|
||||
// To get synthesis working quickly
|
||||
// Kmacsaigoren@hmc.edu 28 May 2021:
|
||||
// Added working version of parameterized priority encoder.
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
// David_Harris@Hmc.edu switched to one-hot output
|
||||
//
|
||||
// Purpose: Priority circuit producing a thermometer code output.
|
||||
// with 1's in all the least signficant bits of the output
|
||||
// with 1's in all the least significant bits of the output
|
||||
// until the column where the least significant 1 occurs in the input.
|
||||
//
|
||||
// Example: msb lsb
|
||||
|
|
|
@ -67,7 +67,7 @@ module hazard (
|
|||
// Trap returns (RetM) also flush the entire pipeline after the RetM (all stages except W) because all the subsequent instructions must be discarded.
|
||||
// Similarly, CSR writes and fences flush all subsequent instructions and refetch them in light of the new operating modes and cache/TLB contents
|
||||
// Branch misprediction is found in the Execute stage and must flush the next two instructions.
|
||||
// However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete
|
||||
// However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divide must still complete
|
||||
// When a WFI is interrupted and causes a trap, it flushes the rest of the pipeline but not the W stage, because the WFI needs to commit
|
||||
assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE;
|
||||
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
|
||||
|
@ -75,7 +75,7 @@ module hazard (
|
|||
assign FlushWCause = TrapM & ~WFIInterruptedM;
|
||||
|
||||
// Stall causes
|
||||
// Most data depenency stalls are identified in the decode stage
|
||||
// Most data dependency stalls are identified in the decode stage
|
||||
// Division stalls in the execute stage
|
||||
// Flushing any stage has priority over the corresponding stage stall.
|
||||
// Even if the register gave clear priority over enable, various FSMs still need to disable the stall, so it's best to gate the stall here with flush
|
||||
|
|
|
@ -37,7 +37,7 @@ module aes64ks1i(
|
|||
logic [31:0] rcon, rs1Rotate;
|
||||
|
||||
rconlut32 rc(round, rcon); // Get rcon value from lookup table
|
||||
assign rs1Rotate = {rs1[39:32], rs1[63:40]}; // Get rotated value fo ruse in tmp2
|
||||
assign rs1Rotate = {rs1[39:32], rs1[63:40]}; // Get rotated value for use in tmp2
|
||||
assign finalround = (round == 4'b1010); // round 10 is the last one
|
||||
assign SboxKIn = finalround ? rs1[63:32] : rs1Rotate; // Don't rotate on the last round
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ module bitmanipalu import cvw::*; #(parameter cvw_t P) (
|
|||
logic [P.XLEN-1:0] MaskB; // BitMask of B
|
||||
logic [P.XLEN-1:0] RevA; // Bit-reversed A
|
||||
logic Mask; // Indicates if it is ZBS instruction
|
||||
logic PreShift; // Inidicates if it is sh1add, sh2add, sh3add instruction
|
||||
logic PreShift; // Indicates if it is sh1add, sh2add, sh3add instruction
|
||||
logic [1:0] PreShiftAmt; // Amount to Pre-Shift A
|
||||
logic [P.XLEN-1:0] CondZextA; // A Conditional Extend Intermediary Signal
|
||||
logic [P.XLEN-1:0] ABMU, BBMU; // Gated data inputs to reduce BMU activity
|
||||
|
|
|
@ -35,8 +35,8 @@ module bmuctrl import cvw::*; #(parameter cvw_t P) (
|
|||
input logic ALUOpD, // Regular ALU Operation
|
||||
output logic BRegWriteD, // Indicates if it is a R type B instruction in Decode Stage
|
||||
output logic BALUSrcBD, // Indicates if it is an I/IW (non auipc) type B instruction in Decode Stage
|
||||
output logic BW64D, // Indiciates if it is a W type B instruction in Decode Stage
|
||||
output logic BUW64D, // Indiciates if it is a .uw type B instruction in Decode Stage
|
||||
output logic BW64D, // Indicates if it is a W type B instruction in Decode Stage
|
||||
output logic BUW64D, // Indicates if it is a .uw type B instruction in Decode Stage
|
||||
output logic BSubArithD, // TRUE if ext, clr, andn, orn, xnor instruction in Decode Stage
|
||||
output logic IllegalBitmanipInstrD, // Indicates if it is unrecognized B instruction in Decode Stage
|
||||
// Execute stage control signals
|
||||
|
|
|
@ -158,7 +158,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
|
|||
logic MatchDE; // Match between a source register in Decode stage and destination register in Execute stage
|
||||
logic FCvtIntStallD, MDUStallD, CSRRdStallD; // Stall due to conversion, load, multiply/divide, CSR read
|
||||
logic FunctCZeroD; // Funct7 and Funct3 indicate czero.* (not including Op check)
|
||||
logic BUW64D; // Indiciates if it is a .uw type B instruction in Decode Stage
|
||||
logic BUW64D; // Indicates if it is a .uw type B instruction in Decode Stage
|
||||
|
||||
// Extract fields
|
||||
assign OpD = InstrD[6:0];
|
||||
|
@ -401,7 +401,7 @@ module controller import cvw::*; #(parameter cvw_t P) (
|
|||
IFUPrefetchD = 1'b0;
|
||||
LSUPrefetchD = 1'b0;
|
||||
ImmSrcD = PreImmSrcD;
|
||||
if (P.ZICBOP_SUPPORTED & (InstrD[14:0] == 15'b110_00000_0010011)) begin // ori with destiation x0 is hint for Prefetch
|
||||
if (P.ZICBOP_SUPPORTED & (InstrD[14:0] == 15'b110_00000_0010011)) begin // ori with destination x0 is hint for Prefetch
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
case (Rs2D) // which type of prefectch? Note: prefetch.r and .w are handled the same in Wally
|
||||
5'b00000: IFUPrefetchD = 1'b1; // prefetch.i
|
||||
|
|
|
@ -60,7 +60,7 @@ module shifter import cvw::*; #(parameter cvw_t P) (
|
|||
if (P.ZBB_SUPPORTED | P.ZBKB_SUPPORTED) begin: rotfunnel64 // rv64 shifter with rotates
|
||||
// shifter rotate source select mux
|
||||
logic [P.XLEN-1:0] RotA; // rotate source
|
||||
mux2 #(P.XLEN) rotmux(A, {A[31:0], A[31:0]}, W64, RotA); // W64 rotatons
|
||||
mux2 #(P.XLEN) rotmux(A, {A[31:0], A[31:0]}, W64, RotA); // W64 rotations
|
||||
always_comb // funnel mux
|
||||
case ({Right, Rotate})
|
||||
2'b00: Z = {A64[63:0],{63'b0}};
|
||||
|
|
|
@ -55,7 +55,7 @@ module bpred import cvw::*; #(parameter cvw_t P) (
|
|||
input logic InstrValidD, InstrValidE,
|
||||
input logic BranchD, BranchE,
|
||||
input logic JumpD, JumpE,
|
||||
input logic PCSrcE, // Executation stage branch is taken
|
||||
input logic PCSrcE, // Execution stage branch is taken
|
||||
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||
input logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
|
@ -188,7 +188,7 @@ module bpred import cvw::*; #(parameter cvw_t P) (
|
|||
mux2 #(P.XLEN) pccorrectemux(PCLinkE, IEUAdrE, PCSrcE, PCCorrectE);
|
||||
|
||||
// If the fence/csrw was predicted as a taken branch then we select PCF, rather than PCE.
|
||||
// Effectively this is PCM+4 or the non-existant PCLinkM
|
||||
// Effectively this is PCM+4 or the non-existent PCLinkM
|
||||
if(`INSTR_CLASS_PRED) mux2 #(P.XLEN) pcmuxBPWrongInvalidateFlush(PCE, PCF, BPWrongM, NextValidPCE);
|
||||
else assign NextValidPCE = PCE;
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Modified: 24 January 2023
|
||||
//
|
||||
// Purpose: Branch Target Buffer (BTB). The BTB predicts the target address of all control flow instructions.
|
||||
// It also guesses the type of instrution; jalr(r), return, jump (jr), or branch.
|
||||
// It also guesses the type of instruction; jalr(r), return, jump (jr), or branch.
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design
|
||||
//
|
||||
|
|
|
@ -49,7 +49,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||
output logic [P.XLEN-1:0] PCSpillF, // PCF with possible + 2 to handle spill to HPTW
|
||||
// Execute
|
||||
output logic [P.XLEN-1:0] PCLinkE, // The address following the branch instruction. (AKA Fall through address)
|
||||
input logic PCSrcE, // Executation stage branch is taken
|
||||
input logic PCSrcE, // Execution stage branch is taken
|
||||
input logic [P.XLEN-1:0] IEUAdrE, // The branch/jump target address
|
||||
input logic [P.XLEN-1:0] IEUAdrM, // The branch/jump target address
|
||||
output logic [P.XLEN-1:0] PCE, // Execution stage instruction address
|
||||
|
@ -79,7 +79,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
|
||||
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
|
||||
// mmu management
|
||||
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
|
||||
input logic [1:0] PrivilegeModeW, // Privilege mode in Writeback stage
|
||||
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
|
||||
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
|
||||
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
|
||||
|
@ -219,7 +219,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// CommittedM tells the CPU's privileged unit the current instruction
|
||||
// in the memory stage is a memory operaton and that memory operation is either completed
|
||||
// in the memory stage is a memory operation and that memory operation is either completed
|
||||
// or is partially executed. Partially completed memory operations need to prevent an interrupts.
|
||||
// There is not a clean way to restore back to a partial executed instruction. CommiteedM will
|
||||
// delay the interrupt until the LSU is in a clean state.
|
||||
|
|
|
@ -40,7 +40,7 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||
logic [31:0] RawIROMInstrF;
|
||||
logic [2:1] AdrD;
|
||||
|
||||
// preload IROM with the FPGA bootloader by default so that it syntehsizes to something, avoiding having the IEU optimized away because instructions are all 0
|
||||
// preload IROM with the FPGA bootloader by default so that it synthesizes to something, avoiding having the IEU optimized away because instructions are all 0
|
||||
// the testbench replaces these dummy contents with the actual program of interest during simulation
|
||||
rom1p1r #(ADDR_WDITH, P.XLEN, 1) rom(.clk, .ce, .addr(Adr[ADDR_WDITH+OFFSET-1:OFFSET]), .dout(IROMInstrFFull));
|
||||
if (P.XLEN == 32) assign RawIROMInstrF = IROMInstrFFull;
|
||||
|
@ -50,7 +50,7 @@ module irom import cvw::*; #(parameter cvw_t P) (
|
|||
flopen #(1) AdrReg2(clk, ce, Adr[2], AdrD[2]);
|
||||
assign RawIROMInstrF = AdrD[2] ? IROMInstrFFull[63:32] : IROMInstrFFull[31:0];
|
||||
end
|
||||
// If the memory addres is aligned to 2 bytes return the upper 2 bytes in the lower 2 bytes.
|
||||
// If the memory address is aligned to 2 bytes return the upper 2 bytes in the lower 2 bytes.
|
||||
// The spill logic will handle merging the two together.
|
||||
if (P.ZCA_SUPPORTED) begin
|
||||
flopen #(1) AdrReg1(clk, ce, Adr[1], AdrD[1]);
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Modified: 26 October 2023
|
||||
//
|
||||
// Purpose: This module implements native alignment support for the Zicclsm extension
|
||||
// It is simlar to the IFU's spill module and probably could be merged together with
|
||||
// It is similar to the IFU's spill module and probably could be merged together with
|
||||
// some effort.
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design
|
||||
|
@ -98,7 +98,7 @@ module align import cvw::*; #(parameter cvw_t P) (
|
|||
// 2) offset
|
||||
// 3) access location within the cacheline
|
||||
|
||||
// compute misalignement
|
||||
// compute misalignment
|
||||
always_comb begin
|
||||
case (Funct3M & {FpLoadStoreM, 2'b11})
|
||||
3'b000: AccessByteOffsetM = '0; // byte access
|
||||
|
|
|
@ -36,7 +36,7 @@ module lrsc import cvw::*; #(parameter cvw_t P) (
|
|||
input logic MemReadM, // Memory read
|
||||
input logic [1:0] PreLSURWM, // Memory operation from the HPTW or IEU [1]: read, [0]: write
|
||||
output logic [1:0] LSURWM, // Memory operation after potential squash of SC
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operaiton
|
||||
input logic [1:0] LSUAtomicM, // Atomic memory operation
|
||||
input logic [P.PA_BITS-1:0] PAdrM, // Physical memory address
|
||||
output logic SquashSCW // Squash the store conditional by not allowing rf write
|
||||
);
|
||||
|
|
|
@ -142,7 +142,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||
|
||||
logic DTLBMissM; // DTLB miss causes HPTW walk
|
||||
logic DTLBWriteM; // Writes PTE and PageType to DTLB
|
||||
logic LSULoadAccessFaultM; // Load acces fault
|
||||
logic LSULoadAccessFaultM; // Load access fault
|
||||
logic LSUStoreAmoAccessFaultM; // Store access fault
|
||||
logic HPTWFlushW; // HPTW needs to flush operation
|
||||
logic LSUFlushW; // HPTW or hazard unit flushes operation
|
||||
|
@ -303,7 +303,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||
logic [P.PA_BITS-1:0] DCacheBusAdr; // Cacheline address to fetch or writeback.
|
||||
logic [AHBWLOGBWPL-1:0] BeatCount; // Position within a cacheline. ahbcacheinterface to cache
|
||||
logic DCacheBusAck; // ahbcacheinterface completed fetch or writeback
|
||||
logic SelBusBeat; // ahbcacheinterface selects postion in cacheline with BeatCount
|
||||
logic SelBusBeat; // ahbcacheinterface selects position in cacheline with BeatCount
|
||||
logic [1:0] CacheBusRW; // Cache sends request to ahbcacheinterface
|
||||
logic [1:0] BusRW; // Uncached bus memory access
|
||||
logic CacheableOrFlushCacheM; // Memory address is cacheable or operation is a cache flush
|
||||
|
@ -353,7 +353,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
|
|||
mux3 #(P.LLEN) UnCachedDataMux(.d0(DCacheReadDataWordSpillM), .d1({LLENPOVERAHBW{FetchBuffer[P.XLEN-1:0]}}),
|
||||
.d2({{P.LLEN-P.XLEN{1'b0}}, DTIMReadDataWordM[P.XLEN-1:0]}),
|
||||
.s({SelDTIM, ~(CacheableOrFlushCacheM)}), .y(ReadDataWordMuxM));
|
||||
end else begin : passthrough // No Cache, use simple ahbinterface instad of ahbcacheinterface
|
||||
end else begin : passthrough // No Cache, use simple ahbinterface instead of ahbcacheinterface
|
||||
logic [1:0] BusRW; // Non-DTIM memory access, ignore cacheableM
|
||||
logic [P.XLEN-1:0] FetchBuffer;
|
||||
assign BusRW = ~SelDTIM ? LSURWM : 0;
|
||||
|
|
|
@ -78,7 +78,7 @@ module div import cvw::*; #(parameter cvw_t P) (
|
|||
assign DinE = ForwardedSrcBE;
|
||||
end
|
||||
|
||||
// Extract sign bits and check fo division by zero
|
||||
// Extract sign bits and check for division by zero
|
||||
assign SignDE = DivSignedE & DinE[P.XLEN-1];
|
||||
assign SignXE = DivSignedE & XinE[P.XLEN-1];
|
||||
assign NegQE = SignDE ^ SignXE;
|
||||
|
|
|
@ -33,7 +33,7 @@ module mdu import cvw::*; #(parameter cvw_t P) (
|
|||
input logic FlushE, FlushM, FlushW,
|
||||
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // inputs A and B from IEU forwarding mux output
|
||||
input logic [2:0] Funct3E, Funct3M, // type of MDU operation
|
||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instrutions
|
||||
input logic IntDivE, W64E, // Integer division/remainder, and W-type instructions
|
||||
input logic MDUActiveE, // Mul/Div instruction being executed
|
||||
output logic [P.XLEN-1:0] MDUResultW, // multiply/divide result
|
||||
output logic DivBusyE // busy signal to stall pipeline in Execute stage
|
||||
|
|
|
@ -200,8 +200,8 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||
assign InvalidOp = DTLBWalk ? (InvalidRead | InvalidWrite) : ~Executable;
|
||||
assign OtherPageFault = ImproperPrivilege | InvalidOp | UpperBitsUnequalD | Misaligned | ~Valid;
|
||||
|
||||
// hptw needs to know if there is a Dirty or Access fault occuring on this
|
||||
// memory access. If there is the PTE needs to be updated seting Access
|
||||
// hptw needs to know if there is a Dirty or Access fault occurring on this
|
||||
// memory access. If there is the PTE needs to be updated setting Access
|
||||
// and possibly also Dirty. Dirty is set if the operation is a store/amo.
|
||||
// However any other fault should not cause the update, and updates are in software when ENVCFG_ADUE = 0
|
||||
assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ENVCFG_ADUE & ~OtherPageFault;
|
||||
|
@ -316,7 +316,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
|
|||
// HTPW address/data/control muxing
|
||||
|
||||
// Once the walk is done and it is time to update the TLB we need to switch back
|
||||
// to the orignal data virtual address.
|
||||
// to the original data virtual address.
|
||||
assign SelHPTWAdr = SelHPTW & ~(DTLBWriteM | ITLBWriteF);
|
||||
|
||||
// multiplex the outputs to LSU
|
||||
|
|
|
@ -47,7 +47,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||
input logic TLBFlush, // Invalidate all TLB entries
|
||||
output logic [P.PA_BITS-1:0] PhysicalAddress, // PAdr when no translation, or translated VAdr (TLBPAdr) when there is translation
|
||||
output logic TLBMiss, // Miss TLB
|
||||
output logic Cacheable, // PMA indicates memory address is cachable
|
||||
output logic Cacheable, // PMA indicates memory address is cacheable
|
||||
output logic Idempotent, // PMA indicates memory address is idempotent
|
||||
output logic SelTIM, // Select a tightly integrated memory
|
||||
// Faults
|
||||
|
@ -105,8 +105,8 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||
assign TLBPAdr = '0;
|
||||
end
|
||||
|
||||
// If translation is occuring, select translated physical address from TLB
|
||||
// the lower 12 bits are the page offset. These are never changed from the orginal
|
||||
// If translation is occurring, select translated physical address from TLB
|
||||
// the lower 12 bits are the page offset. These are never changed from the original
|
||||
// non translated address.
|
||||
mux2 #(P.PA_BITS-12) addressmux(VAdr[P.PA_BITS-1:12], TLBPAdr[P.PA_BITS-1:12], Translate, PhysicalAddress[P.PA_BITS-1:12]);
|
||||
assign PhysicalAddress[11:0] = VAdr[11:0];
|
||||
|
@ -141,7 +141,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
|
|||
2'b10: DataMisalignedM = VAdr[1] | VAdr[0]; // lw, sw, flw, fsw, lwu
|
||||
2'b11: DataMisalignedM = |VAdr[2:0]; // ld, sd, fld, fsd
|
||||
endcase
|
||||
// When ZiCCLSM_SUPPORTED, misalgined cachable loads and stores are handled in hardware so they do not throw a misaligned fault
|
||||
// When ZiCCLSM_SUPPORTED, misalgined cacheable loads and stores are handled in hardware so they do not throw a misaligned fault
|
||||
assign LoadMisalignedFaultM = DataMisalignedM & ReadNoAmoAccessM & ~(P.ZICCLSM_SUPPORTED & Cacheable) & ~TLBMiss;
|
||||
assign StoreAmoMisalignedFaultM = DataMisalignedM & WriteAccessM & ~(P.ZICCLSM_SUPPORTED & Cacheable) & ~TLBMiss; // Store and AMO both assert WriteAccess
|
||||
|
||||
|
|
|
@ -58,8 +58,8 @@ module pmachecker import cvw::*; #(parameter cvw_t P) (
|
|||
// Determine which region of physical memory (if any) is being accessed
|
||||
adrdecs #(P) adrdecs(PhysicalAddress, AccessRW, AccessRX, AccessRWXC, Size, SelRegions);
|
||||
|
||||
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cachable; NC and IO are uncachable
|
||||
assign CacheableRegion = SelRegions[3] | SelRegions[4] | SelRegions[5]; // exclusion-tag: unused-cachable
|
||||
// Only non-core RAM/ROM memory regions are cacheable. PBMT can override cacheable; NC and IO are uncachable
|
||||
assign CacheableRegion = SelRegions[3] | SelRegions[4] | SelRegions[5]; // exclusion-tag: unused-cacheable
|
||||
assign Cacheable = (PBMemoryType == 2'b00) ? CacheableRegion : 1'b0;
|
||||
|
||||
// Nonidemdempotent means access could have side effect and must not be done speculatively or redundantly
|
||||
|
|
|
@ -76,7 +76,7 @@ module pmpadrdec import cvw::*; #(parameter cvw_t P) (
|
|||
// form a mask where the bottom k bits are 1, corresponding to a size of 2^k bytes for this memory region.
|
||||
// This assumes we're using at least an NA4 region, but works for any size NAPOT region.
|
||||
assign NABase = {(PMPAdr & ~NAMask[P.PA_BITS-1:2]), 2'b00}; // base physical address of the pmp region
|
||||
assign NAMatch = &((NABase ~^ PhysicalAddress) | NAMask); // check if upper bits of base address match, ignore lower bits correspoonding to inside the memory range
|
||||
assign NAMatch = &((NABase ~^ PhysicalAddress) | NAMask); // check if upper bits of base address match, ignore lower bits corresponding to inside the memory range
|
||||
|
||||
// finally pick the appropriate match for the access type
|
||||
assign Match = (AdrMode == TOR) ? TORMatch :
|
||||
|
|
|
@ -75,7 +75,7 @@ module pmpchecker import cvw::*; #(parameter cvw_t P) (
|
|||
.Match, .PMPTop, .L, .X, .W, .R);
|
||||
end
|
||||
|
||||
priorityonehot #(P.PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the adress decoders to find the first one that matches.
|
||||
priorityonehot #(P.PMP_ENTRIES) pmppriority(.a(Match), .y(FirstMatch)); // combine the match signal from all the address decoders to find the first one that matches.
|
||||
|
||||
// Distributed AND-OR mux to select the first matching results
|
||||
// If the access does not match all bytes of the PMP region, it is too big and the matches are disabled
|
||||
|
|
|
@ -71,7 +71,7 @@ module tlbcamline import cvw::*; #(parameter cvw_t P,
|
|||
// Calculate the actual match value based on the input vpn and the page type.
|
||||
// For example, a megapage in SV32 only cares about VPN[1], so VPN[0]
|
||||
// should automatically match.
|
||||
assign Match0 = (Query0 == Key0) | (PageType[0]); // least signifcant section
|
||||
assign Match0 = (Query0 == Key0) | (PageType[0]); // least significant section
|
||||
assign Match1 = (Query1 == Key1);
|
||||
|
||||
assign Match = Match0 & Match1 & MatchASID & Valid;
|
||||
|
|
|
@ -115,7 +115,7 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
|
|||
assign PreUpdateDA = ~PTE_A | WriteAccess & ~PTE_D;
|
||||
end
|
||||
|
||||
// Determine wheter to update DA bits. With SVADU, it is done in hardware
|
||||
// Determine whether to update DA bits. With SVADU, it is done in hardware
|
||||
assign UpdateDA = P.SVADU_SUPPORTED & PreUpdateDA & Translate & TLBHit & ~TLBPageFault & ENVCFG_ADUE;
|
||||
|
||||
// Determine whether page fault occurs
|
||||
|
|
|
@ -63,7 +63,7 @@ module tlbmixer import cvw::*; #(parameter cvw_t P) (
|
|||
|
||||
// In Svnapot, when N=1, use bottom bits of VPN for contiugous translations
|
||||
if (P.SVNAPOT_SUPPORTED) begin
|
||||
// 64 KiB contiguous NAPOT translations suported
|
||||
// 64 KiB contiguous NAPOT translations supported
|
||||
logic [3:0] PPNMixedBot;
|
||||
mux2 #(4) napotmux(PPNMixed[3:0], VPN[3:0], PTE_N, PPNMixedBot);
|
||||
assign PPNMixed2 = {PPNMixed[P.PPN_BITS-1:4], PPNMixedBot};
|
||||
|
|
|
@ -90,14 +90,14 @@ module csrsr import cvw::*; #(parameter cvw_t P) (
|
|||
end
|
||||
|
||||
// hardwired STATUS bits
|
||||
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override reigster with 0 if supervisor mode not supported
|
||||
assign STATUS_TSR = P.S_SUPPORTED & STATUS_TSR_INT; // override register with 0 if supervisor mode not supported
|
||||
assign STATUS_TW = P.U_SUPPORTED & STATUS_TW_INT; // override register with 0 if only machine mode supported
|
||||
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override reigster with 0 if supervisor mode not supported
|
||||
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override reigster with 0 if supervisor mode not supported
|
||||
assign STATUS_TVM = P.S_SUPPORTED & STATUS_TVM_INT; // override register with 0 if supervisor mode not supported
|
||||
assign STATUS_MXR = P.S_SUPPORTED & STATUS_MXR_INT; // override register with 0 if supervisor mode not supported
|
||||
// SXL and UXL bits only matter for RV64. Set to 10 for RV64 if mode is supported, or 0 if not
|
||||
assign STATUS_SXL = P.S_SUPPORTED ? 2'b10 : 2'b00; // 10 if supervisor mode supported
|
||||
assign STATUS_UXL = P.U_SUPPORTED ? 2'b10 : 2'b00; // 10 if user mode supported
|
||||
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override reigster with 0 if supervisor mode not supported
|
||||
assign STATUS_SUM = P.S_SUPPORTED & P.VIRTMEM_SUPPORTED & STATUS_SUM_INT; // override register with 0 if supervisor mode not supported
|
||||
assign STATUS_MPRV = P.U_SUPPORTED & STATUS_MPRV_INT; // override with 0 if user mode not supported
|
||||
assign STATUS_FS = P.F_SUPPORTED ? STATUS_FS_INT : 2'b00; // off if no FP
|
||||
assign STATUS_SD = (STATUS_FS == 2'b11) | (STATUS_XS == 2'b11); // dirty state logic
|
||||
|
|
|
@ -83,7 +83,7 @@ module privdec import cvw::*; #(parameter cvw_t P) (
|
|||
assign WFICountPlus1 = wfiM ? WFICount + 1 : '0; // restart counting on WFI
|
||||
flopr #(P.WFI_TIMEOUT_BIT+1) wficountreg(clk, reset, WFICountPlus1, WFICount); // count while in WFI
|
||||
// coverage off -item e 1 -fecexprrow 1
|
||||
// WFI Timout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
|
||||
// WFI Timeout trap will not occur when STATUS_TW is low while in supervisor mode, so the system gets stuck waiting for an interrupt and triggers a watchdog timeout.
|
||||
assign WFITimeoutM = ((STATUS_TW & PrivilegeModeW != P.M_MODE) | (P.S_SUPPORTED & PrivilegeModeW == P.U_MODE)) & WFICount[P.WFI_TIMEOUT_BIT];
|
||||
// coverage on
|
||||
end else assign WFITimeoutM = 1'b0;
|
||||
|
|
|
@ -52,7 +52,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||
input logic DCacheStallM, // D cache stalled
|
||||
input logic BPDirWrongM, // branch predictor guessed wrong direction
|
||||
input logic BTAWrongM, // branch predictor guessed wrong target
|
||||
input logic RASPredPCWrongM, // return adddress stack guessed wrong target
|
||||
input logic RASPredPCWrongM, // return address stack guessed wrong target
|
||||
input logic IClassWrongM, // branch predictor guessed wrong instruction class
|
||||
input logic BPWrongM, // branch predictor is wrong
|
||||
input logic [3:0] IClassM, // actual instruction class
|
||||
|
@ -114,7 +114,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||
logic [11:0] MIP_REGW, MIE_REGW; // interrupt pending and enable bits
|
||||
logic [1:0] NextPrivilegeModeM; // next privilege mode based on trap or return
|
||||
logic DelegateM; // trap should be delegated
|
||||
logic InterruptM; // interrupt occuring
|
||||
logic InterruptM; // interrupt occurring
|
||||
logic ExceptionM; // Memory stage instruction caused a fault
|
||||
logic HPTWInstrAccessFaultM; // Hardware page table access fault while fetching instruction PTE
|
||||
logic HPTWInstrPageFaultM; // Hardware page table page fault while fetching instruction PTE
|
||||
|
|
|
@ -48,7 +48,7 @@ module trap import cvw::*; #(parameter cvw_t P) (
|
|||
output logic [3:0] CauseM // trap cause
|
||||
);
|
||||
|
||||
logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables
|
||||
logic MIntGlobalEnM, SIntGlobalEnM; // Global interrupt enables
|
||||
logic Committed; // LSU or IFU has committed to a bus operation that can't be interrupted
|
||||
logic BothInstrAccessFaultM, BothInstrPageFaultM; // instruction or HPTW ITLB fill caused an Instruction Access Fault
|
||||
logic [11:0] PendingIntsM, ValidIntsM, EnabledIntsM; // interrupts are pending, valid, or enabled
|
||||
|
|
|
@ -48,7 +48,7 @@ module rvvisynth import cvw::*; #(parameter cvw_t P,
|
|||
output logic [72+(5*P.XLEN) + MAX_CSRS*(P.XLEN+16)-1:0] rvvi
|
||||
);
|
||||
|
||||
// pipeline controlls
|
||||
// pipeline controls
|
||||
|
||||
// required
|
||||
logic [P.XLEN-1:0] PCW;
|
||||
|
|
|
@ -215,7 +215,7 @@ module timereg import cvw::*; #(parameter cvw_t P) (
|
|||
done <= ack_stored & ~ack;
|
||||
end
|
||||
|
||||
// synchronize the reset and reqest into the TIMECLK domain
|
||||
// synchronize the reset and request into the TIMECLK domain
|
||||
sync resetsync(TIMECLK, PRESETn, resetn_sync);
|
||||
sync rsync(TIMECLK, req, req_sync);
|
||||
// synchronize the acknowledge back to the PCLK domain to indicate the request was handled and can be lowered
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
// up to 63 sources supported; in the future, allow up to 1023 sources
|
||||
|
||||
`define C 2
|
||||
// number of conexts
|
||||
// number of contexts
|
||||
// hardcoded to 2 contexts for now; later upgrade to arbitrary (up to 15872) contexts
|
||||
|
||||
module plic_apb import cvw::*; #(parameter cvw_t P) (
|
||||
|
@ -195,7 +195,7 @@ module plic_apb import cvw::*; #(parameter cvw_t P) (
|
|||
end
|
||||
end
|
||||
|
||||
// which prority levels have one or more active requests?
|
||||
// which priority levels have one or more active requests?
|
||||
assign priorities_with_irqs[ctx][7:1] = {
|
||||
|irqMatrix[ctx][7],
|
||||
|irqMatrix[ctx][6],
|
||||
|
|
|
@ -60,7 +60,7 @@ module ram_ahb import cvw::*; #(parameter cvw_t P,
|
|||
flopenr #(1) memwritereg(HCLK, ~HRESETn, HREADY, memwrite, memwriteD);
|
||||
flopenr #(P.PA_BITS) haddrreg(HCLK, ~HRESETn, HREADY, HADDR, HADDRD);
|
||||
|
||||
// Stall on a read after a write because the RAM can't take both adddresses on the same cycle
|
||||
// Stall on a read after a write because the RAM can't take both addresses on the same cycle
|
||||
assign nextHREADYRam = (~(memwriteD & memread)) & ~DelayReady;
|
||||
flopr #(1) readyreg(HCLK, ~HRESETn, nextHREADYRam, HREADYRam);
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
//
|
||||
// Purpose: SPI peripheral
|
||||
//
|
||||
// SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and recieve FIFOs connected to shift registers.
|
||||
// SPI module is written to the specifications described in FU540-C000-v1.0. At the top level, it is consists of synchronous 8 byte transmit and receive FIFOs connected to shift registers.
|
||||
// The FIFOs are connected to WALLY by an apb control register interface, which includes various control registers for modifying the SPI transmission along with registers for writing
|
||||
// to the transmit FIFO and reading from the receive FIFO. The transmissions themselves are then controlled by a finite state machine. The SPI module uses 4 tristate pins for SPI input/output,
|
||||
// along with a 4 bit Chip Select signal, a clock signal, and an interrupt signal to WALLY.
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
// Written: David_Harris@hmc.edu 21 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: Universial Asynchronous Receiver/ Transmitter with FIFOs
|
||||
// Purpose: Universal Asynchronous Receiver/ Transmitter with FIFOs
|
||||
// Emulates interface of Texas Instruments PC16550D
|
||||
// https://media.digikey.com/pdf/Data%20Sheets/Texas%20Instruments%20PDFs/PC16550D.pdf
|
||||
// Compatible with UART in Imperas Virtio model
|
||||
//
|
||||
// Compatible with most of PC16550D with the following known exceptions:
|
||||
// Generates 2 rather than 1.5 stop bits when 5-bit word length is slected and LCR[2] = 1
|
||||
// Generates 2 rather than 1.5 stop bits when 5-bit word length is selected and LCR[2] = 1
|
||||
// Timeout not yet implemented
|
||||
//
|
||||
// Documentation: RISC-V System on Chip Design
|
||||
|
@ -71,7 +71,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
logic [3:0] IER, MSR;
|
||||
logic [4:0] MCR;
|
||||
|
||||
// Syncrhonized and delayed UART signals
|
||||
// Synchronized and delayed UART signals
|
||||
logic SINd, DSRbd, DCDbd, CTSbd, RIbd;
|
||||
logic SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync;
|
||||
logic DSRb2, DCDb2, CTSb2, RIb2;
|
||||
|
@ -88,7 +88,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
logic [3:0] rxbitsreceived, txbitssent;
|
||||
statetype rxstate, txstate;
|
||||
|
||||
// shift registrs and FIFOs
|
||||
// shift registers and FIFOs
|
||||
logic [9:0] rxshiftreg;
|
||||
logic [10:0] rxfifo[15:0];
|
||||
logic [7:0] txfifo[15:0];
|
||||
|
@ -137,7 +137,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
always_ff @(posedge PCLK) begin
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd} <= {SIN, DSRb, DCDb, CTSb, RIb};
|
||||
{SINsync, DSRbsync, DCDbsync, CTSbsync, RIbsync} <= loop ? {SOUTbit, ~MCR[0], ~MCR[3], ~MCR[1], ~MCR[2]} :
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd}; // syncrhonized signals, handle loopback testing
|
||||
{SINd, DSRbd, DCDbd, CTSbd, RIbd}; // synchronized signals, handle loopback testing
|
||||
{DSRb2, DCDb2, CTSb2, RIb2} <= {DSRbsync, DCDbsync, CTSbsync, RIbsync}; // for detecting state changes
|
||||
end
|
||||
|
||||
|
@ -171,7 +171,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
end
|
||||
|
||||
// Line Status Register (8.6.3)
|
||||
// Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay.
|
||||
// Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unnecessary delay.
|
||||
if (~MEMWb & (A == UART_LSR))
|
||||
LSR[6:1] <= Din[6:1]; // recommended only for test, see 8.6.3
|
||||
else begin
|
||||
|
@ -203,7 +203,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
case (A)
|
||||
UART_DLL_RBR: if (DLAB) Dout = DLL; else Dout = RBR[7:0];
|
||||
UART_DLM_IER: if (DLAB) Dout = DLM; else Dout = {4'b0, IER[3:0]};
|
||||
UART_IIR: Dout = {{2{fifoenabled}}, 2'b00, intrID[2:0], ~intrpending}; // Read only Interupt Ident Register
|
||||
UART_IIR: Dout = {{2{fifoenabled}}, 2'b00, intrID[2:0], ~intrpending}; // Read only Interrupt Ident Register
|
||||
UART_LCR: Dout = LCR;
|
||||
UART_MCR: Dout = {3'b000, MCR};
|
||||
UART_LSR: Dout = LSR;
|
||||
|
@ -472,7 +472,7 @@ module uartPC16550D #(parameter UART_PRESCALE) (
|
|||
// pointer indicates where the next write goes and not the location of the
|
||||
// current head, the head and tail pointer being equal imply two different
|
||||
// things. First it could mean the fifo is empty and second it could mean
|
||||
// the fifo is full. To differenciate we need to know which pointer moved
|
||||
// the fifo is full. To differentiate we need to know which pointer moved
|
||||
// to cause them to be equal. If the head pointer moved then it is full.
|
||||
// If the tail pointer moved then it is empty. it resets to empty so
|
||||
// if reset with the tail pointer indicating the last update.
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
// Written: David_Harris@hmc.edu 21 January 2021
|
||||
// Modified:
|
||||
//
|
||||
// Purpose: APB Interface to Universial Asynchronous Receiver/ Transmitter with FIFOs
|
||||
// Purpose: APB Interface to Universal Asynchronous Receiver/ Transmitter with FIFOs
|
||||
// Emulates interface of Texas Instruments PC165550D
|
||||
// Compatible with UART in Imperas Virtio model
|
||||
//
|
||||
|
|
|
@ -195,9 +195,9 @@ module uncore import cvw::*; #(parameter cvw_t P)(
|
|||
|
||||
// Address Decoder Delay (figure 4-2 in spec)
|
||||
// The select for HREADY needs to be based on the address phase address. If the device
|
||||
// takes more than 1 cycle to repsond it needs to hold on to the old select until the
|
||||
// device is ready. Hense this register must be selectively enabled by HREADY.
|
||||
// However on reset None must be seleted.
|
||||
// takes more than 1 cycle to respond it needs to hold on to the old select until the
|
||||
// device is ready. Hence this register must be selectively enabled by HREADY.
|
||||
// However on reset None must be selected.
|
||||
flopenl #(12) hseldelayreg(HCLK, ~HRESETn, HREADY, HSELRegions, 12'b1,
|
||||
{HSELSPID, HSELSDCD, HSELPLICD, HSELUARTD, HSELGPIOD, HSELCLINTD,
|
||||
HSELRamD, HSELBootRomD, HSELEXTD, HSELIROMD, HSELDTIMD, HSELNoneD});
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue