Skip to content

Assertion with configuration #473

@RossComputerGuy

Description

@RossComputerGuy
import scala.collection.mutable.ArrayBuffer

import spinal.core._
import spinal.core.sim._
import spinal.lib._
import spinal.lib.bus.amba3.apb._
import spinal.lib.bus.amba4.axi._
import spinal.lib.bus.amba4.axilite.AxiLite4SpecRenamer
import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl}
import spinal.lib.com.jtag.sim.JtagTcp
import spinal.lib.com.uart._
import spinal.lib.com.uart.sim.{UartDecoder, UartEncoder}
import spinal.lib.misc.AxiLite4Clint
import spinal.lib.misc.HexTools
import spinal.lib.misc.plic.AxiLite4Plic

import vexriscv.demo.MuraxApb3Timer
import vexriscv.ip._
import vexriscv.ip.fpu.FpuParameter
import vexriscv.plugin._
import vexriscv.{Riscv, VexRiscv, VexRiscvConfig, plugin}

case class MeerkatSoCConfig(
  coreFrequency: HertzNumber,
  withNativeJtag: Boolean,
  hardwareBreakpointCount: Int,
  uartCtrlConfig: UartCtrlMemoryMappedConfig,
  onChipRamHexFile: String,
  onChipRamSize: BigInt,
  cpuPlugins: ArrayBuffer[Plugin[VexRiscv]]
)

object MeerkatSoCConfig {
  def default: MeerkatSoCConfig = MeerkatSoCConfig(
    coreFrequency = 12 MHz,
    withNativeJtag = false,
    hardwareBreakpointCount = 0,
    onChipRamHexFile = null,
    onChipRamSize = 8000 kB,
    uartCtrlConfig = UartCtrlMemoryMappedConfig(
      uartCtrlConfig = UartCtrlGenerics(
        dataWidthMax = 8,
        clockDividerWidth = 20,
        preSamplingSize = 1,
        samplingSize = 3,
        postSamplingSize = 1
      ),
      initConfig = UartCtrlInitConfig(
        baudrate = 115200,
        dataLength = 7,
        parity = UartParityType.NONE,
        stop = UartStopType.ONE
      ),
      busCanWriteClockDividerConfig = false,
      busCanWriteFrameConfig = false,
      txFifoDepth = 16,
      rxFifoDepth = 16
    ),
    cpuPlugins = ArrayBuffer(

  new MmuPlugin(
    ioRange = _(31 downto 28) === 0xF
  ),

  new IBusCachedPlugin(
    resetVector = 0x80000000L,
    compressedGen = true,
    prediction = DYNAMIC,
    config = InstructionCacheConfig(
      cacheSize = 4096,
      bytePerLine = 32,
      wayCount = 1,
      addressWidth = 32,
      cpuDataWidth = 32,
      memDataWidth = 32,
      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,
      bytePerLine = 32,
      wayCount = 1,
      addressWidth = 32,
      cpuDataWidth = 32,
      memDataWidth = 32,
      catchAccessError = true,
      catchIllegal = true,
      catchUnaligned = true,
      withExclusive = false,
      withInvalidate = false,
      withLrSc = true,
      withAmo = true
    ),
    memoryTranslatorPortConfig = MmuPortConfig(
      portTlbSize = 4
    )
  ),

  new DecoderSimplePlugin(
    catchIllegalInstruction = true
  ),

  new RegFilePlugin(
    regFileReadyKind = plugin.SYNC,
    zeroBoot = false
  ),

  new IntAluPlugin,

  new SrcPlugin(
    separatedAddSub = false
  ),

  new FullBarrelShifterPlugin,

  new HazardSimplePlugin(
    bypassExecute = true,
    bypassMemory = true,
    bypassWriteBack = true,
    bypassWriteBackBuffer = true,
    pessimisticUseSrc = false,
    pessimisticWriteRegFile = false,
    pessimisticAddressMatch = false
  ),

  new MulPlugin,

  new MulDivIterativePlugin(
    genMul = false,
    genDiv = true,
    mulUnrollFactor = 32,
    divUnrollFactor = 1
  ),

  new CsrPlugin(
    CsrPluginConfig.openSbi(mhartid = 0, misa = Riscv.misaToInt("imac")).copy(
      mtvecInit = 0x80000000L,
      ebreakGen = true,
      marchid = 33,
      utimeAccess = CsrAccess.READ_ONLY
    )
  ),

  new BranchPlugin(
    earlyBranch = false
  )
),
  )
}

case class MeerkatSoC(config: MeerkatSoCConfig) extends Component {
  import config._

  val io = new Bundle {
    val asyncReset = in Bool()
    val mainClk = in Bool()
    val jtag = ifGen(!withNativeJtag)(slave(Jtag()))
    val uart = master(Uart())
  }

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

  val resetCtrl = new ClockingArea(resetCtrlClockDomain) {
    val mainClkResetUnbuffered = False

    val systemClkResetCounter = Reg(UInt(6 bits)) init (0)
    when(systemClkResetCounter =/= U(systemClkResetCounter.range -> true)) {
      systemClkResetCounter := systemClkResetCounter + 1
      mainClkResetUnbuffered := True
    }
    when(BufferCC(io.asyncReset)) {
      systemClkResetCounter := 0
    }

    val mainClkReset = RegNext(mainClkResetUnbuffered)
    val systemReset = RegNext(mainClkResetUnbuffered)
  }

  val systemClockDomain = ClockDomain(
    clock = io.mainClk,
    reset = resetCtrl.systemReset,
    frequency = FixedFrequency(coreFrequency)
  )

  val debugClockDomain = ClockDomain(
    clock = io.mainClk,
    reset = resetCtrl.mainClkReset,
    frequency = FixedFrequency(coreFrequency)
  )

  val jtagNative = withNativeJtag generate new ClockingArea(debugClockDomain) {
    val jtagCtrl = JtagTapInstructionCtrl()
    val tap = jtagCtrl.fromXilinxBscane2(userId = 2)
  }

  val system = new ClockingArea(systemClockDomain) {
    val cpu = new VexRiscv(
      VexRiscvConfig(
        plugins = cpuPlugins += new DebugPlugin(debugClockDomain, hardwareBreakpointCount)
      )
    ){
      val clintCtrl = new AxiLite4Clint(1, bufferTime = false)
      val plicCtrl = new AxiLite4Plic(
        sourceCount = 31,
        targetCount = 2
      )

      val clint = clintCtrl.io.bus.toIo()
      val plic = plicCtrl.io.bus.toIo()
      val plicInterrupts = in Bits(32 bits)
      plicCtrl.io.sources := plicInterrupts >> 1

      AxiLite4SpecRenamer(clint)
      AxiLite4SpecRenamer(plic)
    }

    var iBus: Axi4ReadOnly = null
    var dBus: Axi4Shared = null

    for (plugin <- cpu.plugins) plugin match {
      case p: IBusCachedPlugin =>
        iBus = p.iBus.toAxi4ReadOnly()

      case p: DBusCachedPlugin =>
        dBus = p.dBus.toAxi4Shared(true)

      case p: CsrPlugin =>
        p.timerInterrupt.setAsDirectionLess() := cpu.clintCtrl.io.timerInterrupt(0)
        p.softwareInterrupt.setAsDirectionLess() := cpu.clintCtrl.io.softwareInterrupt(0)
        p.externalInterrupt.setAsDirectionLess() := cpu.plicCtrl.io.targets(0)
        //p.externalInterruptS.setAsDirectionLess() := cpu.plicCtrl.io.targets(1)
        p.utime.setAsDirectionLess() := cpu.clintCtrl.io.time

      case p: DebugPlugin =>
        p.debugClockDomain {
          resetCtrl.systemReset setWhen RegNext(p.io.resetOut)
          if (withNativeJtag) {
            jtagNative.jtagCtrl <> p.io.bus.fromJtagInstructionCtrl(
              ClockDomain(jtagNative.tap.TCK),
              0
            )
          } else {
            io.jtag <> p.io.bus.fromJtag()
          }
        }

      case _ =>
    }

    assert(iBus != null, "IBusCachedPlugin missing from cpuPlugins")
    assert(dBus != null, "DBusCachedPlugin missing from cpuPlugins")

    val ram = Axi4SharedOnChipRam(
      dataWidth = 32,
      byteCount = onChipRamSize,
      idWidth = 4,
    )

    if (onChipRamHexFile != null) {
      val resetVector = cpu.plugins.collectFirst {
        case p: IBusCachedPlugin => p.resetVector
      }.getOrElse {
        BigInt(0)
      };
      HexTools.initRam(ram.ram, onChipRamHexFile, resetVector)
    }

    val apbBridge = Axi4SharedToApb3Bridge(
      addressWidth = 20,
      dataWidth = 32,
      idWidth = 4
    )

    val uartCtrl = Apb3UartCtrl(uartCtrlConfig)
    uartCtrl.io.uart <> io.uart

    val axiCrossbar = Axi4CrossbarFactory()

    axiCrossbar.addSlaves(
      ram.io.axi -> (0x80000000L, onChipRamSize),
      apbBridge.io.axi -> (0xF0000000L, 1 MB)
    )

    axiCrossbar.addConnections(
      iBus -> List(ram.io.axi),
      dBus -> List(ram.io.axi, apbBridge.io.axi)
    )

    axiCrossbar.addPipelining(ram.io.axi) { (crossbar, ctrl) =>
      crossbar.sharedCmd.halfPipe() >> ctrl.sharedCmd
      crossbar.writeData >/-> ctrl.writeData
      crossbar.writeRsp << ctrl.writeRsp
      crossbar.readRsp << ctrl.readRsp
    }

    axiCrossbar.addPipelining(apbBridge.io.axi) { (crossbar, bridge) =>
      crossbar.sharedCmd.halfPipe() >> bridge.sharedCmd
      crossbar.writeData.halfPipe() >> bridge.writeData
      crossbar.writeRsp << bridge.writeRsp
      crossbar.readRsp << bridge.readRsp
    }

    axiCrossbar.addPipelining(dBus) { (cpuBus, crossbar) =>
      cpuBus.sharedCmd >> crossbar.sharedCmd
      cpuBus.writeData >> crossbar.writeData
      cpuBus.writeRsp << crossbar.writeRsp
      cpuBus.readRsp <-< crossbar.readRsp
    }

    axiCrossbar.build()

    val apbDecoder = Apb3Decoder(
      master = apbBridge.io.apb,
      slaves = List(
        uartCtrl.io.apb -> (0x10000, 4 kB),
      )
    )
  }
}

object MeerkatSoC {
  case class Args(
    firmware: Option[String] = None,
    yaml_out: Option[String] = None,
  )

  def parseArgs(args: Array[String]): Args = {
    var firmware: Option[String] = None
    var yaml_out: Option[String] = None

    val it = args.iterator
    while (it.hasNext) {
      it.next() match {
        case "--firmware" =>
          if (!it.hasNext) {
            sys.error("--firmware requires a path")
          }
          firmware = Some(it.next())

        case "--yaml-out" =>
          if (!it.hasNext) {
            sys.error("--yaml-out requires a path")
          }
          yaml_out = Some(it.next())

        case unknown =>
          sys.error(s"Unknown argument: $unknown")
      }
    }

    Args(firmware, yaml_out)
  }

  def main(args: Array[String]): Unit = {
    val parsed = parseArgs(args)

    val config = MeerkatSoCConfig.default.copy(
      onChipRamHexFile = parsed.firmware.orNull
    )

    parsed.yaml_out.foreach { path =>
      config.cpuPlugins += new YamlPlugin(path)
    }

    SpinalVerilog(MeerkatSoC(config))
  }
}

object MeerkatSoCSim {
  def main(args: Array[String]): Unit = {
    val parsed = MeerkatSoC.parseArgs(args)

    val config = MeerkatSoCConfig.default.copy(
      onChipRamHexFile = parsed.firmware.orNull
    )

    parsed.yaml_out.foreach { path =>
      config.cpuPlugins += new YamlPlugin(path)
    }

    SimConfig.allOptimisation.compile(MeerkatSoC(config)).doSimUntilVoid{dut =>
      val mainClkPeriod = (1e12/dut.config.coreFrequency.toDouble).toLong
      val jtagClkPeriod = mainClkPeriod*4
      val uartBaudRate = 115200
      val uartBaudPeriod = (1e12/uartBaudRate).toLong

      val clockDomain = ClockDomain(dut.io.mainClk, dut.io.asyncReset)
      clockDomain.forkStimulus(mainClkPeriod)

      val tcpJtag = JtagTcp(
        jtag = dut.io.jtag,
        jtagClkPeriod = jtagClkPeriod
      )

      val uartTx = UartDecoder(
        uartPin = dut.io.uart.txd,
        baudPeriod = uartBaudPeriod
      )

      val uartRx = UartEncoder(
        uartPin = dut.io.uart.rxd,
        baudPeriod = uartBaudPeriod
      )
    }
  }
}
[error] Exception in thread "main" java.lang.AssertionError: assertion failed
[error]         at scala.Predef$.assert(Predef.scala:208)
[error]         at spinal.core.package$.assert(core.scala:545)
[error]         at vexriscv.plugin.DecoderSimplePlugin.addDefault(DecoderSimplePlugin.scala:67)
[error]         at vexriscv.plugin.IBusCachedPlugin.setup(IBusCachedPlugin.scala:103)
[error]         at vexriscv.plugin.IBusCachedPlugin.setup(IBusCachedPlugin.scala:28)
[error]         at vexriscv.Pipeline.$anonfun$build$2(Pipeline.scala:47)
[error]         at vexriscv.Pipeline.$anonfun$build$2$adapted(Pipeline.scala:47)
[error]         at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62)
[error]         at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55)
[error]         at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49)
[error]         at vexriscv.Pipeline.build(Pipeline.scala:47)
[error]         at vexriscv.Pipeline.build$(Pipeline.scala:45)
[error]         at vexriscv.VexRiscv.build(VexRiscv.scala:131)
[error]         at vexriscv.Pipeline.$anonfun$$init$$1(Pipeline.scala:161)
[error]         at spinal.core.Component.$anonfun$prePop$1(Component.scala:194)
[error]         at spinal.core.Component.$anonfun$prePop$1$adapted(Component.scala:192)
[error]         at scala.collection.mutable.ResizableArray.foreach(ResizableArray.scala:62)
[error]         at scala.collection.mutable.ResizableArray.foreach$(ResizableArray.scala:55)
[error]         at scala.collection.mutable.ArrayBuffer.foreach(ArrayBuffer.scala:49)
[error]         at spinal.core.Component.prePop(Component.scala:192)
[error]         at spinal.core.Component.postInitCallback(Component.scala:201)
[error]         at MeerkatSoC$$anon$4.<init>(MeerkatSoC.scala:214)
[error]         at MeerkatSoC.<init>(MeerkatSoC.scala:213)
[error]         at MeerkatSoCSim$.$anonfun$main$4(MeerkatSoC.scala:398)
[error]         at spinal.core.internals.PhaseCreateComponent.$anonfun$impl$322(Phase.scala:3082)
[error]         at spinal.core.fiber.Engine$.$anonfun$create$1(AsyncCtrl.scala:174)
[error]         at spinal.core.fiber.AsyncThread.$anonfun$jvmThread$1(AsyncThread.scala:60)
[error]         at spinal.core.fiber.EngineContext.$anonfun$newJvmThread$1(AsyncCtrl.scala:39)
[error]         at spinal.sim.JvmThread.run(SimManager.scala:51)
[error] nonzero exit code returned from runner: 1
[error] (Compile / runMain) nonzero exit code returned from runner: 1
[error] Total time: 10 s, completed 2026/03/07 23:16:20

Everything I change causes the assert, idk what I am doing wrong. I've been changing things for an hour to resolve the issue but it doesn't work

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions