SpinalHDL / VexRiscv

A FPGA friendly 32 bit RISC-V CPU implementation
MIT License
2.52k stars 420 forks source link

Cannot access medeleg and mideleg #337

Closed flaviens closed 1 year ago

flaviens commented 1 year ago

Hi!

I'm trying to access medeleg and mideleg but I get exceptions despite trying to authorize them in the configuration. Should I do anything else in the configuration?

Configuration

  def main(args: Array[String]) {
    val report = SpinalConfig(mode = if(args.contains("--vhdl")) VHDL else Verilog).generate{

      //CPU configuration
      val cpuConfig = VexRiscvConfig(
        plugins = List(
          // new IBusSimplePlugin(
          //   resetVector = 0x80000000l,
          //   cmdForkOnSecondStage = false,
          //   cmdForkPersistence = true,
          //   prediction = DYNAMIC_TARGET,
          //   catchAccessFault = true,
          //   compressedGen = true
          // ),
          // new DBusSimplePlugin(
          //   catchAddressMisaligned = true,
          //   catchAccessFault = true
          // ),
          new IBusCachedPlugin(
            resetVector = 0x80000000l,
            compressedGen = false, 
            prediction = STATIC,
            historyRamSizeLog2 = 4,
            injectorStage = false,
            config = InstructionCacheConfig(
              cacheSize = 4096*1,
              bytePerLine = 8,
              wayCount = 2,
              addressWidth = 32,
              cpuDataWidth = 32,
              memDataWidth = 64,
              catchIllegalAccess = true,
              catchAccessFault = true,
              asyncTagMemory = false,
              twoCycleRam = false,
              twoCycleCache = false
            ),
            memoryTranslatorPortConfig = MmuPortConfig(
              portTlbSize = 4
            )
          ),
          new DBusCachedPlugin(
            dBusCmdMasterPipe = true,
            dBusCmdSlavePipe = true,
            dBusRspSlavePipe = true,
            config = new DataCacheConfig(
              cacheSize         = 4096*1,
              bytePerLine       = 8,
              wayCount          = 2,
              addressWidth      = 32,
              cpuDataWidth      = 64,
              memDataWidth      = 64,
              catchAccessError  = true,
              catchIllegal      = true,
              catchUnaligned    = true,
              withExclusive = false, // = withsmp
              withInvalidate = false, // = withsmp
              withLrSc = false,
              withAmo = false,
              withWriteAggregation = false
            ),
            memoryTranslatorPortConfig = MmuPortConfig(
              portTlbSize = 4
            )
          ),
          new MmuPlugin(
            virtualRange = _(31 downto 28) === 0xC,
            ioRange      = _(31 downto 28) === 0xF
          ),
          new FpuPlugin(
            externalFpu = false,
            simHalt = false,
            p = FpuParameter(withDouble = true)
          ),
          new DecoderSimplePlugin(
            catchIllegalInstruction = true
          ),
          new RegFilePlugin(
            regFileReadyKind = plugin.SYNC,
            zeroBoot = false
          ),
          new IntAluPlugin,
          new SrcPlugin(
            separatedAddSub = false,
            executeInsertion = true
          ),
          new FullBarrelShifterPlugin,
          new MulPlugin,
          new DivPlugin,
          new HazardSimplePlugin(
            bypassExecute           = true,
            bypassMemory            = true,
            bypassWriteBack         = true,
            bypassWriteBackBuffer   = true,
            pessimisticUseSrc       = false,
            pessimisticWriteRegFile = false,
            pessimisticAddressMatch = false
          ),
          new BranchPlugin(
            earlyBranch = false,
            catchAddressMisaligned = true
          ),
          new CsrPlugin(
            config = CsrPluginConfig(
              catchIllegalAccess = true,
              mvendorid      = 0,
              marchid        = 0,
              mimpid         = 0,
              mhartid        = 0,
              misaExtensionsInit = 66,
              misaAccess     = CsrAccess.READ_ONLY,
              mtvecAccess    = CsrAccess.READ_WRITE,
              mtvecInit      = 0x00000020l,
              mepcAccess     = CsrAccess.READ_WRITE,
              mscratchGen    = false,
              mcauseAccess   = CsrAccess.READ_ONLY,
              mbadaddrAccess = CsrAccess.READ_ONLY,
              mcycleAccess   = CsrAccess.READ_ONLY,
              minstretAccess = CsrAccess.READ_ONLY,
              ecallGen       = true,
              ebreakGen      = true,
              wfiGenAsWait   = false,
              ucycleAccess   = CsrAccess.READ_ONLY,
              uinstretAccess = CsrAccess.READ_ONLY,
              medelegAccess  = CsrAccess.READ_WRITE,
              midelegAccess  = CsrAccess.READ_WRITE

            )
          ),
          new YamlPlugin("cpu0.yaml")
        )
      )

      val cpu = new VexRiscv(cpuConfig)
      cpu
    }
  }

Example snippet

This snippet behaves unexpectedly by throwing an exception when reading medeleg.

  .section ".text.init","ax",@progbits
  .globl _start
  .align 2
_start:

  li a0, 0x10

  la      ra, trap_handler
  csrrw zero,mtvec,ra

  csrr t0, medeleg

  li t0, 0

  sw t0, (a0)
  sw zero, (zero)

infinite_loop0:
  j infinite_loop0

.section ".trap_handler","ax",@progbits
trap_handler:

  li t0, 1

  sw t0, (a0)
  sw zero, (zero)

infinite_loop1:
  j infinite_loop1

Thanks!

Dolu1990 commented 1 year ago

Hi,

Yes, you will have to enable supervisor. Here is an instance of supervisor Csr config : https://github.com/SpinalHDL/VexRiscv/blob/master/src/main/scala/vexriscv/plugin/CsrPlugin.scala#L100

flaviens commented 1 year ago

Cool thanks! It worked! Another quick question: what is pipelineCsrRead intended to do? I see that it is false by default everywhere.

Dolu1990 commented 1 year ago

Cool ^^ I would say, pipelineCsrRead is deprecated. It was implementing CSRRW instruction in two cycles in order to get better timings.

flaviens commented 1 year ago

Thanks! Yet another question: I noticed that accesses to hpmcountern, mhpmcountern and mhpmeventn are triggering exceptions, but I cannot see where to change the config to get them. The rv priv spec 1.10 says:

All counters should be implemented, but a legal implementation is to hard-wire both the counter and its corresponding event selector to 0.

Is this another problem of my config?

Dolu1990 commented 1 year ago

About hpm, basicaly there were not implemented at all, until the recent commit : https://github.com/SpinalHDL/VexRiscv/commit/051080e060ecf3feb84adf46e7e3759c281ebb93

Did you had it in when you tested it ?

flaviens commented 1 year ago

Great! I'm testing on master. I cherry-picked the commit and I confirm that https://github.com/SpinalHDL/VexRiscv/commit/051080e060ecf3feb84adf46e7e3759c281ebb93 looks like it makes it compliant. Thanks!

Dolu1990 commented 1 year ago

Ahhh, master is quite a bit behind some recent fixes ^^ normaly, you can merge dev into master, it should be fine, you only need to preserve the build.sbt file, i think