refactor(Frontend): replace NamedUInt with EnumUInt (#4529)
	
		
			
	
		
	
	
		
			
				
	
				EMU Test / Changes Detection (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Generate Verilog (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - Basics (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - CHI (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - Performance (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - MC (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / SIMV - Basics (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Upload Artifacts (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Check Submodules (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Check Format (push) Has been cancelled
				
					Details
				
			
		
	
				
					
				
			
				
	
				EMU Test / Changes Detection (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Generate Verilog (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - Basics (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - CHI (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - Performance (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / EMU - MC (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / SIMV - Basics (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Upload Artifacts (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Check Submodules (push) Has been cancelled
				
					Details
				
			
		
			
				
	
				EMU Test / Check Format (push) Has been cancelled
				
					Details
				
			
		
	Use EnumUInt introduced by #4528 to do some compile-time check. Also: - add `class ExceptionType` to replace `ExceptionType.hasException(xxx)` with `xxx.hasException`, etc. - apply CamelCase to `BrType`.
This commit is contained in:
		
							parent
							
								
									3bfc5a3c90
								
							
						
					
					
						commit
						cbea99c932
					
				|  | @ -33,12 +33,12 @@ object PreDecodeInst { | |||
| 
 | ||||
|   val brTable = Array( | ||||
|     // C_JAL     -> List(BrType.jal), | ||||
|     C_EBREAK  -> List(BrType.notCFI), // c.ebreak should not be decoded as jalr, higher priority than c.jalr | ||||
|     C_J       -> List(BrType.jal), | ||||
|     C_JALR    -> List(BrType.jalr), | ||||
|     C_BRANCH  -> List(BrType.branch), | ||||
|     JAL       -> List(BrType.jal), | ||||
|     JALR      -> List(BrType.jalr), | ||||
|     BRANCH    -> List(BrType.branch) | ||||
|     C_EBREAK  -> List(BrType.NotCfi), // c.ebreak should not be decoded as jalr, higher priority than c.jalr | ||||
|     C_J       -> List(BrType.Jal), | ||||
|     C_JALR    -> List(BrType.Jalr), | ||||
|     C_BRANCH  -> List(BrType.Branch), | ||||
|     JAL       -> List(BrType.Jal), | ||||
|     JALR      -> List(BrType.Jalr), | ||||
|     BRANCH    -> List(BrType.Branch) | ||||
|   ) | ||||
| } | ||||
|  |  | |||
|  | @ -82,9 +82,9 @@ object Itype extends NamedUInt(4) { | |||
|   def jumpTypeGen(brType: UInt, rd: OpRegType, rs: OpRegType): UInt = { | ||||
| 
 | ||||
|     val isEqualRdRs = rd === rs | ||||
|     val isJal       = brType === BrType.jal | ||||
|     val isJalr      = brType === BrType.jalr | ||||
|     val isBranch    = brType === BrType.branch | ||||
|     val isJal       = brType === BrType.Jal | ||||
|     val isJalr      = brType === BrType.Jalr | ||||
|     val isBranch    = brType === BrType.Branch | ||||
| 
 | ||||
|     // push to RAS when rd is link, pop from RAS when rs is link | ||||
|     def isUninferableCall      = isJalr && rd.isLink && (!rs.isLink || rs.isLink && isEqualRdRs)  //8   push | ||||
|  |  | |||
|  | @ -24,7 +24,7 @@ import ftq.FtqRedirectSramEntry | |||
| import ftq.FtqRfComponents | ||||
| import org.chipsalliance.cde.config.Parameters | ||||
| import utility._ | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| import xiangshan._ | ||||
| import xiangshan.backend.GPAMemEntry | ||||
| import xiangshan.backend.fu.PMPRespBundle | ||||
|  | @ -88,7 +88,7 @@ class FtqICacheInfo(implicit p: Parameters) extends XSBundle with HasICacheParam | |||
| 
 | ||||
| class FtqToPrefetchBundle(implicit p: Parameters) extends XSBundle { | ||||
|   val req:              FtqICacheInfo = new FtqICacheInfo | ||||
|   val backendException: UInt          = ExceptionType() | ||||
|   val backendException: ExceptionType = new ExceptionType | ||||
| } | ||||
| 
 | ||||
| class FtqToFetchBundle(implicit p: Parameters) extends XSBundle with HasICacheParameters { | ||||
|  | @ -152,138 +152,94 @@ class mmioCommitRead(implicit p: Parameters) extends XSBundle { | |||
|   val mmioLastCommit = Input(Bool()) | ||||
| } | ||||
| 
 | ||||
| object ExceptionType extends NamedUInt(2) { | ||||
|   def none: UInt = "b00".U(width.W) | ||||
|   def pf:   UInt = "b01".U(width.W) // instruction page fault | ||||
|   def gpf:  UInt = "b10".U(width.W) // instruction guest page fault | ||||
|   def af:   UInt = "b11".U(width.W) // instruction access fault | ||||
| class ExceptionType extends Bundle { | ||||
|   val value: UInt = ExceptionType.Value() | ||||
| 
 | ||||
|   def hasException(e: UInt):             Bool = e =/= none | ||||
|   def hasException(e: Vec[UInt]):        Bool = e.map(_ =/= none).reduce(_ || _) | ||||
|   def hasException(e: IndexedSeq[UInt]): Bool = hasException(VecInit(e)) | ||||
|   def isNone: Bool = value === ExceptionType.Value.None | ||||
|   def isPf:   Bool = value === ExceptionType.Value.Pf | ||||
|   def isGpf:  Bool = value === ExceptionType.Value.Gpf | ||||
|   def isAf:   Bool = value === ExceptionType.Value.Af | ||||
| 
 | ||||
|   def fromOH(has_pf: Bool, has_gpf: Bool, has_af: Bool): UInt = { | ||||
|   def hasException: Bool = value =/= ExceptionType.Value.None | ||||
| 
 | ||||
|   /** merge exception from multiple sources, the leftmost one has higher priority | ||||
|    * @example {{{ | ||||
|    *   val itlbException = ExceptionType(io.itlb.resp.bits) | ||||
|    *   val pmpException = ExceptionType(io.pmp.resp) | ||||
|    * | ||||
|    *   // itlb has higher priority than pmp, as when itlb has exception, pAddr is not valid | ||||
|    *   val exception = itlbException || pmpException | ||||
|    * }}} | ||||
|    */ | ||||
|   def ||(that: ExceptionType): ExceptionType = | ||||
|     Mux(this.hasException, this, that) | ||||
| } | ||||
| 
 | ||||
| object ExceptionType { | ||||
|   private object Value extends EnumUInt(4) { | ||||
|     def None: UInt = 0.U(width.W) | ||||
|     def Pf:   UInt = 1.U(width.W) // instruction page fault | ||||
|     def Gpf:  UInt = 2.U(width.W) // instruction guest page fault | ||||
|     def Af:   UInt = 3.U(width.W) // instruction access fault | ||||
|   } | ||||
| 
 | ||||
|   def apply(that: UInt): ExceptionType = { | ||||
|     Value.assertLegal(that) | ||||
|     val e = Wire(new ExceptionType) | ||||
|     e.value := that | ||||
|     e | ||||
|   } | ||||
| 
 | ||||
|   def None: ExceptionType = apply(Value.None) | ||||
|   def Pf:   ExceptionType = apply(Value.Pf) | ||||
|   def Gpf:  ExceptionType = apply(Value.Gpf) | ||||
|   def Af:   ExceptionType = apply(Value.Af) | ||||
| 
 | ||||
|   def apply(hasPf: Bool, hasGpf: Bool, hasAf: Bool): ExceptionType = { | ||||
|     assert( | ||||
|       PopCount(VecInit(has_pf, has_gpf, has_af)) <= 1.U, | ||||
|       "ExceptionType.fromOH receives input that is not one-hot: pf=%d, gpf=%d, af=%d", | ||||
|       has_pf, | ||||
|       has_gpf, | ||||
|       has_af | ||||
|       PopCount(VecInit(hasPf, hasGpf, hasAf)) <= 1.U, | ||||
|       "ExceptionType receives input that is not one-hot: pf=%d, gpf=%d, af=%d", | ||||
|       hasPf, | ||||
|       hasGpf, | ||||
|       hasAf | ||||
|     ) | ||||
|     // input is at-most-one-hot encoded, so we don't worry about priority here. | ||||
|     MuxCase( | ||||
|       none, | ||||
|       None, | ||||
|       Seq( | ||||
|         has_pf  -> pf, | ||||
|         has_gpf -> gpf, | ||||
|         has_af  -> af | ||||
|         hasPf  -> Pf, | ||||
|         hasGpf -> Gpf, | ||||
|         hasAf  -> Af | ||||
|       ) | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   // only af is used most frequently (pmp / ecc / tilelink), so we define a shortcut | ||||
|   // we cannot use default parameter in apply(), as it is overloaded and scala won't allow | ||||
|   def apply(hasAf: Bool): ExceptionType = | ||||
|     apply(hasPf = false.B, hasGpf = false.B, hasAf = hasAf) | ||||
| 
 | ||||
|   // raise pf/gpf/af according to itlb response | ||||
|   def fromTlbResp(resp: TlbResp, useDup: Int = 0): UInt = { | ||||
|   def fromTlbResp(resp: TlbResp, useDup: Int = 0): ExceptionType = { | ||||
|     require(useDup >= 0 && useDup < resp.excp.length) | ||||
|     // itlb is guaranteed to respond at most one exception | ||||
|     fromOH( | ||||
|       resp.excp(useDup).pf.instr, | ||||
|       resp.excp(useDup).gpf.instr, | ||||
|       resp.excp(useDup).af.instr | ||||
|     apply( | ||||
|       hasPf = resp.excp(useDup).pf.instr, | ||||
|       hasGpf = resp.excp(useDup).gpf.instr, | ||||
|       hasAf = resp.excp(useDup).af.instr | ||||
|     ) | ||||
|   } | ||||
| 
 | ||||
|   // raise af if pmp check failed | ||||
|   def fromPMPResp(resp: PMPRespBundle): UInt = | ||||
|     Mux(resp.instr, af, none) | ||||
| 
 | ||||
|   // raise af if meta/data array ecc check failed or l2 cache respond with tilelink corrupt | ||||
|   /* FIXME: RISC-V Machine ISA v1.13 (draft) introduced a "hardware error" exception, described as: | ||||
|    * > A Hardware Error exception is a synchronous exception triggered when corrupted or | ||||
|    * > uncorrectable data is accessed explicitly or implicitly by an instruction. In this context, | ||||
|    * > "data" encompasses all types of information used within a RISC-V hart. Upon a hardware | ||||
|    * > error exception, the xepc register is set to the address of the instruction that attempted to | ||||
|    * > access corrupted data, while the xtval register is set either to 0 or to the virtual address | ||||
|    * > of an instruction fetch, load, or store that attempted to access corrupted data. The priority | ||||
|    * > of Hardware Error exception is implementation-defined, but any given occurrence is | ||||
|    * > generally expected to be recognized at the point in the overall priority order at which the | ||||
|    * > hardware error is discovered. | ||||
|    * Maybe it's better to raise hardware error instead of access fault when ECC check failed. | ||||
|    * But it's draft and XiangShan backend does not implement this exception code yet, so we still raise af here. | ||||
|    */ | ||||
|   def fromECC(enable: Bool, corrupt: Bool): UInt = | ||||
|     Mux(enable && corrupt, af, none) | ||||
| 
 | ||||
|   def fromTilelink(corrupt: Bool): UInt = | ||||
|     Mux(corrupt, af, none) | ||||
| 
 | ||||
|   /**Generates exception mux tree | ||||
|    * | ||||
|    * Exceptions that are further to the left in the parameter list have higher priority | ||||
|    * @example | ||||
|    * {{{ | ||||
|    *   val itlb_exception = ExceptionType.fromTlbResp(io.itlb.resp.bits) | ||||
|    *   // so as pmp_exception, meta_corrupt | ||||
|    *   // ExceptionType.merge(itlb_exception, pmp_exception, meta_corrupt) is equivalent to: | ||||
|    *   Mux( | ||||
|    *     itlb_exception =/= none, | ||||
|    *     itlb_exception, | ||||
|    *     Mux(pmp_exception =/= none, pmp_exception, meta_corrupt) | ||||
|    *   ) | ||||
|    * }}} | ||||
|    */ | ||||
|   def merge(exceptions: UInt*): UInt = { | ||||
| //    // recursively generate mux tree | ||||
| //    if (exceptions.length == 1) { | ||||
| //      require(exceptions.head.getWidth == width) | ||||
| //      exceptions.head | ||||
| //    } else { | ||||
| //      Mux(exceptions.head =/= none, exceptions.head, merge(exceptions.tail: _*)) | ||||
| //    } | ||||
|     // use MuxCase with default | ||||
|     exceptions.foreach(e => require(e.getWidth == width)) | ||||
|     val mapping = exceptions.init.map(e => (e =/= none) -> e) | ||||
|     val default = exceptions.last | ||||
|     MuxCase(default, mapping) | ||||
|   } | ||||
| 
 | ||||
|   /**Generates exception mux tree for multi-port exception vectors | ||||
|    * | ||||
|    * Exceptions that are further to the left in the parameter list have higher priority | ||||
|    * @example | ||||
|    * {{{ | ||||
|    *   val itlb_exception = VecInit((0 until PortNumber).map(i => ExceptionType.fromTlbResp(io.itlb(i).resp.bits))) | ||||
|    *   // so as pmp_exception, meta_corrupt | ||||
|    *   // ExceptionType.merge(itlb_exception, pmp_exception, meta_corrupt) is equivalent to: | ||||
|    *   VecInit((0 until PortNumber).map(i => Mux( | ||||
|    *     itlb_exception(i) =/= none, | ||||
|    *     itlb_exception(i), | ||||
|    *     Mux(pmp_exception(i) =/= none, pmp_exception(i), meta_corrupt(i)) | ||||
|    *   )) | ||||
|    * }}} | ||||
|    */ | ||||
|   def merge(exceptionVecs: Vec[UInt]*): Vec[UInt] = { | ||||
| //    // recursively generate mux tree | ||||
| //    if (exceptionVecs.length == 1) { | ||||
| //      exceptionVecs.head.foreach(e => require(e.getWidth == width)) | ||||
| //      exceptionVecs.head | ||||
| //    } else { | ||||
| //      require(exceptionVecs.head.length == exceptionVecs.last.length) | ||||
| //      VecInit((exceptionVecs.head zip merge(exceptionVecs.tail: _*)).map{ case (high, low) => | ||||
| //        Mux(high =/= none, high, low) | ||||
| //      }) | ||||
| //    } | ||||
|     // merge port-by-port | ||||
|     val length = exceptionVecs.head.length | ||||
|     exceptionVecs.tail.foreach(vec => require(vec.length == length)) | ||||
|     VecInit((0 until length).map(i => merge(exceptionVecs.map(_(i)): _*))) | ||||
|   } | ||||
|   def fromPmpResp(resp: PMPRespBundle): ExceptionType = | ||||
|     apply(hasAf = resp.instr) | ||||
| } | ||||
| 
 | ||||
| object BrType extends NamedUInt(2) { | ||||
|   def notCFI: UInt = "b00".U(width.W) | ||||
|   def branch: UInt = "b01".U(width.W) | ||||
|   def jal:    UInt = "b10".U(width.W) | ||||
|   def jalr:   UInt = "b11".U(width.W) | ||||
| object BrType extends EnumUInt(4) { | ||||
|   def NotCfi: UInt = 0.U(width.W) | ||||
|   def Branch: UInt = 1.U(width.W) | ||||
|   def Jal:    UInt = 2.U(width.W) | ||||
|   def Jalr:   UInt = 3.U(width.W) | ||||
| } | ||||
| 
 | ||||
| class PreDecodeInfo extends Bundle { // 8 bit | ||||
|  | @ -293,10 +249,10 @@ class PreDecodeInfo extends Bundle { // 8 bit | |||
|   val isCall = Bool() | ||||
|   val isRet  = Bool() | ||||
|   // val excType = UInt(3.W) | ||||
|   def isBr   = brType === BrType.branch | ||||
|   def isJal  = brType === BrType.jal | ||||
|   def isJalr = brType === BrType.jalr | ||||
|   def notCFI = brType === BrType.notCFI | ||||
|   def isBr   = brType === BrType.Branch | ||||
|   def isJal  = brType === BrType.Jal | ||||
|   def isJalr = brType === BrType.Jalr | ||||
|   def notCFI = brType === BrType.NotCfi | ||||
| } | ||||
| 
 | ||||
| class FetchToIBuffer(implicit p: Parameters) extends XSBundle { | ||||
|  | @ -307,7 +263,7 @@ class FetchToIBuffer(implicit p: Parameters) extends XSBundle { | |||
|   val foldpc           = Vec(PredictWidth, UInt(MemPredPCWidth.W)) | ||||
|   val ftqOffset        = Vec(PredictWidth, ValidUndirectioned(UInt(log2Ceil(PredictWidth).W))) | ||||
|   val backendException = Vec(PredictWidth, Bool()) | ||||
|   val exceptionType    = Vec(PredictWidth, ExceptionType()) | ||||
|   val exceptionType    = Vec(PredictWidth, new ExceptionType) | ||||
|   val crossPageIPFFix  = Vec(PredictWidth, Bool()) | ||||
|   val illegalInstr     = Vec(PredictWidth, Bool()) | ||||
|   val triggered        = Vec(PredictWidth, TriggerAction()) | ||||
|  |  | |||
|  | @ -49,6 +49,41 @@ class IBufferIO(implicit p: Parameters) extends XSBundle { | |||
|   val stallReason          = new StallReasonIO(DecodeWidth) | ||||
| } | ||||
| 
 | ||||
| object IBufferExceptionType extends EnumUInt(8) { | ||||
|   def None:        UInt = "b000".U(width.W) | ||||
|   def NonCrossPF:  UInt = "b001".U(width.W) | ||||
|   def NonCrossGPF: UInt = "b010".U(width.W) | ||||
|   def NonCrossAF:  UInt = "b011".U(width.W) | ||||
|   def RvcII:       UInt = "b100".U(width.W) // illegal instruction | ||||
|   def CrossPF:     UInt = "b101".U(width.W) | ||||
|   def CrossGPF:    UInt = "b110".U(width.W) | ||||
|   def CrossAF:     UInt = "b111".U(width.W) | ||||
| 
 | ||||
|   def cvtFromFetchExcpAndCrossPageAndRVCII(fetchExcp: ExceptionType, crossPage: Bool, rvcIll: Bool): UInt = | ||||
|     MuxCase( | ||||
|       0.U, | ||||
|       Seq( | ||||
|         crossPage              -> Cat(1.U(1.W), fetchExcp.value), | ||||
|         fetchExcp.hasException -> fetchExcp.value, | ||||
|         rvcIll                 -> this.RvcII | ||||
|       ) | ||||
|     ) | ||||
| 
 | ||||
|   def isRVCII(uint: UInt): Bool = { | ||||
|     this.checkInputWidth(uint) | ||||
|     uint(2) && uint(1, 0) === 0.U | ||||
|   } | ||||
| 
 | ||||
|   def isCrossPage(uint: UInt): Bool = { | ||||
|     this.checkInputWidth(uint) | ||||
|     uint(2) && uint(1, 0) =/= 0.U | ||||
|   } | ||||
| 
 | ||||
|   def isPF(uint:  UInt): Bool = uint(1, 0) === this.NonCrossPF(1, 0) | ||||
|   def isGPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossGPF(1, 0) | ||||
|   def isAF(uint:  UInt): Bool = uint(1, 0) === this.NonCrossAF(1, 0) | ||||
| } | ||||
| 
 | ||||
| class IBufEntry(implicit p: Parameters) extends XSBundle { | ||||
|   val inst             = UInt(32.W) | ||||
|   val pc               = PrunedAddr(VAddrBits) | ||||
|  | @ -109,48 +144,6 @@ class IBufEntry(implicit p: Parameters) extends XSBundle { | |||
|     cf.debug_seqNum                      := debug_seqNum | ||||
|     cf | ||||
|   } | ||||
| 
 | ||||
|   object IBufferExceptionType extends NamedUInt(3) { | ||||
|     def None        = "b000".U | ||||
|     def NonCrossPF  = "b001".U | ||||
|     def NonCrossGPF = "b010".U | ||||
|     def NonCrossAF  = "b011".U | ||||
|     // illegal instruction | ||||
|     def rvcII    = "b100".U | ||||
|     def CrossPF  = "b101".U | ||||
|     def CrossGPF = "b110".U | ||||
|     def CrossAF  = "b111".U | ||||
| 
 | ||||
|     def cvtFromFetchExcpAndCrossPageAndRVCII(fetchExcp: UInt, crossPage: Bool, rvcIll: Bool): UInt = { | ||||
|       require( | ||||
|         fetchExcp.getWidth == ExceptionType.width, | ||||
|         s"The width(${fetchExcp.getWidth}) of fetchExcp should be equal to " + | ||||
|           s"the width(${ExceptionType.width}) of frontend.ExceptionType." | ||||
|       ) | ||||
|       MuxCase( | ||||
|         0.U, | ||||
|         Seq( | ||||
|           crossPage     -> Cat(1.U(1.W), fetchExcp), | ||||
|           fetchExcp.orR -> fetchExcp, | ||||
|           rvcIll        -> this.rvcII | ||||
|         ) | ||||
|       ) | ||||
|     } | ||||
| 
 | ||||
|     def isRVCII(uint: UInt): Bool = { | ||||
|       this.checkInputWidth(uint) | ||||
|       uint(2) && uint(1, 0) === 0.U | ||||
|     } | ||||
| 
 | ||||
|     def isCrossPage(uint: UInt): Bool = { | ||||
|       this.checkInputWidth(uint) | ||||
|       uint(2) && uint(1, 0) =/= 0.U | ||||
|     } | ||||
| 
 | ||||
|     def isPF(uint:  UInt): Bool = uint(1, 0) === this.NonCrossPF(1, 0) | ||||
|     def isGPF(uint: UInt): Bool = uint(1, 0) === this.NonCrossGPF(1, 0) | ||||
|     def isAF(uint:  UInt): Bool = uint(1, 0) === this.NonCrossAF(1, 0) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| class IBuffer(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper with HasPerfEvents { | ||||
|  |  | |||
|  | @ -159,13 +159,13 @@ class Ftq(implicit p: Parameters) extends FtqModule | |||
|   // raises IPF or IAF, which is ifuWbPtr_write or IfuPtr_write. | ||||
|   // Only when IFU has written back that FTQ entry can backendIpf and backendIaf be false because this | ||||
|   // makes sure that IAF and IPF are correctly raised instead of being flushed by redirect requests. | ||||
|   val backendException  = RegInit(ExceptionType.none) | ||||
|   val backendException  = RegInit(ExceptionType.None) | ||||
|   val backendPcFaultPtr = RegInit(FtqPtr(false.B, 0.U)) | ||||
|   when(fromBackendRedirect.valid) { | ||||
|     backendException := ExceptionType.fromOH( | ||||
|       has_pf = fromBackendRedirect.bits.cfiUpdate.backendIPF, | ||||
|       has_gpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF, | ||||
|       has_af = fromBackendRedirect.bits.cfiUpdate.backendIAF | ||||
|     backendException := ExceptionType( | ||||
|       hasPf = fromBackendRedirect.bits.cfiUpdate.backendIPF, | ||||
|       hasGpf = fromBackendRedirect.bits.cfiUpdate.backendIGPF, | ||||
|       hasAf = fromBackendRedirect.bits.cfiUpdate.backendIAF | ||||
|     ) | ||||
|     when( | ||||
|       fromBackendRedirect.bits.cfiUpdate.backendIPF || fromBackendRedirect.bits.cfiUpdate.backendIGPF || | ||||
|  | @ -174,7 +174,7 @@ class Ftq(implicit p: Parameters) extends FtqModule | |||
|       backendPcFaultPtr := ifuWbPtr_write | ||||
|     } | ||||
|   }.elsewhen(ifuWbPtr =/= backendPcFaultPtr) { | ||||
|     backendException := ExceptionType.none | ||||
|     backendException := ExceptionType.None | ||||
|   } | ||||
| 
 | ||||
|   // ********************************************************************** | ||||
|  | @ -473,7 +473,7 @@ class Ftq(implicit p: Parameters) extends FtqModule | |||
|     copy.ftqIdx := ifuPtr | ||||
|   } | ||||
|   io.toICache.fetchReq.bits.isBackendException := | ||||
|     ExceptionType.hasException(backendException) && backendPcFaultPtr === ifuPtr | ||||
|     backendException.hasException && backendPcFaultPtr === ifuPtr | ||||
| 
 | ||||
|   io.toICache.prefetchReq.valid := toPrefetchEntryToSend && pfPtr =/= bpuPtr | ||||
|   io.toICache.prefetchReq.bits.req.fromFtqPcBundle(toPrefetchPcBundle) | ||||
|  | @ -481,7 +481,7 @@ class Ftq(implicit p: Parameters) extends FtqModule | |||
|   io.toICache.prefetchReq.bits.backendException := Mux( | ||||
|     backendPcFaultPtr === pfPtr, | ||||
|     backendException, | ||||
|     ExceptionType.none | ||||
|     ExceptionType.None | ||||
|   ) | ||||
|   // io.toICache.fetchReq.bits.bypassSelect := last_cycle_bpu_in && bpu_in_bypass_ptr === ifuPtr | ||||
|   // io.toICache.fetchReq.bits.bpuBypassWrite.zipWithIndex.map{case(bypassWrtie, i) => | ||||
|  |  | |||
|  | @ -161,14 +161,14 @@ class ReplacerVictimBundle(implicit p: Parameters) extends ICacheBundle { | |||
| /* ***** MainPipe ***** */ | ||||
| // ICache(MainPipe) -> IFU | ||||
| class ICacheRespBundle(implicit p: Parameters) extends ICacheBundle { | ||||
|   val doubleline:         Bool            = Bool() | ||||
|   val vAddr:              Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(VAddrBits)) | ||||
|   val data:               UInt            = UInt(blockBits.W) | ||||
|   val pAddr:              Vec[PrunedAddr] = Vec(PortNumber, PrunedAddr(PAddrBits)) | ||||
|   val exception:          Vec[UInt]       = Vec(PortNumber, ExceptionType()) | ||||
|   val pmpMmio:            Vec[Bool]       = Vec(PortNumber, Bool()) | ||||
|   val itlbPbmt:           Vec[UInt]       = Vec(PortNumber, UInt(Pbmt.width.W)) | ||||
|   val isBackendException: Bool            = Bool() | ||||
|   val doubleline:         Bool               = Bool() | ||||
|   val vAddr:              Vec[PrunedAddr]    = Vec(PortNumber, PrunedAddr(VAddrBits)) | ||||
|   val data:               UInt               = UInt(blockBits.W) | ||||
|   val pAddr:              Vec[PrunedAddr]    = Vec(PortNumber, PrunedAddr(PAddrBits)) | ||||
|   val exception:          Vec[ExceptionType] = Vec(PortNumber, new ExceptionType) | ||||
|   val pmpMmio:            Vec[Bool]          = Vec(PortNumber, Bool()) | ||||
|   val itlbPbmt:           Vec[UInt]          = Vec(PortNumber, UInt(Pbmt.width.W)) | ||||
|   val isBackendException: Bool               = Bool() | ||||
|   /* NOTE: GPAddrBits(=50bit) is not enough for gpAddr here, refer to PR#3795 | ||||
|    * Sv48*4 only allows 50bit gpAddr, when software violates this requirement | ||||
|    * it needs to fill the mtval2 register with the full XLEN(=64bit) gpAddr, | ||||
|  | @ -181,11 +181,11 @@ class ICacheRespBundle(implicit p: Parameters) extends ICacheBundle { | |||
| 
 | ||||
| /* ***** PrefetchPipe ***** */ | ||||
| class PrefetchReqBundle(implicit p: Parameters) extends ICacheBundle { | ||||
|   val startAddr:        PrunedAddr = PrunedAddr(VAddrBits) | ||||
|   val nextlineStart:    PrunedAddr = PrunedAddr(VAddrBits) | ||||
|   val ftqIdx:           FtqPtr     = new FtqPtr | ||||
|   val isSoftPrefetch:   Bool       = Bool() | ||||
|   val backendException: UInt       = ExceptionType() | ||||
|   val startAddr:        PrunedAddr    = PrunedAddr(VAddrBits) | ||||
|   val nextlineStart:    PrunedAddr    = PrunedAddr(VAddrBits) | ||||
|   val ftqIdx:           FtqPtr        = new FtqPtr | ||||
|   val isSoftPrefetch:   Bool          = Bool() | ||||
|   val backendException: ExceptionType = new ExceptionType | ||||
| 
 | ||||
|   def crossCacheline: Bool = startAddr(blockOffBits - 1) === 1.U | ||||
| 
 | ||||
|  | @ -214,12 +214,12 @@ class PrefetchReqBundle(implicit p: Parameters) extends ICacheBundle { | |||
|  *      to save area, we separate those signals from WayLookupEntry and store only once. | ||||
|  */ | ||||
| class WayLookupEntry(implicit p: Parameters) extends ICacheBundle { | ||||
|   val vSetIdx:       Vec[UInt] = Vec(PortNumber, UInt(idxBits.W)) | ||||
|   val waymask:       Vec[UInt] = Vec(PortNumber, UInt(nWays.W)) | ||||
|   val pTag:          Vec[UInt] = Vec(PortNumber, UInt(tagBits.W)) | ||||
|   val itlbException: Vec[UInt] = Vec(PortNumber, ExceptionType()) | ||||
|   val itlbPbmt:      Vec[UInt] = Vec(PortNumber, UInt(Pbmt.width.W)) | ||||
|   val metaCodes:     Vec[UInt] = Vec(PortNumber, UInt(ICacheMetaCodeBits.W)) | ||||
|   val vSetIdx:       Vec[UInt]          = Vec(PortNumber, UInt(idxBits.W)) | ||||
|   val waymask:       Vec[UInt]          = Vec(PortNumber, UInt(nWays.W)) | ||||
|   val pTag:          Vec[UInt]          = Vec(PortNumber, UInt(tagBits.W)) | ||||
|   val itlbException: Vec[ExceptionType] = Vec(PortNumber, new ExceptionType) | ||||
|   val itlbPbmt:      Vec[UInt]          = Vec(PortNumber, UInt(Pbmt.width.W)) | ||||
|   val metaCodes:     Vec[UInt]          = Vec(PortNumber, UInt(ICacheMetaCodeBits.W)) | ||||
| } | ||||
| 
 | ||||
| class WayLookupGpfEntry(implicit p: Parameters) extends ICacheBundle { | ||||
|  | @ -233,14 +233,14 @@ class WayLookupBundle(implicit p: Parameters) extends ICacheBundle { | |||
|   val gpf   = new WayLookupGpfEntry | ||||
| 
 | ||||
|   // for compatibility | ||||
|   def vSetIdx:           Vec[UInt]  = entry.vSetIdx | ||||
|   def waymask:           Vec[UInt]  = entry.waymask | ||||
|   def pTag:              Vec[UInt]  = entry.pTag | ||||
|   def itlbException:     Vec[UInt]  = entry.itlbException | ||||
|   def itlbPbmt:          Vec[UInt]  = entry.itlbPbmt | ||||
|   def metaCodes:         Vec[UInt]  = entry.metaCodes | ||||
|   def gpAddr:            PrunedAddr = gpf.gpAddr | ||||
|   def isForVSnonLeafPTE: Bool       = gpf.isForVSnonLeafPTE | ||||
|   def vSetIdx:           Vec[UInt]          = entry.vSetIdx | ||||
|   def waymask:           Vec[UInt]          = entry.waymask | ||||
|   def pTag:              Vec[UInt]          = entry.pTag | ||||
|   def itlbException:     Vec[ExceptionType] = entry.itlbException | ||||
|   def itlbPbmt:          Vec[UInt]          = entry.itlbPbmt | ||||
|   def metaCodes:         Vec[UInt]          = entry.metaCodes | ||||
|   def gpAddr:            PrunedAddr         = gpf.gpAddr | ||||
|   def isForVSnonLeafPTE: Bool               = gpf.isForVSnonLeafPTE | ||||
| } | ||||
| 
 | ||||
| /* ***** Miss ***** */ | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ import freechips.rocketchip.regmapper.RegReadFn | |||
| import freechips.rocketchip.regmapper.RegWriteFn | ||||
| import freechips.rocketchip.tilelink.TLRegisterNode | ||||
| import org.chipsalliance.cde.config.Parameters | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| import xiangshan.frontend.PrunedAddrInit | ||||
| 
 | ||||
| // currently for ECC control only | ||||
|  | @ -61,7 +61,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e | |||
| 
 | ||||
|     // eccCtrl.ierror: inject error code | ||||
|     private def nInjError: Int = 8 | ||||
|     private object EccCtrlInjError extends NamedUInt(log2Up(nInjError)) { | ||||
|     private object EccCtrlInjError extends EnumUInt(nInjError) { | ||||
|       def NotEnabled:    UInt = 0.U(width.W) // try to inject when ECC check is not enabled | ||||
|       def TargetInvalid: UInt = 1.U(width.W) // try to inject to invalid(rsvd) eccCtrl.itarget | ||||
|       def NotFound:      UInt = 2.U(width.W) // try to inject to eccIAddr.pAddr does not exist in ICache | ||||
|  | @ -78,7 +78,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e | |||
|     } | ||||
|     // eccCtrl.istatus: inject status | ||||
|     private def nInjStatus: Int = 8 | ||||
|     private object EccCtrlInjStatus extends NamedUInt(log2Up(nInjStatus)) { | ||||
|     private object EccCtrlInjStatus extends EnumUInt(nInjStatus) { | ||||
|       def Idle:     UInt = 0.U(width.W) | ||||
|       def Working:  UInt = 1.U(width.W) | ||||
|       def Injected: UInt = 2.U(width.W) | ||||
|  | @ -94,7 +94,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e | |||
|     } | ||||
|     // eccCtrl.itarget: inject target | ||||
|     private def nInjTarget: Int = 4 | ||||
|     private object EccCtrlInjTarget extends NamedUInt(log2Up(nInjTarget)) { | ||||
|     private object EccCtrlInjTarget extends EnumUInt(nInjTarget) { | ||||
|       def MetaArray: UInt = 0.U(width.W) | ||||
|       def DataArray: UInt = 2.U(width.W) | ||||
|       @unused | ||||
|  | @ -151,7 +151,7 @@ class ICacheCtrlUnit(params: ICacheCtrlUnitParameters)(implicit p: Parameters) e | |||
| 
 | ||||
|     // inject FSM | ||||
|     private def nInjectFsmState: Int = 5 | ||||
|     private object InjectFsmState extends NamedUInt(log2Up(nInjectFsmState)) { | ||||
|     private object InjectFsmState extends EnumUInt(nInjectFsmState) { | ||||
|       // scala ask identifier that begins with uppercase cannot be used in pattern matching like `X :: Nil = Enum()` | ||||
|       // but we want UpperCamelCase for constants for better readability, so we dont use Enum() here | ||||
|       def Idle:         UInt = 0.U(width.W) | ||||
|  |  | |||
|  | @ -224,14 +224,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|     p.bits.size := 3.U | ||||
|     p.bits.cmd  := TlbCmd.exec | ||||
|   } | ||||
|   private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPMPResp)) | ||||
|   private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPmpResp)) | ||||
|   private val s1_pmpMmio      = VecInit(fromPmp.map(_.mmio)) | ||||
| 
 | ||||
|   // merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next | ||||
|   private val s1_exceptionOut = ExceptionType.merge( | ||||
|     s1_itlbException, | ||||
|     s1_pmpException | ||||
|   ) | ||||
|   private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p }) | ||||
| 
 | ||||
|   /** | ||||
|     ****************************************************************************** | ||||
|  | @ -418,7 +415,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|   private val s2_shouldFetch = VecInit((0 until PortNumber).map { i => | ||||
|     (!s2_hits(i) || s2_corruptRefetch(i)) && | ||||
|     (if (i == 0) true.B else s2_doubleline) && | ||||
|     !ExceptionType.hasException(s2_exception.take(i + 1)) && | ||||
|     s2_exception.take(i + 1).map(_.isNone).reduce(_ && _) && | ||||
|     s2_isMmio.take(i + 1).map(!_).reduce(_ && _) | ||||
|   }) | ||||
| 
 | ||||
|  | @ -446,14 +443,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|   private val s2_fetchFinish = !s2_shouldFetch.reduce(_ || _) | ||||
| 
 | ||||
|   // also raise af if l2 corrupt is detected | ||||
|   private val s2_l2Exception = VecInit(s2_l2Corrupt.map(ExceptionType.fromTilelink)) | ||||
|   private val s2_l2Exception = VecInit(s2_l2Corrupt.map(corrupt => ExceptionType(hasAf = corrupt))) | ||||
|   // NOTE: do NOT raise af if meta/data corrupt is detected, they are automatically recovered by re-fetching from L2 | ||||
| 
 | ||||
|   // merge s2 exceptions, itlb has the highest priority, then l2 | ||||
|   private val s2_exceptionOut = ExceptionType.merge( | ||||
|     s2_exception, // includes itlb/pmp exception | ||||
|     s2_l2Exception | ||||
|   ) | ||||
|   // merge s2 exceptions, itlb/pmp has the highest priority, then l2 | ||||
|   private val s2_exceptionOut = VecInit((s2_exception zip s2_l2Exception).map { case (in, l2) => in || l2 }) | ||||
| 
 | ||||
|   /** | ||||
|     ****************************************************************************** | ||||
|  | @ -468,7 +462,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|   toIfu.bits.pAddr              := s2_pAddr | ||||
|   (0 until PortNumber).foreach { i => | ||||
|     val needThisLine = if (i == 0) true.B else s2_doubleline | ||||
|     toIfu.bits.exception(i) := Mux(needThisLine, s2_exceptionOut(i), ExceptionType.none) | ||||
|     toIfu.bits.exception(i) := Mux(needThisLine, s2_exceptionOut(i), ExceptionType.None) | ||||
|     toIfu.bits.pmpMmio(i)   := Mux(needThisLine, s2_pmpMmio(i), false.B) | ||||
|     toIfu.bits.itlbPbmt(i)  := Mux(needThisLine, s2_itlbPbmt(i), Pbmt.pma) | ||||
|   } | ||||
|  | @ -507,11 +501,11 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|   io.perf.hit0Miss1    := s2_hits(0) && !s2_hits(1) && s2_doubleline | ||||
|   io.perf.miss0Hit1    := !s2_hits(0) && s2_hits(1) && s2_doubleline | ||||
|   io.perf.miss0Miss1   := !s2_hits(0) && !s2_hits(1) && s2_doubleline | ||||
|   io.perf.hit0Except1  := s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline | ||||
|   io.perf.miss0Except1 := !s2_hits(0) && ExceptionType.hasException(s2_exception(1)) && s2_doubleline | ||||
|   io.perf.hit0Except1  := s2_hits(0) && s2_exception(1).hasException && s2_doubleline | ||||
|   io.perf.miss0Except1 := !s2_hits(0) && s2_exception(1).hasException && s2_doubleline | ||||
|   io.perf.bankHit(0)   := s2_hits(0) | ||||
|   io.perf.bankHit(1)   := s2_hits(1) && s2_doubleline | ||||
|   io.perf.except0      := ExceptionType.hasException(s2_exception(0)) | ||||
|   io.perf.except0      := s2_exception(0).hasException | ||||
|   io.perf.hit          := s2_hits(0) && (!s2_doubleline || s2_hits(1)) | ||||
| 
 | ||||
|   /** <PERF> fetch bubble generated by icache miss */ | ||||
|  | @ -553,7 +547,7 @@ class ICacheMainPipe(implicit p: Parameters) extends ICacheModule | |||
|     */ | ||||
|   if (env.EnableDifftest) { | ||||
|     val discards = (0 until PortNumber).map { i => | ||||
|       ExceptionType.hasException(toIfu.bits.exception(i)) || | ||||
|       toIfu.bits.exception(i).hasException || | ||||
|       toIfu.bits.pmpMmio(i) || | ||||
|       Pbmt.isUncache(toIfu.bits.itlbPbmt(i)) | ||||
|     } | ||||
|  |  | |||
|  | @ -22,13 +22,12 @@ import utility.DataHoldBypass | |||
| import utility.PriorityMuxDefault | ||||
| import utility.ValidHold | ||||
| import utility.XSPerfAccumulate | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| import xiangshan.cache.mmu.Pbmt | ||||
| import xiangshan.cache.mmu.TlbCmd | ||||
| import xiangshan.cache.mmu.TlbRequestIO | ||||
| import xiangshan.cache.mmu.ValidHoldBypass // FIXME: should move this to utility? | ||||
| import xiangshan.frontend.ExceptionType | ||||
| import xiangshan.frontend.PrunedAddr | ||||
| import xiangshan.frontend.PrunedAddrInit | ||||
| import xiangshan.frontend.ftq.BpuFlushInfo | ||||
| 
 | ||||
|  | @ -117,7 +116,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|   private val s1_backendException = RegEnable(s0_backendException, 0.U.asTypeOf(s0_backendException), s0_fire) | ||||
| 
 | ||||
|   private def nS1FsmState: Int = 5 | ||||
|   private object S1FsmState extends NamedUInt(log2Up(nS1FsmState)) { | ||||
|   private object S1FsmState extends EnumUInt(nS1FsmState) { | ||||
|     def Idle:       UInt = 0.U(width.W) | ||||
|     def ItlbResend: UInt = 1.U(width.W) | ||||
|     def MetaResend: UInt = 2.U(width.W) | ||||
|  | @ -185,7 +184,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|     Mux(tlbValidPulse(i), s1_pAddrWire(i), s1_pAddrReg(i)) | ||||
|   }) | ||||
|   private val s1_itlbExceptionRaw = VecInit((0 until PortNumber).map { i => | ||||
|     DataHoldBypass(ExceptionType.fromTlbResp(fromItlb(i).bits), 0.U(ExceptionType.width.W), tlbValidPulse(i)) | ||||
|     DataHoldBypass(ExceptionType.fromTlbResp(fromItlb(i).bits), ExceptionType.None, tlbValidPulse(i)) | ||||
|   }) | ||||
|   private val s1_itlbPbmt = VecInit((0 until PortNumber).map { i => | ||||
|     DataHoldBypass(fromItlb(i).bits.pbmt(0), 0.U.asTypeOf(fromItlb(i).bits.pbmt(0)), tlbValidPulse(i)) | ||||
|  | @ -207,10 +206,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|   // merge backend exception and itlb exception | ||||
|   // for area concern, we don't have 64 bits vaddr in frontend, but spec asks page fault when high bits are not all 0/1 | ||||
|   // this check is finished in backend, and passed to frontend with redirect, we see it as a part of itlb exception | ||||
|   private val s1_itlbException = ExceptionType.merge( | ||||
|     s1_backendException, | ||||
|     s1_itlbExceptionRaw | ||||
|   ) | ||||
|   private val s1_itlbException = VecInit((s1_backendException zip s1_itlbExceptionRaw).map { case (b, i) => b || i }) | ||||
|   // debug | ||||
|   dontTouch(s1_itlbExceptionRaw) | ||||
|   dontTouch(s1_itlbException) | ||||
|  | @ -221,7 +217,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|    *       see GPAMem: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/backend/GPAMem.scala#L33-L34 | ||||
|    *       see also: https://github.com/OpenXiangShan/XiangShan/blob/344cf5d55568dd40cd658a9ee66047a505eeb504/src/main/scala/xiangshan/frontend/IFU.scala#L374-L375 | ||||
|    */ | ||||
|   private val s1_itlbExceptionIsGpf = VecInit(s1_itlbException.map(_ === ExceptionType.gpf)) | ||||
|   private val s1_itlbExceptionIsGpf = VecInit(s1_itlbException.map(_.isGpf)) | ||||
|   private val s1_gpAddr = PriorityMuxDefault( | ||||
|     s1_itlbExceptionIsGpf zip (0 until PortNumber).map(i => s1_gpAddrRaw(i) - (i << blockOffBits).U), | ||||
|     0.U.asTypeOf(s1_gpAddrRaw(0)) | ||||
|  | @ -326,7 +322,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|     toWayLookup.bits.itlbException(i) := Mux( | ||||
|       excpValid, | ||||
|       s1_itlbException(i), // includes backend exception | ||||
|       ExceptionType.none | ||||
|       ExceptionType.None | ||||
|     ) | ||||
|     toWayLookup.bits.itlbPbmt(i) := Mux(excpValid, s1_itlbPbmt(i), Pbmt.pma) | ||||
|   } | ||||
|  | @ -359,15 +355,12 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|     p.bits.size := 3.U | ||||
|     p.bits.cmd  := TlbCmd.exec | ||||
|   } | ||||
|   private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPMPResp)) | ||||
|   private val s1_pmpException = VecInit(fromPmp.map(ExceptionType.fromPmpResp)) | ||||
|   private val s1_pmpMmio      = VecInit(fromPmp.map(_.mmio)) | ||||
| 
 | ||||
|   // merge s1 itlb/pmp exceptions, itlb has the highest priority, pmp next | ||||
|   // for timing consideration, meta_corrupt is not merged, and it will NOT cancel prefetch | ||||
|   private val s1_exceptionOut = ExceptionType.merge( | ||||
|     s1_itlbException, // includes backend exception | ||||
|     s1_pmpException | ||||
|   ) | ||||
|   // here, itlb exception includes backend exception | ||||
|   private val s1_exceptionOut = VecInit((s1_itlbException zip s1_pmpException).map { case (i, p) => i || p }) | ||||
| 
 | ||||
|   // merge pmp mmio and itlb pbmt | ||||
|   private val s1_isMmio = VecInit((s1_pmpMmio zip s1_itlbPbmt).map { case (mmio, pbmt) => | ||||
|  | @ -503,7 +496,7 @@ class ICachePrefetchPipe(implicit p: Parameters) extends ICacheModule | |||
|    */ | ||||
|   private val s2_miss = VecInit((0 until PortNumber).map { i => | ||||
|     !s2_hits(i) && (if (i == 0) true.B else s2_doubleline) && | ||||
|     !ExceptionType.hasException(s2_exception.take(i + 1)) && | ||||
|     s2_exception.take(i + 1).map(_.isNone).reduce(_ && _) && | ||||
|     s2_isMmio.take(i + 1).map(!_).reduce(_ && _) | ||||
|   }) | ||||
| 
 | ||||
|  |  | |||
|  | @ -123,7 +123,7 @@ class ICacheWayLookup(implicit p: Parameters) extends ICacheModule with ICacheMi | |||
|   io.write.ready := !full && !gpfStall | ||||
|   when(io.write.fire) { | ||||
|     entries(writePtr.value) := io.write.bits.entry | ||||
|     when(io.write.bits.itlbException.map(_ === ExceptionType.gpf).reduce(_ || _)) { | ||||
|     when(io.write.bits.itlbException.map(_.isGpf).reduce(_ || _)) { | ||||
|       // if gpfEntry is bypassed, we don't need to save it | ||||
|       // note this will override the read (L156) | ||||
|       gpfEntry.valid := !(canBypass && io.read.fire) | ||||
|  |  | |||
|  | @ -18,7 +18,7 @@ package xiangshan.frontend.ifu | |||
| import chisel3._ | ||||
| import chisel3.util._ | ||||
| import org.chipsalliance.cde.config.Parameters | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| import xiangshan.frontend.PrunedAddr | ||||
| 
 | ||||
| /* *** | ||||
|  | @ -32,14 +32,14 @@ import xiangshan.frontend.PrunedAddr | |||
|  * *** */ | ||||
| 
 | ||||
| /* ***** PreDecode ***** */ | ||||
| object PreDecodeFaultType extends NamedUInt(3) { | ||||
|   def noFault:      UInt = "b000".U(width.W) | ||||
|   def jalFault:     UInt = "b001".U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def retFault:     UInt = "b010".U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def targetFault:  UInt = "b011".U(width.W) | ||||
|   def notCfiFault:  UInt = "b100".U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def invalidTaken: UInt = "b101".U(width.W) | ||||
|   def jalrFault:    UInt = "b110".U(width.W) | ||||
| object PreDecodeFaultType extends EnumUInt(7) { | ||||
|   def NoFault:      UInt = 0.U(width.W) | ||||
|   def JalFault:     UInt = 1.U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def RetFault:     UInt = 2.U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def TargetFault:  UInt = 3.U(width.W) | ||||
|   def NotCfiFault:  UInt = 4.U(width.W) // not CFI taken or invalid instruction taken | ||||
|   def InvalidTaken: UInt = 5.U(width.W) | ||||
|   def JalrFault:    UInt = 6.U(width.W) | ||||
| } | ||||
| 
 | ||||
| /* ***** Ifu last half ***** */ | ||||
|  |  | |||
|  | @ -31,14 +31,14 @@ trait PreDecodeHelper extends HasXSParameter { | |||
|   def isLink(reg: UInt): Bool = reg === 1.U || reg === 5.U | ||||
| 
 | ||||
|   def getBrType(inst: UInt): UInt = | ||||
|     ListLookup(inst, List(BrType.notCFI), PreDecodeInst.brTable).head | ||||
|     ListLookup(inst, List(BrType.NotCfi), PreDecodeInst.brTable).head | ||||
| 
 | ||||
|   def getBrInfo(inst: UInt): (UInt, Bool, Bool) = { | ||||
|     val brType = getBrType(inst) | ||||
|     val rd     = Mux(isRVC(inst), inst(12), inst(11, 7)) | ||||
|     val rs     = Mux(isRVC(inst), Mux(brType === BrType.jal, 0.U, inst(11, 7)), inst(19, 15)) | ||||
|     val isCall = (brType === BrType.jal && !isRVC(inst) || brType === BrType.jalr) && isLink(rd) // Only for RV64 | ||||
|     val isRet  = brType === BrType.jalr && isLink(rs) && !isCall | ||||
|     val rs     = Mux(isRVC(inst), Mux(brType === BrType.Jal, 0.U, inst(11, 7)), inst(19, 15)) | ||||
|     val isCall = (brType === BrType.Jal && !isRVC(inst) || brType === BrType.Jalr) && isLink(rd) // Only for RV64 | ||||
|     val isRet  = brType === BrType.Jalr && isLink(rs) && !isCall | ||||
|     (brType, isCall, isRet) | ||||
|   } | ||||
| 
 | ||||
|  |  | |||
|  | @ -32,7 +32,7 @@ import utility.XSDebug | |||
| import utility.XSError | ||||
| import utility.XSPerfAccumulate | ||||
| import utility.XSPerfHistogram | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| import xiangshan.FrontendTdataDistributeIO | ||||
| import xiangshan.RedirectLevel | ||||
| import xiangshan.RobCommitInfo | ||||
|  | @ -331,21 +331,19 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
| 
 | ||||
|   // FIXME: raise af if one fetch block crosses the cacheable/un-cacheable boundary, might not correct | ||||
|   private val s2_mmioMismatchException = VecInit(Seq( | ||||
|     ExceptionType.none, // mark the exception only on the second line | ||||
|     Mux( | ||||
|       // not double-line, skip check | ||||
|       !fromICache.bits.doubleline || ( | ||||
|     ExceptionType.None, // mark the exception only on the second line | ||||
|     ExceptionType(hasAf = | ||||
|       // if not double-line, skip check | ||||
|       fromICache.bits.doubleline && ( | ||||
|         // is double-line, ask for consistent pmp_mmio and itlb_pbmt value | ||||
|         fromICache.bits.pmpMmio(0) === fromICache.bits.pmpMmio(1) && | ||||
|           fromICache.bits.itlbPbmt(0) === fromICache.bits.itlbPbmt(1) | ||||
|       ), | ||||
|       ExceptionType.none, | ||||
|       ExceptionType.af | ||||
|         fromICache.bits.pmpMmio(0) =/= fromICache.bits.pmpMmio(1) || | ||||
|           fromICache.bits.itlbPbmt(0) =/= fromICache.bits.itlbPbmt(1) | ||||
|       ) | ||||
|     ) | ||||
|   )) | ||||
| 
 | ||||
|   // merge exceptions | ||||
|   private val s2_exception = ExceptionType.merge(s2_exceptionIn, s2_mmioMismatchException) | ||||
|   private val s2_exception = VecInit((s2_exceptionIn zip s2_mmioMismatchException).map { case (in, m) => in || m }) | ||||
| 
 | ||||
|   // we need only the first port, as the second is asked to be the same | ||||
|   private val s2_pmpMmio  = fromICache.bits.pmpMmio(0) | ||||
|  | @ -379,7 +377,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|   private val s2_instrRange = s2_jumpRange & s2_ftrRange | ||||
|   private val s2_exceptionVec = VecInit((0 until PredictWidth).map(i => | ||||
|     MuxCase( | ||||
|       ExceptionType.none, | ||||
|       ExceptionType.None, | ||||
|       Seq( | ||||
|         !isNextLine(s2_pc(i), s2_ftqReq.startAddr)                   -> s2_exception(0), | ||||
|         (isNextLine(s2_pc(i), s2_ftqReq.startAddr) && s2_doubleline) -> s2_exception(1) | ||||
|  | @ -454,9 +452,9 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|    */ | ||||
|   private val s2_crossPageExceptionVec = VecInit((0 until PredictWidth).map { i => | ||||
|     Mux( | ||||
|       isLastInLine(s2_pc(i)) && !s2_pd(i).isRVC && s2_doubleline && !ExceptionType.hasException(s2_exception(0)), | ||||
|       isLastInLine(s2_pc(i)) && !s2_pd(i).isRVC && s2_doubleline && s2_exception(0).isNone, | ||||
|       s2_exception(1), | ||||
|       ExceptionType.none | ||||
|       ExceptionType.None | ||||
|     ) | ||||
|   }) | ||||
|   XSPerfAccumulate("fetch_bubble_icache_not_resp", s2_valid && !icacheRespAllValid) | ||||
|  | @ -563,7 +561,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
| 
 | ||||
|   /* *** mmio *** */ | ||||
|   private def nMmioFsmState = 11 | ||||
|   private object MmioFsmState extends NamedUInt(log2Up(nMmioFsmState)) { | ||||
|   private object MmioFsmState extends EnumUInt(nMmioFsmState) { | ||||
|     def Idle:           UInt = 0.U(width.W) | ||||
|     def WaitLastCommit: UInt = 1.U(width.W) | ||||
|     def SendReq:        UInt = 2.U(width.W) | ||||
|  | @ -580,7 +578,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|   private val mmioState = RegInit(MmioFsmState.Idle) | ||||
| 
 | ||||
|   private val mmioData       = RegInit(VecInit(Seq.fill(2)(0.U(16.W)))) | ||||
|   private val mmioException  = RegInit(0.U(ExceptionType.width.W)) | ||||
|   private val mmioException  = RegInit(ExceptionType.None) | ||||
|   private val mmioIsRvc      = RegInit(false.B) | ||||
|   private val mmioHasResend  = RegInit(false.B) | ||||
|   private val mmioResendAddr = RegInit(PrunedAddrInit(0.U(PAddrBits.W))) | ||||
|  | @ -591,7 +589,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|   private def mmioReset(): Unit = { | ||||
|     mmioState := MmioFsmState.Idle | ||||
|     mmioData.foreach(_ := 0.U) | ||||
|     mmioException               := ExceptionType.none | ||||
|     mmioException               := ExceptionType.None | ||||
|     mmioIsRvc                   := false.B | ||||
|     mmioHasResend               := false.B | ||||
|     mmioResendAddr              := PrunedAddrInit(0.U(PAddrBits.W)) | ||||
|  | @ -607,7 +605,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
| 
 | ||||
|   // do mmio fetch only when pmp/pbmt shows it is a un-cacheable address and no exception occurs | ||||
|   private val s3_reqIsMmio = | ||||
|     s3_valid && (s3_pmpMmio || Pbmt.isUncache(s3_itlbPbmt)) && !ExceptionType.hasException(s3_exception) | ||||
|     s3_valid && (s3_pmpMmio || Pbmt.isUncache(s3_itlbPbmt)) && s3_exception.map(_.isNone).reduce(_ && _) | ||||
|   private val mmioCommit = VecInit(io.robCommits.map { commit => | ||||
|     commit.valid && commit.bits.ftqIdx === s3_ftqReq.ftqIdx && commit.bits.ftqOffset === 0.U | ||||
|   }).asUInt.orR | ||||
|  | @ -682,9 +680,9 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|     is(MmioFsmState.WaitResp) { | ||||
|       when(fromUncache.fire) { | ||||
|         val respIsRVC = isRVC(fromUncache.bits.data(1, 0)) | ||||
|         val exception = ExceptionType.fromTilelink(fromUncache.bits.corrupt) | ||||
|         val exception = ExceptionType(hasAf = fromUncache.bits.corrupt) | ||||
|         // when response is not RVC, and lower bits of pAddr is 6 => request crosses 8B boundary, need resend | ||||
|         val needResend = !respIsRVC && s3_pAddr(0)(2, 1) === 3.U && !ExceptionType.hasException(exception) | ||||
|         val needResend = !respIsRVC && s3_pAddr(0)(2, 1) === 3.U && exception.isNone | ||||
|         mmioState     := Mux(needResend, MmioFsmState.SendTlb, MmioFsmState.WaitCommit) | ||||
|         mmioException := exception | ||||
|         mmioIsRvc     := respIsRVC | ||||
|  | @ -702,16 +700,13 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|       when(io.itlb.resp.fire) { | ||||
|         // we are using a blocked tlb, so resp.fire must have !resp.bits.miss | ||||
|         assert(!io.itlb.resp.bits.miss, "blocked mode iTLB miss when resp.fire") | ||||
|         val tlbException = ExceptionType.fromTlbResp(io.itlb.resp.bits) | ||||
|         val itlbException = ExceptionType.fromTlbResp(io.itlb.resp.bits) | ||||
|         // if itlb re-check respond pbmt mismatch with previous check, must be access fault | ||||
|         val pbmtMismatchException = Mux( | ||||
|           io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt, | ||||
|           ExceptionType.af, | ||||
|           ExceptionType.none | ||||
|         ) | ||||
|         val exception = ExceptionType.merge(tlbException, pbmtMismatchException) | ||||
|         val pbmtMismatchException = ExceptionType(hasAf = io.itlb.resp.bits.pbmt(0) =/= s3_itlbPbmt) | ||||
|         // merge, itlbException has higher priority | ||||
|         val exception = itlbException || pbmtMismatchException | ||||
|         // if tlb has exception, abort checking pmp, just send instr & exception to iBuffer and wait for commit | ||||
|         mmioState := Mux(ExceptionType.hasException(exception), MmioFsmState.WaitCommit, MmioFsmState.SendPmp) | ||||
|         mmioState := Mux(exception.hasException, MmioFsmState.WaitCommit, MmioFsmState.SendPmp) | ||||
|         // also save itlb response | ||||
|         mmioException               := exception | ||||
|         mmioResendAddr              := io.itlb.resp.bits.paddr(0) | ||||
|  | @ -721,16 +716,13 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|     } | ||||
| 
 | ||||
|     is(MmioFsmState.SendPmp) { | ||||
|       val pmpException = ExceptionType.fromPMPResp(io.pmp.resp) | ||||
|       val pmpException = ExceptionType.fromPmpResp(io.pmp.resp) | ||||
|       // if pmp re-check respond mismatch with previous check, must be access fault | ||||
|       val mmioMismatchException = Mux( | ||||
|         io.pmp.resp.mmio =/= s3_pmpMmio, | ||||
|         ExceptionType.af, | ||||
|         ExceptionType.none | ||||
|       ) | ||||
|       val exception = ExceptionType.merge(pmpException, mmioMismatchException) | ||||
|       val mmioMismatchException = ExceptionType(hasAf = io.pmp.resp.mmio =/= s3_pmpMmio) | ||||
|       // merge, pmpException has higher priority | ||||
|       val exception = pmpException || mmioMismatchException | ||||
|       // if pmp has exception, abort sending request, just send instr & exception to iBuffer and wait for commit | ||||
|       mmioState := Mux(ExceptionType.hasException(exception), MmioFsmState.WaitCommit, MmioFsmState.ResendReq) | ||||
|       mmioState := Mux(exception.hasException, MmioFsmState.WaitCommit, MmioFsmState.ResendReq) | ||||
|       // also save pmp response | ||||
|       mmioException := exception | ||||
|     } | ||||
|  | @ -742,7 +734,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|     is(MmioFsmState.WaitResendResp) { | ||||
|       when(fromUncache.fire) { | ||||
|         mmioState     := MmioFsmState.WaitCommit | ||||
|         mmioException := ExceptionType.fromTilelink(fromUncache.bits.corrupt) | ||||
|         mmioException := ExceptionType(hasAf = fromUncache.bits.corrupt) | ||||
|         mmioData(1)   := fromUncache.bits.data(15, 0) | ||||
|       } | ||||
|     } | ||||
|  | @ -860,8 +852,10 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|     a.bits  := i.U | ||||
|     a.valid := checkerOutStage1.fixedTaken(i) && !s3_reqIsMmio | ||||
|   } | ||||
|   io.toIBuffer.bits.foldpc        := s3_foldPc | ||||
|   io.toIBuffer.bits.exceptionType := ExceptionType.merge(s3_exceptionVec, s3_crossPageExceptionVec) | ||||
|   io.toIBuffer.bits.foldpc := s3_foldPc | ||||
|   io.toIBuffer.bits.exceptionType := VecInit((s3_exceptionVec zip s3_crossPageExceptionVec).map { case (e, ce) => | ||||
|     e || ce // merge, cross page fix has lower priority | ||||
|   }) | ||||
|   // backendException only needs to be set for the first instruction. | ||||
|   // Other instructions in the same block may have pf or af set, | ||||
|   // which is a side effect of the first instruction and actually not necessary. | ||||
|  | @ -869,7 +863,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|     case 0 => s3_isBackendException | ||||
|     case _ => false.B | ||||
|   } | ||||
|   io.toIBuffer.bits.crossPageIPFFix := s3_crossPageExceptionVec.map(ExceptionType.hasException) | ||||
|   io.toIBuffer.bits.crossPageIPFFix := s3_crossPageExceptionVec.map(_.hasException) | ||||
|   io.toIBuffer.bits.illegalInstr    := s3_ill | ||||
|   io.toIBuffer.bits.triggered       := s3_triggered | ||||
| 
 | ||||
|  | @ -899,8 +893,8 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
|   // s3_gpAddr is valid iff gpf is detected | ||||
|   io.toBackend.gpaddrMem_wen := s3_toIBufferValid && Mux( | ||||
|     s3_reqIsMmio, | ||||
|     mmioException === ExceptionType.gpf, | ||||
|     s3_exception.map(_ === ExceptionType.gpf).reduce(_ || _) | ||||
|     mmioException.isGpf, | ||||
|     s3_exception.map(_.isGpf).reduce(_ || _) | ||||
|   ) | ||||
|   io.toBackend.gpaddrMem_waddr        := s3_ftqReq.ftqIdx.value | ||||
|   io.toBackend.gpaddrMem_wdata.gpaddr := Mux(s3_reqIsMmio, mmioResendGpAddr.toUInt, s3_gpAddr.toUInt) | ||||
|  | @ -951,7 +945,7 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
| 
 | ||||
|     io.toIBuffer.bits.exceptionType(0) := mmioException | ||||
|     // exception can happen in next page only when resend | ||||
|     io.toIBuffer.bits.crossPageIPFFix(0) := mmioHasResend && ExceptionType.hasException(mmioException) | ||||
|     io.toIBuffer.bits.crossPageIPFFix(0) := mmioHasResend && mmioException.hasException | ||||
|     io.toIBuffer.bits.illegalInstr(0)    := mmioRvcExpander.io.ill | ||||
| 
 | ||||
|     io.toIBuffer.bits.enqEnable := s3_mmioRange.asUInt | ||||
|  | @ -1053,12 +1047,12 @@ class Ifu(implicit p: Parameters) extends IfuModule | |||
| 
 | ||||
|   /* write back flush type */ | ||||
|   private val checkFaultType    = wbCheckResultStage2.faultType | ||||
|   private val checkJalFault     = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalFault).reduce(_ || _) | ||||
|   private val checkJalrFault    = wbValid && checkFaultType.map(_ === PreDecodeFaultType.jalrFault).reduce(_ || _) | ||||
|   private val checkRetFault     = wbValid && checkFaultType.map(_ === PreDecodeFaultType.retFault).reduce(_ || _) | ||||
|   private val checkTargetFault  = wbValid && checkFaultType.map(_ === PreDecodeFaultType.targetFault).reduce(_ || _) | ||||
|   private val checkNotCFIFault  = wbValid && checkFaultType.map(_ === PreDecodeFaultType.notCfiFault).reduce(_ || _) | ||||
|   private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.invalidTaken).reduce(_ || _) | ||||
|   private val checkJalFault     = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalFault).reduce(_ || _) | ||||
|   private val checkJalrFault    = wbValid && checkFaultType.map(_ === PreDecodeFaultType.JalrFault).reduce(_ || _) | ||||
|   private val checkRetFault     = wbValid && checkFaultType.map(_ === PreDecodeFaultType.RetFault).reduce(_ || _) | ||||
|   private val checkTargetFault  = wbValid && checkFaultType.map(_ === PreDecodeFaultType.TargetFault).reduce(_ || _) | ||||
|   private val checkNotCFIFault  = wbValid && checkFaultType.map(_ === PreDecodeFaultType.NotCfiFault).reduce(_ || _) | ||||
|   private val checkInvalidTaken = wbValid && checkFaultType.map(_ === PreDecodeFaultType.InvalidTaken).reduce(_ || _) | ||||
| 
 | ||||
|   XSPerfAccumulate("predecode_flush_jalFault", checkJalFault) | ||||
|   XSPerfAccumulate("predecode_flush_jalrFault", checkJalrFault) | ||||
|  |  | |||
|  | @ -139,14 +139,14 @@ class PredChecker(implicit p: Parameters) extends IfuModule { | |||
| 
 | ||||
|   io.resp.stage2Out.faultType.zipWithIndex.foreach { case (faultType, i) => | ||||
|     faultType := MuxCase( | ||||
|       PreDecodeFaultType.noFault, | ||||
|       PreDecodeFaultType.NoFault, | ||||
|       Seq( | ||||
|         jalFaultVecNext(i)  -> PreDecodeFaultType.jalFault, | ||||
|         jalrFaultVecNext(i) -> PreDecodeFaultType.jalrFault, | ||||
|         retFaultVecNext(i)  -> PreDecodeFaultType.retFault, | ||||
|         targetFault(i)      -> PreDecodeFaultType.targetFault, | ||||
|         notCFITakenNext(i)  -> PreDecodeFaultType.notCfiFault, | ||||
|         invalidTakenNext(i) -> PreDecodeFaultType.invalidTaken | ||||
|         jalFaultVecNext(i)  -> PreDecodeFaultType.JalFault, | ||||
|         jalrFaultVecNext(i) -> PreDecodeFaultType.JalrFault, | ||||
|         retFaultVecNext(i)  -> PreDecodeFaultType.RetFault, | ||||
|         targetFault(i)      -> PreDecodeFaultType.TargetFault, | ||||
|         notCFITakenNext(i)  -> PreDecodeFaultType.NotCfiFault, | ||||
|         invalidTakenNext(i) -> PreDecodeFaultType.InvalidTaken | ||||
|       ) | ||||
|     ) | ||||
|   } | ||||
|  |  | |||
|  | @ -21,7 +21,7 @@ import freechips.rocketchip.tilelink.TLBundleA | |||
| import freechips.rocketchip.tilelink.TLBundleD | ||||
| import freechips.rocketchip.tilelink.TLEdgeOut | ||||
| import org.chipsalliance.cde.config.Parameters | ||||
| import utils.NamedUInt | ||||
| import utils.EnumUInt | ||||
| 
 | ||||
| // One miss entry deals with one mmio request | ||||
| class InstrUncacheEntry(edge: TLEdgeOut)(implicit p: Parameters) extends InstrUncacheModule { | ||||
|  | @ -40,7 +40,7 @@ class InstrUncacheEntry(edge: TLEdgeOut)(implicit p: Parameters) extends InstrUn | |||
|   val io: InstrUncacheEntryIO = IO(new InstrUncacheEntryIO(edge)) | ||||
| 
 | ||||
|   private def nState: Int = 4 | ||||
|   private object State extends NamedUInt(log2Up(nState)) { | ||||
|   private object State extends EnumUInt(nState) { | ||||
|     def Invalid:    UInt = 0.U(width.W) | ||||
|     def RefillReq:  UInt = 1.U(width.W) | ||||
|     def RefillResp: UInt = 2.U(width.W) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue