SpinalHDL / NaxRiscv

MIT License
269 stars 40 forks source link

Problems about debug and Halt the Nax #98

Closed xie-1399 closed 6 months ago

xie-1399 commented 6 months ago

Hi! When I using the naxriscv to build my soc, I meet a problem about the openocd

Here is my Soc:

object SOCConfig{
  //set default soc config
  val init = UartCtrlInitConfig(
    baudrate = 921600,
    dataLength = 7, // 8 bits
    parity = UartParityType.NONE,
    stop = UartStopType.ONE
  )
  val socParameter= SOCConfig(
    CoreFrequency = 12 MHz,
    onChipRamSize = 8 KiB,
    onChipRamHexFile = null,
    uartCtrlConfig = UartCtrlMemoryMappedConfig(
      uartCtrlConfig = UartCtrlGenerics(
        dataWidthMax = 8,
        clockDividerWidth = 20,
        preSamplingSize = 1,
        samplingSize = 5,
        postSamplingSize = 2
      ),
      initConfig = init,
      busCanWriteClockDividerConfig = false,
      busCanWriteFrameConfig = false,
      txFifoDepth = 16,
      rxFifoDepth = 16
    ),
    spiMasterCtrlConfig = SpiMasterCtrlMemoryMappedConfig(
      ctrlGenerics = SpiMasterCtrlGenerics(
        ssWidth = 4,
        timerWidth = 12,
        dataWidth = 8
      ),
      cmdFifoDepth = 32,
      rspFifoDepth = 32
    )
  )
}

class SOC(val socParameter:SOCConfig) extends Component {

  noIoPrefix()
  val io = new Bundle {
    //clock and reset
    val asyncReset = in Bool()
    val clk = in Bool()
    val jtag = slave(Jtag())
    val bus = master(Axi4(axiConfig))
    val uart = master(Uart())
    val spi = master(SpiMaster(ssWidth = 4))
  }

  val resetCtrlClockDomain = ClockDomain(
    clock = io.clk,
    config = ClockDomainConfig(
      resetKind = BOOT
    )
  )

  val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
    val systemReset = RegNext(io.asyncReset) simPublic()
    val debugReset = RegNext(io.asyncReset)
  }

  val systemClockDomain = ClockDomain(
    clock = io.clk,
    reset = resetCtrl.systemReset,
    frequency = FixedFrequency(socParameter.CoreFrequency)
  )

  val debugClockDomain = ClockDomain(
    clock = io.clk,
    reset = resetCtrl.debugReset,
    frequency = FixedFrequency(socParameter.CoreFrequency)
  )

  def plugins = {
    val l = Config.plugins(
      sideChannels = false,
      xlen = 64,
      withRdTime = false,
      aluCount = 2,
      decodeCount = 2,
      withRvc = true,
      withDebug = true,
      withEmbeddedJtagTap = true,
      withEmbeddedJtagInstruction = false,
      jtagTunneled = false,
      debugTriggers = 4,
      withFloat = true,
      withDouble = true,
      lqSize = 16,
      sqSize = 16,
      resetVector = 0x80000000l
    )
    l.foreach {
      case p: EmbeddedJtagPlugin => p.debugCd.load(debugClockDomain)
      case _ =>
    }
    l
  }

  val soc = new ClockingArea(systemClockDomain) {
    val MachineexternalInterrupt = False
    val SupervisorexternalInterrupt = False
    val timerInterrupt = False
    val softWareInterrupt = False

    val cpu: NaxRiscv = new NaxRiscv(plugins = plugins)
    var iBus: Axi4ReadOnly = null
    var dBus: Axi4 = null
    var pBus: Axi4Shared = null

    for (plugin <- cpu.plugins) plugin match {
      case plugin: FetchCachePlugin => {
        iBus = plugin.mem.resizer(256).toAxi4()
      }
      case plugin: DataCachePlugin => {
        dBus = plugin.mem.resizer(256).toAxi4()
      }
      case plugin: PrivilegedPlugin => {
        plugin.io.int.machine.external := MachineexternalInterrupt
        plugin.io.int.machine.software := softWareInterrupt
        plugin.io.int.machine.timer := timerInterrupt
        plugin.io.int.supervisor.external := SupervisorexternalInterrupt
      }
      case plugin: Lsu2Plugin => {
        pBus = plugin.peripheralBus.resize(32).toAxiLite4().toAxi().toShared()
      }
      case plugin: EmbeddedJtagPlugin => {
        plugin.logic.jtag <> io.jtag
      }
      case _ =>
    }

    val axi4Crossbar = Axi4CrossbarFactory()
    val ram = Axi4SharedOnChipRam(
      dataWidth = 256,
      byteCount = socParameter.onChipRamSize,
      idWidth = 5
    )

    axi4Crossbar.addSlaves(
      io.bus -> (0x80000000L, 2 GiB),
      ram.io.axi ->(0x20000000L, socParameter.onChipRamSize)  /* just for the debug purpose */
    )

    axi4Crossbar.addConnections(
      iBus -> List(io.bus,ram.io.axi),
      dBus -> List(io.bus,ram.io.axi)
    )

    // crossbar <-> highspeedBus
    axi4Crossbar.addPipelining(io.bus)((readCrossbar, Bus) => {
      readCrossbar.readCmd >> Bus.readCmd
      readCrossbar.readRsp << Bus.readRsp
    })((writeCrossbar, Bus) => {
      writeCrossbar.writeData >> Bus.writeData
      writeCrossbar.writeCmd >> Bus.writeCmd
      writeCrossbar.writeRsp << Bus.writeRsp
    })
    axi4Crossbar.addPipelining(ram.io.axi)((crossbar, ctrl) => {
      crossbar.sharedCmd.halfPipe() >> ctrl.sharedCmd
      crossbar.writeData >/-> ctrl.writeData
      crossbar.writeRsp << ctrl.writeRsp
      crossbar.readRsp << ctrl.readRsp
    })

    axi4Crossbar.build()

    val apbclint = Apb3Clint(hartCount = 1)
    /* add the plic to control the external interrupt */

    //IO bus
    val uartCtrl = Apb3UartCtrl(socParameter.uartCtrlConfig)
    uartCtrl.io.apb.simPublic()
    val spiCtrl = Apb3SpiMasterCtrl(socParameter.spiMasterCtrlConfig)
    spiCtrl.addAttribute(Verilator.public)
    io.uart <> uartCtrl.io.uart
    io.spi <> spiCtrl.io.spi
    val plic = new Apb3Plic(2,1)
    plic.io.sources := (uartCtrl.io.interrupt.asBits ## spiCtrl.io.interrupt.asBits)

    val machineInterruptCtrl = new MachineInterruptCtrl(1)
    val supervisorInterruptCtrl = new SupervisorInterruptCtrl(1)
    machineInterruptCtrl.io.inputs := (uartCtrl.io.interrupt || spiCtrl.io.interrupt).asBits
    supervisorInterruptCtrl.io.inputs := (uartCtrl.io.interrupt || spiCtrl.io.interrupt).asBits

    /* the interrupt Node */
    timerInterrupt.setWhen(apbclint.io.timerInterrupt.asBool)
    softWareInterrupt.setWhen(apbclint.io.softwareInterrupt.asBool)
    MachineexternalInterrupt.setWhen(machineInterruptCtrl.io.pendings.asBool)
    SupervisorexternalInterrupt.setWhen(supervisorInterruptCtrl.io.pendings.asBool)

    val apbBridge = Axi4SharedToApb3Bridge(
      addressWidth = 34,
      dataWidth = 32,
      idWidth = 4
    )
    val apbDecoder = Apb3Decoder(
      master = apbBridge.io.apb,
      slaves = List(
        uartCtrl.io.apb -> (0x10000000, 1 Byte),
        machineInterruptCtrl.io.bus -> (0x10000010,1 Byte),
        supervisorInterruptCtrl.io.bus -> (0x10000018,1 Byte),
        apbclint.io.bus -> (0x10010000,64 KiB), /* 0x10000 - 0x20000*/
        spiCtrl.io.apb -> (0x10020000, 4 KiB),
        plic.io.bus -> (0x10C00000,64 KiB)
      )
    )
    pBus <> apbBridge.io.axi
  }
}

then I run the jtag simulation code like this:

class JtagSim extends AnyFunSuite {
  test("debug") {
    SIMCFG(debug = true, generateWave = false).compile { //use fst wave
      val dut = new SOC(SOCConfig.socParameter)
      dut
    }.doSimUntilVoid {
      dut =>
        val mainClkPeriod = (1e12 / dut.systemClockDomain.frequency.getValue.toDouble).toLong
        val jtagClkPeriod = 4 * mainClkPeriod
        val clockDomain = ClockDomain(dut.io.clk, dut.io.asyncReset)
        clockDomain.forkStimulus(mainClkPeriod)
        val tcpJtag = JtagTcp(
          jtag = dut.io.jtag,
          jtagClkPeriod = jtagClkPeriod
        )

    }
  }
}

I use the spinal openocd and build it , then I run the command src/openocd -f "/my_path/naxriscv_sim.cfg",the error happens:

716dc3021ff1821d27fdd633ce953b8 I try some methods like https://github.com/riscv-collab/riscv-openocd/issues/195 But it doesn't work well,can you help me? Thank You!

Dolu1990 commented 6 months ago

Hi,

Can you send the fst wave ?

One possibility, is that because the io.bus isn't handled in simulation, NaxRiscv is waiting on it indefinitly ?

xie-1399 commented 6 months ago

of course,here is my wave... Thank you very much wave.zip .

Dolu1990 commented 6 months ago

I can't open the fst file with gtkwave. Depending how you exited the simualtion, they may be a companion file ? with also the fst char in the name ?

xie-1399 commented 6 months ago

My fault,I ignore the hier file,here is new file: wave_new.zip

Dolu1990 commented 6 months ago

Looking at the toplevel io, i can see there is 2 clk and 2 reset, which is weird, probably the default clockdomain leaked in some ways.

Can you send your generated verilog ?

xie-1399 commented 6 months ago

This is generated verilog verilog.zip

Dolu1990 commented 6 months ago

The issue in the reset controller.

the CPU never get any reset.

xie-1399 commented 6 months ago

Ah!! you are right , and I solve my problem , Thank you :)