SpinalHDL / VexiiRiscv

Like VexRiscv, but, Harder, Better, Faster, Stronger
MIT License
63 stars 7 forks source link

**Phenomenon** VexiiRiscv cannot be composed into new Module #5

Closed dreamflyings closed 5 months ago

dreamflyings commented 5 months ago

Hi~ I found that VexiiRiscv cannot be instantiated in new Module, Of course, it may also be that I am not familiar enough with the FiberPlugin framework. What I want to say is: if VexiiRiscv cannot be composed into new Module, This will limit the application of the FiberPlugin framework. In addition, because the FrameWork framework used in naxriscv can be composed, This causes some trouble for old users who want to upgrade the framework. What do you think of this phenomenon? The code is as follows:

object Miaouuuu9 extends App{
 // class VexiiRiscv extends Component{
 // val host = new PluginHost
 // }

 import spinal.core._
 import spinal.core.fiber.Retainer
 import spinal.lib.misc.plugin._
 import spinal.lib.CountOne
 import vexiiriscv._
 import scala.collection.mutable.ArrayBuffer

 class EventCounterPlugin extends FiberPlugin{
 val lock = Retainer() // Will allow other plugins to block the elaboration of "logic" thread
 val events = ArrayBuffer[Bool]() // Will allow other plugins to add event sources
 val logic = during build new Area{
 lock.await() // Active blocking
 val counter = Reg(UInt(32 bits)) init(0)
 counter := counter + CountOne(events)
counter.asOutput()
 }
 }

 //For the demo we want to be able to instanciate this plugin multiple times, so we add a prefix parameter
 class EventSourcePlugin(prefix : String) extends FiberPlugin{
 withPrefix(prefix)

 // Create a thread starting from the setup phase (this allow to run some code before the build phase, and so lock some other plugins retainers)
 val logic = during setup new Area{
 val ecp = host[EventCounterPlugin] // Search for the single instance of EventCounterPlugin in the plugin pool
 // Generate a lock to prevent the EventCounterPlugin elaboration until we release it.
 // this will allow us to add our localEvent to the ecp.events list
 val ecpLocker = ecp.lock()

 // Wait for the build phase before generating any hardware
 awaitBuild()

 // Here the local event is a input of the VexiiRiscv toplevel (just for the demo)
 val localEvent = in Bool()
 ecp.events += localEvent

 // As everything is done, we now allow the ecp to elaborate itself
 ecpLocker.release()
 }
 }

 SpinalVerilog{
 val plugins = ArrayBuffer[FiberPlugin]()
 plugins += new EventCounterPlugin()
 plugins += new EventSourcePlugin("lane0")
 plugins += new EventSourcePlugin("lane1")
 new Module{
 val mod = VexiiRiscv(plugins)
 val modCnt = mod.host[EventCounterPlugin].logic.get
 val cnt = modCnt.counter.resize(8).toIo()
 }.setName("TestComb")
 }
}
Dolu1990 commented 5 months ago

Here is the fix to the above example :

  SpinalVerilog{
    val plugins = ArrayBuffer[FiberPlugin]()
    plugins += new EventCounterPlugin()
    plugins += new EventSourcePlugin("lane0")
    plugins += new EventSourcePlugin("lane1")
    new Module{
      val mod = VexiiRiscv(plugins)

      val patch = Fiber build mod.rework(new Area {
        val modCnt = mod.host[EventCounterPlugin].logic.get
        val cnt = out(modCnt.counter.resize(8))
      })
    }.setName("TestComb")
  }

The fiber build/setup phase will not start before the elaboration main thread is done. So the code was blocked on the mod.host[EventCounterPlugin].logic.get.

The diagnostic for that case can be done seen the error message :

[Progress] at 0.000 : Elaborate components
The main thread is stuck at :
...
app//vexiiriscv.sandbox.Miaouuuu9$$anonfun$6$$anon$2.<init>(Play.scala:80)

:)