2021-01-15 04:37:51 +00:00
///////////////////////////////////////////
2021-01-28 03:49:47 +00:00
// ifu.sv
2021-01-15 04:37:51 +00:00
//
// Written: David_Harris@hmc.edu 9 January 2021
2021-03-30 19:25:07 +00:00
// Modified:
2021-01-15 04:37:51 +00:00
//
2021-01-28 03:49:47 +00:00
// Purpose: Instrunction Fetch Unit
// PC, branch prediction, instruction cache
2021-01-15 04:37:51 +00:00
//
// 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-01-15 04:37:51 +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-01-15 04:37:51 +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-01-15 04:37:51 +00:00
2021-01-23 15:48:12 +00:00
`include " wally-config.vh "
2021-01-15 04:37:51 +00:00
2021-01-28 03:49:47 +00:00
module ifu (
2022-01-04 04:23:04 +00:00
input logic clk , reset ,
input logic StallF , StallD , StallE , StallM , StallW ,
input logic FlushF , FlushD , FlushE , FlushM , FlushW ,
// Bus interface
2022-01-07 04:30:00 +00:00
( * mark_debug = " true " * ) input logic [ `XLEN - 1 : 0 ] IFUBusHRDATA ,
( * mark_debug = " true " * ) input logic IFUBusAck ,
( * mark_debug = " true " * ) output logic [ `PA_BITS - 1 : 0 ] IFUBusAdr ,
( * mark_debug = " true " * ) output logic IFUBusRead ,
( * mark_debug = " true " * ) output logic IFUStallF ,
2022-01-04 04:23:04 +00:00
( * mark_debug = " true " * ) output logic [ `XLEN - 1 : 0 ] PCF ,
// Execute
output logic [ `XLEN - 1 : 0 ] PCLinkE ,
input logic PCSrcE ,
input logic [ `XLEN - 1 : 0 ] IEUAdrE ,
output logic [ `XLEN - 1 : 0 ] PCE ,
output logic BPPredWrongE ,
// Mem
input logic RetM , TrapM ,
input logic [ `XLEN - 1 : 0 ] PrivilegedNextPCM ,
input logic InvalidateICacheM ,
output logic [ 31 : 0 ] InstrD , InstrM ,
output logic [ `XLEN - 1 : 0 ] PCM ,
// branch predictor
output logic [ 4 : 0 ] InstrClassM ,
output logic BPPredDirWrongM ,
output logic BTBPredPCWrongM ,
output logic RASPredPCWrongM ,
output logic BPPredClassNonCFIWrongM ,
// Faults
input logic IllegalBaseInstrFaultD ,
output logic ITLBInstrPageFaultF ,
output logic IllegalIEUInstrFaultD ,
output logic InstrMisalignedFaultM ,
output logic [ `XLEN - 1 : 0 ] InstrMisalignedAdrM ,
input logic ExceptionM , PendingInterruptM ,
// mmu management
input logic [ 1 : 0 ] PrivilegeModeW ,
input logic [ `XLEN - 1 : 0 ] PTE ,
input logic [ 1 : 0 ] PageType ,
input logic [ `XLEN - 1 : 0 ] SATP_REGW ,
input logic STATUS_MXR , STATUS_SUM , STATUS_MPRV ,
input logic [ 1 : 0 ] STATUS_MPP ,
input logic ITLBWriteF , ITLBFlushF ,
output logic ITLBMissF ,
2021-06-04 21:05:07 +00:00
// pmp/pma (inside mmu) signals. *** temporarily from AHB bus but eventually replace with internal versions pre H
2022-01-04 04:23:04 +00:00
input var logic [ 7 : 0 ] PMPCFG_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ] ,
input var logic [ `XLEN - 1 : 0 ] PMPADDR_ARRAY_REGW [ `PMP_ENTRIES - 1 : 0 ] ,
2022-01-10 04:56:56 +00:00
output logic InstrAccessFaultF ,
output logic ICacheAccess ,
output logic ICacheMiss
2021-01-28 03:49:47 +00:00
) ;
2021-01-15 04:37:51 +00:00
2022-01-19 20:05:14 +00:00
( * mark_debug = " true " * ) logic [ `XLEN - 1 : 0 ] PCCorrectE , UnalignedPCNextF , PCNextF ;
2021-10-27 19:43:55 +00:00
logic misaligned , BranchMisalignedFaultE , BranchMisalignedFaultM , TrapMisalignedFaultM ;
logic PrivilegedChangePCM ;
logic IllegalCompInstrD ;
logic [ `XLEN - 1 : 0 ] PCPlus2or4F , PCLinkD ;
logic [ `XLEN - 3 : 0 ] PCPlusUpperF ;
logic CompressedF ;
2021-12-31 00:09:37 +00:00
logic [ 31 : 0 ] InstrRawD , FinalInstrRawF , InstrRawF ;
2021-10-27 19:43:55 +00:00
logic [ 31 : 0 ] InstrE ;
logic [ `XLEN - 1 : 0 ] PCD ;
2021-10-23 19:00:32 +00:00
2022-01-04 04:23:04 +00:00
localparam [ 31 : 0 ] nop = 32 'h00000013 ; // instruction for NOP
2022-01-21 21:42:54 +00:00
logic reset_q ; // see comment below about PCNextF and icache.
2021-01-28 03:49:47 +00:00
2022-01-04 04:23:04 +00:00
logic [ `XLEN - 1 : 0 ] PCBPWrongInvalidate ;
logic BPPredWrongM ;
2021-07-06 18:43:53 +00:00
2022-01-03 23:00:50 +00:00
( * mark_debug = " true " * ) logic [ `PA_BITS - 1 : 0 ] PCPF ; // used to either truncate or expand PCPF and PCNextF into `PA_BITS width.
2021-10-27 19:43:55 +00:00
logic [ `XLEN + 1 : 0 ] PCFExt ;
2022-01-04 04:23:04 +00:00
2021-12-30 15:18:16 +00:00
logic CacheableF ;
2022-01-21 21:50:54 +00:00
logic [ `XLEN - 1 : 0 ] PCNextFMux ;
2022-01-03 23:00:50 +00:00
logic [ `XLEN - 1 : 0 ] PCFMux ;
2022-01-04 04:23:04 +00:00
logic SelNextSpill ;
2022-01-04 00:10:15 +00:00
logic ICacheFetchLine ;
logic BusStall ;
logic ICacheStallF ;
logic IgnoreRequest ;
logic CPUBusy ;
2022-01-19 20:05:14 +00:00
( * mark_debug = " true " * ) logic [ 31 : 0 ] PostSpillInstrRawF ;
2022-01-04 00:10:15 +00:00
2022-01-14 23:23:39 +00:00
localparam integer SPILLTHRESHOLD = `MEM_ICACHE ? `ICACHE_LINELENINBITS / 32 : 1 ;
2022-01-04 00:10:15 +00:00
2022-01-14 17:13:06 +00:00
if ( `C_SUPPORTED ) begin : SpillSupport
logic [ `XLEN - 1 : 0 ] PCFp2 ;
logic Spill ;
logic SelSpill , SpillSave ;
logic [ 15 : 0 ] SpillDataLine0 ;
// this exists only if there are compressed instructions.
assign PCFp2 = PCF + `XLEN 'b10 ;
2022-01-21 21:50:54 +00:00
assign PCNextFMux = SelNextSpill ? PCFp2 : PCNextF ;
2022-01-14 17:13:06 +00:00
assign PCFMux = SelSpill ? PCFp2 : PCF ;
assign Spill = & PCF [ $clog2 ( SPILLTHRESHOLD ) + 1 : 1 ] ;
typedef enum { STATE_SPILL_READY , STATE_SPILL_SPILL } statetype ;
( * mark_debug = " true " * ) statetype CurrState , NextState ;
always_ff @ ( posedge clk )
if ( reset ) CurrState < = # 1 STATE_SPILL_READY ;
else CurrState < = # 1 NextState ;
always_comb begin
case ( CurrState )
STATE_SPILL_READY: if ( Spill & ~ ( ICacheStallF | BusStall ) ) NextState = STATE_SPILL_SPILL ;
else NextState = STATE_SPILL_READY ;
STATE_SPILL_SPILL: if ( ICacheStallF | BusStall | StallF ) NextState = STATE_SPILL_SPILL ;
else NextState = STATE_SPILL_READY ;
default : NextState = STATE_SPILL_READY ;
endcase
2022-01-04 04:23:04 +00:00
end
2022-01-14 17:13:06 +00:00
assign SelSpill = CurrState = = STATE_SPILL_SPILL ;
assign SelNextSpill = ( CurrState = = STATE_SPILL_READY & ( Spill & ~ ( ICacheStallF | BusStall ) ) ) |
( CurrState = = STATE_SPILL_SPILL & ( ICacheStallF | BusStall ) ) ;
assign SpillSave = CurrState = = STATE_SPILL_READY & ( Spill & ~ ( ICacheStallF | BusStall ) ) ;
flopenr # ( 16 ) SpillInstrReg ( . clk ( clk ) ,
. en ( SpillSave ) ,
. reset ( reset ) ,
. d ( `MEM_ICACHE ? InstrRawF [ 15 : 0 ] : InstrRawF [ 31 : 16 ] ) ,
. q ( SpillDataLine0 ) ) ;
assign PostSpillInstrRawF = Spill ? { InstrRawF [ 15 : 0 ] , SpillDataLine0 } : InstrRawF ;
assign CompressedF = PostSpillInstrRawF [ 1 : 0 ] ! = 2 'b11 ;
// end of spill support
end else begin : NoSpillSupport // line: SpillSupport
2022-01-21 21:50:54 +00:00
assign PCNextFMux = PCNextF ;
2022-01-14 17:13:06 +00:00
assign PCFMux = PCF ;
assign SelNextSpill = 0 ;
assign PostSpillInstrRawF = InstrRawF ;
end
2022-01-03 23:00:50 +00:00
2021-06-18 13:11:31 +00:00
2022-01-03 23:00:50 +00:00
assign PCFExt = { 2 'b00 , PCFMux } ;
2022-01-14 17:13:06 +00:00
2021-07-04 21:52:00 +00:00
mmu # ( . TLB_ENTRIES ( `ITLB_ENTRIES ) , . IMMU ( 1 ) )
2021-07-19 15:33:27 +00:00
immu ( . PAdr ( PCFExt [ `PA_BITS - 1 : 0 ] ) ,
2022-01-03 23:00:50 +00:00
. VAdr ( PCFMux ) ,
2021-06-24 18:05:22 +00:00
. Size ( 2 'b10 ) ,
2021-07-17 19:04:39 +00:00
. PTE ( PTE ) ,
2021-07-17 06:31:23 +00:00
. PageTypeWriteVal ( PageType ) ,
2021-06-24 18:05:22 +00:00
. TLBWrite ( ITLBWriteF ) ,
. TLBFlush ( ITLBFlushF ) ,
2022-01-03 23:00:50 +00:00
. PhysicalAddress ( PCPF ) ,
2021-06-24 18:05:22 +00:00
. TLBMiss ( ITLBMissF ) ,
. TLBPageFault ( ITLBInstrPageFaultF ) ,
2021-07-03 07:29:33 +00:00
. ExecuteAccessF ( 1 'b1 ) , // ***dh -- this should eventually change to only true if an instruction fetch is occurring
2021-06-24 18:05:22 +00:00
. AtomicAccessM ( 1 'b0 ) ,
2021-07-02 18:56:49 +00:00
. ReadAccessM ( 1 'b0 ) ,
. WriteAccessM ( 1 'b0 ) ,
2021-07-06 18:43:53 +00:00
. LoadAccessFaultM ( ) ,
. StoreAccessFaultM ( ) ,
2021-06-24 18:05:22 +00:00
. DisableTranslation ( 1 'b0 ) ,
2021-12-30 15:18:16 +00:00
. Cacheable ( CacheableF ) , . Idempotent ( ) , . AtomicAllowed ( ) ,
2021-03-04 08:11:34 +00:00
2021-12-02 17:45:55 +00:00
. clk , . reset ,
. SATP_REGW ,
. STATUS_MXR , . STATUS_SUM , . STATUS_MPRV ,
. STATUS_MPP ,
. PrivilegeModeW ,
. InstrAccessFaultF ,
2021-12-02 18:32:35 +00:00
. PMPCFG_ARRAY_REGW ,
2021-12-02 17:45:55 +00:00
. PMPADDR_ARRAY_REGW
) ;
2021-06-04 15:59:14 +00:00
2021-12-14 20:46:29 +00:00
// conditional
2021-12-14 21:43:06 +00:00
// 1. ram // controlled by `MEM_IROM
2021-12-14 20:46:29 +00:00
// 2. cache // `MEM_ICACHE
// 3. wire pass-through
2021-12-30 20:23:05 +00:00
2022-01-14 17:13:06 +00:00
// If we have `MEM_IROM we don't have the bus controller
// otherwise we have the bus controller and either a cache or a passthrough.
2022-01-05 04:08:18 +00:00
localparam integer WORDSPERLINE = `MEM_ICACHE ? `ICACHE_LINELENINBITS / `XLEN : 1 ;
2021-12-30 23:53:43 +00:00
localparam integer LOGWPL = `MEM_ICACHE ? $clog2 ( WORDSPERLINE ) : 1 ;
2022-01-05 04:08:18 +00:00
localparam integer LINELEN = `MEM_ICACHE ? `ICACHE_LINELENINBITS : `XLEN ;
2021-12-30 20:23:05 +00:00
localparam integer WordCountThreshold = `MEM_ICACHE ? WORDSPERLINE - 1 : 0 ;
2022-01-05 04:08:18 +00:00
localparam integer LINEBYTELEN = LINELEN / 8 ;
localparam integer OFFSETLEN = $clog2 ( LINEBYTELEN ) ;
2021-12-30 20:23:05 +00:00
logic [ LOGWPL - 1 : 0 ] WordCount ;
2022-01-14 17:13:06 +00:00
logic [ LINELEN - 1 : 0 ] ICacheMemWriteData ;
2021-12-30 20:23:05 +00:00
logic ICacheBusAck ;
2022-01-07 04:30:00 +00:00
logic [ `PA_BITS - 1 : 0 ] LocalIFUBusAdr ;
2021-12-30 20:23:05 +00:00
logic [ `PA_BITS - 1 : 0 ] ICacheBusAdr ;
logic SelUncachedAdr ;
2022-01-03 23:00:50 +00:00
2022-01-14 17:13:06 +00:00
if ( `MEM_IROM ) begin : irom
2022-01-14 04:21:43 +00:00
logic [ `XLEN - 1 : 0 ] FinalInstrRawF_FIXME ;
simpleram # (
2022-01-13 23:00:46 +00:00
. BASE ( `RAM_BASE ) , . RANGE ( `RAM_RANGE ) ) ram (
2022-01-25 17:34:15 +00:00
. clk ,
2022-01-26 23:37:04 +00:00
. a ( CPUBusy | reset ? PCPF [ 31 : 0 ] : PCNextFMux [ 31 : 0 ] ) , // mux is also inside $, have to replay address if CPU is stalled.
2022-01-25 18:26:31 +00:00
. we ( 1 'b0 ) ,
. wd ( 0 ) , . rd ( FinalInstrRawF_FIXME ) ) ;
2022-01-25 17:31:53 +00:00
assign FinalInstrRawF = FinalInstrRawF_FIXME [ 31 : 0 ] ;
2022-01-13 23:00:46 +00:00
assign BusStall = 0 ;
assign IFUBusRead = 0 ;
assign ICacheBusAck = 0 ;
assign SelUncachedAdr = 0 ;
2022-01-14 04:21:43 +00:00
assign IFUBusAdr = 0 ;
2022-01-13 23:00:46 +00:00
end else begin : bus
genvar index ;
for ( index = 0 ; index < WORDSPERLINE ; index + + ) begin : fetchbuffer
flopen # ( `XLEN ) fb ( . clk ( clk ) ,
. en ( IFUBusAck & IFUBusRead & ( index = = WordCount ) ) ,
. d ( IFUBusHRDATA ) ,
. q ( ICacheMemWriteData [ ( index + 1 ) * `XLEN - 1 : index * `XLEN ] ) ) ;
end
assign LocalIFUBusAdr = SelUncachedAdr ? PCPF : ICacheBusAdr ;
assign IFUBusAdr = ( { { `PA_BITS - LOGWPL { 1 'b0 } } , WordCount } < < $clog2 ( `XLEN / 8 ) ) + LocalIFUBusAdr ;
busfsm # ( WordCountThreshold , LOGWPL , `MEM_ICACHE )
busfsm ( . clk , . reset , . IgnoreRequest ,
. LSURWM ( 2 'b10 ) , . DCacheFetchLine ( ICacheFetchLine ) , . DCacheWriteLine ( 1 'b0 ) ,
. LSUBusAck ( IFUBusAck ) ,
. CPUBusy , . CacheableM ( CacheableF ) ,
. BusStall , . LSUBusWrite ( ) , . LSUBusRead ( IFUBusRead ) , . DCacheBusAck ( ICacheBusAck ) ,
. BusCommittedM ( ) , . SelUncachedAdr ( SelUncachedAdr ) , . WordCount ) ;
2022-01-14 17:13:06 +00:00
end
if ( `MEM_ICACHE ) begin : icache
logic [ 1 : 0 ] IFURWF ;
assign IFURWF = CacheableF ? 2 'b10 : 2 'b00 ;
logic [ `XLEN - 1 : 0 ] FinalInstrRawF_FIXME ;
cache # ( . LINELEN ( `ICACHE_LINELENINBITS ) ,
. NUMLINES ( `ICACHE_WAYSIZEINBYTES * 8 / `ICACHE_LINELENINBITS ) ,
. NUMWAYS ( `ICACHE_NUMWAYS ) , . DCACHE ( 0 ) )
icache ( . clk , . reset , . CPUBusy , . IgnoreRequest , . CacheMemWriteData ( ICacheMemWriteData ) , . CacheBusAck ( ICacheBusAck ) ,
. CacheBusAdr ( ICacheBusAdr ) , . CacheStall ( ICacheStallF ) , . ReadDataWord ( FinalInstrRawF_FIXME ) ,
. CacheFetchLine ( ICacheFetchLine ) ,
. CacheWriteLine ( ) ,
. ReadDataLineSets ( ) ,
. CacheMiss ( ICacheMiss ) ,
. CacheAccess ( ICacheAccess ) ,
. FinalWriteData ( '0 ) ,
. RW ( IFURWF ) ,
. Atomic ( 2 'b00 ) ,
. FlushCache ( 1 'b0 ) ,
2022-01-21 21:50:54 +00:00
. NextAdr ( PCNextFMux [ 11 : 0 ] ) ,
2022-01-14 17:13:06 +00:00
. PAdr ( PCPF ) ,
. CacheCommitted ( ) ,
. InvalidateCacheM ( InvalidateICacheM ) ) ;
assign FinalInstrRawF = FinalInstrRawF_FIXME [ 31 : 0 ] ;
end else begin
assign ICacheFetchLine = 0 ;
assign ICacheBusAdr = 0 ;
assign ICacheStallF = 0 ;
if ( ! `MEM_IROM ) assign FinalInstrRawF = 0 ;
assign ICacheAccess = CacheableF ;
assign ICacheMiss = CacheableF ;
end
// branch predictor signal
logic SelBPPredF ;
logic [ `XLEN - 1 : 0 ] BPPredPCF , PCNext0F , PCNext1F , PCNext2F , PCNext3F ;
logic [ 4 : 0 ] InstrClassD , InstrClassE ;
// select between dcache and direct from the BUS. Always selected if no dcache.
// handled in the busfsm.
mux2 # ( 32 ) UnCachedInstrMux ( . d0 ( FinalInstrRawF ) ,
. d1 ( ICacheMemWriteData [ 31 : 0 ] ) ,
. s ( SelUncachedAdr ) ,
. y ( InstrRawF ) ) ;
2022-01-07 04:30:00 +00:00
assign IFUStallF = ICacheStallF | BusStall | SelNextSpill ;
2022-01-04 00:10:15 +00:00
assign CPUBusy = StallF & ~ SelNextSpill ;
2021-12-30 20:23:05 +00:00
2022-01-03 19:27:15 +00:00
//assign IgnoreRequest = ITLBMissF | ExceptionM | PendingInterruptM;
2022-01-04 04:00:35 +00:00
// this is a difference with the dcache.
// uses interlock fsm.
2022-01-03 19:27:15 +00:00
assign IgnoreRequest = ITLBMissF ;
2021-05-03 17:03:17 +00:00
2022-01-14 18:16:48 +00:00
flopenl # ( 32 ) AlignedInstrRawDFlop ( clk , reset , ~ StallD , FlushD ? nop : PostSpillInstrRawF , nop , InstrRawD ) ;
2021-05-03 17:03:17 +00:00
2021-01-15 04:37:51 +00:00
assign PrivilegedChangePCM = RetM | TrapM ;
2022-01-26 23:37:04 +00:00
mux2 # ( `XLEN ) pcmux0 ( . d0 ( PCPlus2or4F ) , . d1 ( BPPredPCF ) , . s ( SelBPPredF ) , . y ( PCNext0F ) ) ;
mux2 # ( `XLEN ) pcmux1 ( . d0 ( PCNext0F ) , . d1 ( PCCorrectE ) , . s ( BPPredWrongE ) , . y ( PCNext1F ) ) ;
// The true correct target is IEUAdrE if PCSrcE is 1 else it is the fall through PCLinkE.
mux2 # ( `XLEN ) pccorrectemux ( . d0 ( PCLinkE ) , . d1 ( IEUAdrE ) , . s ( PCSrcE ) , . y ( PCCorrectE ) ) ;
mux2 # ( `XLEN ) pcmux2 ( . d0 ( PCNext1F ) , . d1 ( PCBPWrongInvalidate ) , . s ( InvalidateICacheM ) , . y ( PCNext2F ) ) ;
// Mux only required on instruction class miss prediction.
mux2 # ( `XLEN ) pcmuxBPWrongInvalidateFlush ( . d0 ( PCE ) , . d1 ( PCF ) , . s ( BPPredWrongM ) , . y ( PCBPWrongInvalidate ) ) ;
mux2 # ( `XLEN ) pcmux3 ( . d0 ( PCNext2F ) , . d1 ( PrivilegedNextPCM ) , . s ( PrivilegedChangePCM ) , . y ( PCNext3F ) ) ;
2022-01-26 19:54:59 +00:00
// This mux is required as PCNextF needs to be the valid reset vector during reset.
// Reseting PCF does not accomplish this as PCNextF will be +2/4 more than PCF.
2022-01-26 23:37:04 +00:00
//mux2 #(`XLEN) pcmux4(.d0(PCNext3F), .d1(`RESET_VECTOR), .s(`MEM_IROM ? reset : reset_q), .y(UnalignedPCNextF));
// mux2 #(`XLEN) pcmux4(.d0(PCNext3F), .d1(`RESET_VECTOR), .s(reset), .y(UnalignedPCNextF)); // ******* probably can get rid of by making reset SelAdr = 01
assign UnalignedPCNextF = PCNext3F ;
2021-12-21 17:29:28 +00:00
2022-01-26 23:37:04 +00:00
flopenrc # ( 1 ) BPPredWrongMReg ( . clk , . reset , . en ( ~ StallM ) , . clear ( FlushM ) , . d ( BPPredWrongE ) , . q ( BPPredWrongM ) ) ;
2021-12-21 17:29:28 +00:00
2021-02-18 04:19:17 +00:00
2021-01-23 15:48:12 +00:00
assign PCNextF = { UnalignedPCNextF [ `XLEN - 1 : 1 ] , 1 'b0 } ; // hart-SPEC p. 21 about 16-bit alignment
2022-01-14 17:19:12 +00:00
flopenl # ( `XLEN ) pcreg ( clk , reset , ~ StallF , PCNextF , `RESET_VECTOR , PCF ) ;
2021-01-19 01:16:53 +00:00
2021-02-18 04:19:17 +00:00
// branch and jump predictor
2022-01-14 17:19:12 +00:00
if ( `BPRED_ENABLED ) begin : bpred
2022-01-26 19:54:59 +00:00
logic BPPredDirWrongE , BTBPredPCWrongE , RASPredPCWrongE , BPPredClassNonCFIWrongE ;
2022-01-05 16:25:08 +00:00
bpred bpred ( . clk , . reset ,
. StallF , . StallD , . StallE ,
. FlushF , . FlushD , . FlushE ,
. PCNextF , . BPPredPCF , . SelBPPredF , . PCE , . PCSrcE , . IEUAdrE ,
. PCD , . PCLinkE , . InstrClassE , . BPPredWrongE , . BPPredDirWrongE ,
. BTBPredPCWrongE , . RASPredPCWrongE , . BPPredClassNonCFIWrongE ) ;
2022-01-26 19:54:59 +00:00
// the branch predictor needs a compact decoding of the instruction class.
// *** consider adding in the alternate return address x5 for returns.
assign InstrClassD [ 4 ] = ( InstrD [ 6 : 0 ] & 7 'h77 ) = = 7 'h67 & ( InstrD [ 11 : 07 ] & 5 'h1B ) = = 5 'h01 ; // jal(r) must link to ra or r5
assign InstrClassD [ 3 ] = InstrD [ 6 : 0 ] = = 7 'h67 & ( InstrD [ 19 : 15 ] & 5 'h1B ) = = 5 'h01 ; // return must return to ra or r5
assign InstrClassD [ 2 ] = InstrD [ 6 : 0 ] = = 7 'h67 & ( InstrD [ 19 : 15 ] & 5 'h1B ) ! = 5 'h01 & ( InstrD [ 11 : 7 ] & 5 'h1B ) ! = 5 'h01 ; // jump register, but not return
assign InstrClassD [ 1 ] = InstrD [ 6 : 0 ] = = 7 'h6F & ( InstrD [ 11 : 7 ] & 5 'h1B ) ! = 5 'h01 ; // jump, RD != x1 or x5
assign InstrClassD [ 0 ] = InstrD [ 6 : 0 ] = = 7 'h63 ; // branch
// branch predictor
flopenrc # ( 5 ) InstrClassRegE ( . clk , . reset , . en ( ~ StallE ) , . clear ( FlushE ) , . d ( InstrClassD ) , . q ( InstrClassE ) ) ;
flopenrc # ( 5 ) InstrClassRegM ( . clk , . reset , . en ( ~ StallM ) , . clear ( FlushM ) , . d ( InstrClassE ) , . q ( InstrClassM ) ) ;
flopenrc # ( 4 ) BPPredWrongRegM ( . clk , . reset , . en ( ~ StallM ) , . clear ( FlushM ) ,
. d ( { BPPredDirWrongE , BTBPredPCWrongE , RASPredPCWrongE , BPPredClassNonCFIWrongE } ) ,
. q ( { BPPredDirWrongM , BTBPredPCWrongM , RASPredPCWrongM , BPPredClassNonCFIWrongM } ) ) ;
2022-01-05 16:25:08 +00:00
end else begin : bpred
2022-01-26 19:54:59 +00:00
assign BPPredPCF = '0 ;
2022-01-26 23:37:04 +00:00
assign BPPredWrongE = PCSrcE ;
2022-01-26 19:54:59 +00:00
assign { SelBPPredF , BPPredDirWrongM , BTBPredPCWrongM , RASPredPCWrongM , BPPredClassNonCFIWrongM } = '0 ;
2022-01-05 16:25:08 +00:00
end
2021-02-18 04:19:17 +00:00
2021-01-19 01:16:53 +00:00
// pcadder
// add 2 or 4 to the PC, based on whether the instruction is 16 bits or 32
2021-01-23 15:48:12 +00:00
assign PCPlusUpperF = PCF [ `XLEN - 1 : 2 ] + 1 ; // add 4 to PC
2021-01-19 01:16:53 +00:00
// choose PC+2 or PC+4
always_comb
if ( CompressedF ) // add 2
if ( PCF [ 1 ] ) PCPlus2or4F = { PCPlusUpperF , 2 'b00 } ;
2021-01-23 15:48:12 +00:00
else PCPlus2or4F = { PCF [ `XLEN - 1 : 2 ] , 2 'b10 } ;
2021-01-19 01:16:53 +00:00
else PCPlus2or4F = { PCPlusUpperF , PCF [ 1 : 0 ] } ; // add 4
2021-01-15 04:37:51 +00:00
2021-01-28 03:49:47 +00:00
// Decode stage pipeline register and logic
flopenrc # ( `XLEN ) PCDReg ( clk , reset , FlushD , ~ StallD , PCF , PCD ) ;
2021-01-28 05:22:05 +00:00
// expand 16-bit compressed instructions to 32 bits
2021-12-02 18:32:35 +00:00
decompress decomp ( . InstrRawD , . InstrD , . IllegalCompInstrD ) ;
2021-01-28 03:49:47 +00:00
assign IllegalIEUInstrFaultD = IllegalBaseInstrFaultD | IllegalCompInstrD ; // illegal if bad 32 or 16-bit instr
// *** combine these with others in better way, including M, F
2021-03-04 15:23:35 +00:00
2021-01-15 04:37:51 +00:00
// Misaligned PC logic
2021-12-30 20:23:05 +00:00
// instruction address misalignment is generated by the target of control flow instructions, not
// the fetch itself.
assign misaligned = PCNextF [ 0 ] | ( PCNextF [ 1 ] & ~ `C_SUPPORTED ) ;
// do we really need to have check if the instruction is control flow? Yes
// Branches are updated in the execution stage but traps are updated in the memory stage.
2021-01-15 04:37:51 +00:00
// pipeline misaligned faults to M stage
assign BranchMisalignedFaultE = misaligned & PCSrcE ; // E-stage (Branch/Jump) misaligned
2021-02-08 04:21:55 +00:00
flopenr # ( 1 ) InstrMisalginedReg ( clk , reset , ~ StallM , BranchMisalignedFaultE , BranchMisalignedFaultM ) ;
2021-06-23 20:13:56 +00:00
// *** Ross Thompson. Check InstrMisalignedAdrM as I believe it is the same as PCF. Should be able to remove.
2021-02-08 04:21:55 +00:00
flopenr # ( `XLEN ) InstrMisalignedAdrReg ( clk , reset , ~ StallM , PCNextF , InstrMisalignedAdrM ) ;
2021-01-15 04:37:51 +00:00
assign TrapMisalignedFaultM = misaligned & PrivilegedChangePCM ;
assign InstrMisalignedFaultM = BranchMisalignedFaultM ; // | TrapMisalignedFaultM; *** put this back in without causing a cyclic path
2021-02-08 04:21:55 +00:00
flopenr # ( 32 ) InstrEReg ( clk , reset , ~ StallE , FlushE ? nop : InstrD , InstrE ) ;
flopenr # ( 32 ) InstrMReg ( clk , reset , ~ StallM , FlushM ? nop : InstrE , InstrM ) ;
flopenr # ( `XLEN ) PCEReg ( clk , reset , ~ StallE , PCD , PCE ) ;
flopenr # ( `XLEN ) PCMReg ( clk , reset , ~ StallM , PCE , PCM ) ;
2021-01-28 05:22:05 +00:00
2021-03-23 18:25:51 +00:00
2021-01-29 02:40:48 +00:00
// seems like there should be a lower-cost way of doing this PC+2 or PC+4 for JAL.
// either have ALU compute PC+2/4 and feed into ALUResult input of ResultMux or
// have dedicated adder in Mem stage based on PCM + 2 or 4
// *** redo this
2021-02-08 04:21:55 +00:00
flopenr # ( `XLEN ) PCPDReg ( clk , reset , ~ StallD , PCPlus2or4F , PCLinkD ) ;
flopenr # ( `XLEN ) PCPEReg ( clk , reset , ~ StallE , PCLinkD , PCLinkE ) ;
2021-01-15 04:37:51 +00:00
endmodule