class PcManagerSimple(resetVector : BigInt,pcWidth : Int,fastFetchCmdPcCalculation : Boolean) extends Plugin[SpinalRiscv] with PcManagerService{
  import StandardStageables._

  //FetchService interface
  case class JumpInfo(pc: UInt, cond: Bool, stage: Stage)
  val jumpInfos = ArrayBuffer[JumpInfo]()
  override def jumpTo(pc: UInt, cond: Bool, stage: Stage): Unit = jumpInfos += JumpInfo(pc,cond,stage)

  override def build(pipeline: SpinalRiscv): Unit = {
    import pipeline.prefetch

    prefetch.plug(new Area {
      import prefetch._

      //PC calculation without Jump
      val pcReg = Reg(UInt(pcWidth bit)) init(resetVector)
      val inc = RegInit(False)
      val pc = if(fastFetchCmdPcCalculation){
        val pcPlus4 = pcReg + 4
        pcPlus4.addAttribute("keep")
        Mux(inc,pcPlus4,pcReg)
      }else{
        pcReg + (inc ? U(4) | U(0))
      }

      //Stage always valid
      arbitration.isValid := True

      //FetchService hardware implementation
      val jumpInfoSorted = jumpInfos.sortWith((a,b) => pipeline.indexOf(a.stage) > pipeline.indexOf(b.stage))
      val jumpRequestValids = jumpInfoSorted.map(_.cond)
      val jumpRequestPcs = jumpInfoSorted.map(_.pc)

      val pcLoad = Flow(pcReg)
      pcLoad.valid := jumpInfos.foldLeft(False)(_ || _.cond)
      pcLoad.payload := MuxOH(jumpRequestValids,jumpRequestPcs)

      //Register managments
      when(pcLoad.valid){
        pc := pcLoad.payload
        inc := False
        pcReg := pc
      }

      when(arbitration.isFiring){
        inc := True
        pcReg := pc
      }

      //Pipeline insertions
      insert(PC) := pc
    })
  }
}