Skip to content

Commit

Permalink
SpinalHDL 1.10.0
Browse files Browse the repository at this point in the history
Merge branch 'dev'
  • Loading branch information
Dolu1990 committed Jan 4, 2024
2 parents 2700185 + 058f199 commit 19725a4
Show file tree
Hide file tree
Showing 84 changed files with 4,255 additions and 314 deletions.
File renamed without changes.
4 changes: 4 additions & 0 deletions core/src/main/scala/spinal/core/Area.scala
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class Composite[T <: Nameable](val self : T, postfix : String = null, weak : Boo
}

trait Area extends NameableByComponent with ContextUser with OwnableRef with ScalaLocated with ValCallbackRec with OverridedEqualsHashCode {
if(globalData != null) globalData.onAreaInit.foreach{f =>
f(this)
globalData.onAreaInit = None
}
def childNamePriority = DATAMODEL_WEAK
val _context = ScopeProperty.capture() //TODO not as heavy
def rework[T](body : => T): T = {
Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/spinal/core/Bits.scala
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,8 @@ class Bits extends BitVector with DataPrimitives[Bits] with BaseTypePrimitives[B
* @return The alias
*/
def aliasAs[T <: Data](t : HardType[T]) : T = {
val wrap = this.as(t)
val wrap = t()
wrap.assignFromBits(this.asBits.resized)
var offsetCounter = 0
for (e <- wrap.flatten) {
val eWidth = e.getBitsWidth
Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/spinal/core/Bool.scala
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ class Bool extends BaseType with DataPrimitives[Bool] with BaseTypePrimitives[B
}

override def assignFromBits(bits: Bits): Unit = {
assert(widthOf(bits) == 1)
assert(widthOf(bits) == 1 || bits.hasTag(tagAutoResize))
this := bits(0)
}

Expand Down
15 changes: 12 additions & 3 deletions core/src/main/scala/spinal/core/ClockDomain.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,18 @@ object ASYNC extends ResetKind
object SYNC extends ResetKind
object BOOT extends ResetKind

sealed trait Polarity
object HIGH extends Polarity
object LOW extends Polarity
sealed trait Polarity{
def assertedBool : Bool
def deassertedBool : Bool
}
object HIGH extends Polarity{
override def assertedBool: Bool = True
override def deassertedBool: Bool = False
}
object LOW extends Polarity{
override def assertedBool: Bool = False
override def deassertedBool: Bool = True
}

case class ClockDomainTag(clockDomain: ClockDomain) extends SpinalTag{
override def toString = s"ClockDomainTag($clockDomain)"
Expand Down
10 changes: 8 additions & 2 deletions core/src/main/scala/spinal/core/Component.scala
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,14 @@ object Component {
* @see [[http://spinalhdl.github.io/SpinalDoc/spinal/core/components_hierarchy Component Documentation]]
*/
abstract class Component extends NameableByComponent with ContextUser with ScalaLocated with PostInitCallback with Stackable with OwnableRef with SpinalTagReady with OverridedEqualsHashCode with ValCallbackRec {
if(globalData.toplevel == null) globalData.toplevel = this
if(globalData.phaseContext.topLevel == null) globalData.phaseContext.topLevel = this
if(parentScope == null) {
if(globalData.config.singleTopLevel) {
if (globalData.toplevel != null) SpinalError(s"MULTIPLE TOPLEVEL : SpinalHDL only allows a single toplevel Component.\n- ${globalData.toplevel.getClass}\n- ${this.getClass}")
assert(globalData.phaseContext.topLevel == null, "???")
}
globalData.toplevel = this
globalData.phaseContext.topLevel = this
}
val dslBody = new ScopeStatement(null)

dslBody.component = this
Expand Down
38 changes: 38 additions & 0 deletions core/src/main/scala/spinal/core/Misc.scala
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ object isPow2 {
if (that < 0) return false
that.bitCount == 1
}
def apply(that : Int) : Boolean = apply(BigInt(that))
}


Expand Down Expand Up @@ -155,6 +156,14 @@ class HardType[T <: Data](t : => T) extends OverridedEqualsHashCode{
}


object NamedType{
def apply[T <: Data](gen : => T) = new NamedType(gen)
def apply[T <: Data](gen : HardType[T]) = new NamedType(gen.craft())
}

class NamedType[T <: Data](gen : => T) extends HardType(gen) with Nameable


object signalCache{
def apply[T](key: Any)(factory: => T): T = {
Component.current.userCache.getOrElseUpdate(key, factory).asInstanceOf[T]
Expand Down Expand Up @@ -588,6 +597,35 @@ object ContextSwapper{
t.allowSuspend = true
ret // return the value returned by that
}

//Allows to (only) to create base type instances on the top of the netlist. Support Fiber suspend
def outsideCondScopeData[T <: Data](that: => T): T = {
val dummyBody = new ScopeStatement(null)
dummyBody.component = Component.current
val ctx = dummyBody.push() // Now all access to the SpinalHDL API will be append to it (instead of the current context)
val ret = that // Execute the block of code (will be added to the recently empty body)
ctx.restore() // Restore the original context in which this function was called

val topBody = Component.current.dslBody // Get the head of the current component symboles tree (AST in other words)
val oldHead = topBody.head
val oldLast = topBody.last
val addedHead = dummyBody.head
val addedLast = dummyBody.last

//Move the AST from dummyBody to the head of topBody
dummyBody.foreachStatements {
case cu: ContextUser => cu.parentScope = topBody
case _ =>
}
topBody.head = addedHead
addedHead.lastScopeStatement = null.asInstanceOf[Statement]
addedLast.nextScopeStatement = oldHead
if(oldHead != null) oldHead.lastScopeStatement = addedLast
if(oldLast != null) oldLast.nextScopeStatement = null.asInstanceOf[Statement]
topBody.last = oldLast

ret // return the value returned by that
}
}


Expand Down
3 changes: 2 additions & 1 deletion core/src/main/scala/spinal/core/Spinal.scala
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ case class SpinalConfig(mode : SpinalMode = null,
private [core] var _withEnumString : Boolean = true,
var enumPrefixEnable : Boolean = true,
var enumGlobalEnable : Boolean = false,
bitVectorWidthMax : Int = 4096
bitVectorWidthMax : Int = 4096,
var singleTopLevel : Boolean = true
){
def generate [T <: Component](gen: => T): SpinalReport[T] = Spinal(this)(gen)
def generateVhdl [T <: Component](gen: => T): SpinalReport[T] = Spinal(this.copy(mode = VHDL))(gen)
Expand Down
5 changes: 4 additions & 1 deletion core/src/main/scala/spinal/core/Trait.scala
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ class GlobalData(val config : SpinalConfig) {
val scalaLocatedComponents = mutable.HashSet[Class[_]]()
val scalaLocateds = mutable.HashSet[ScalaLocated]()
val elab = new Fiber()
elab.setName("global_elab")
elab.inflightLock.globalData = this
var onAreaInit = Option.empty[Area => Unit]

def applyScalaLocated(): Unit ={
try {
Expand Down Expand Up @@ -191,7 +194,7 @@ class GlobalData(val config : SpinalConfig) {

/** Get a link to the globalData */
trait GlobalDataUser {
val globalData = GlobalData.get
var globalData = GlobalData.get
}


Expand Down
2 changes: 1 addition & 1 deletion core/src/main/scala/spinal/core/fiber/AsyncThread.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,6 @@ class AsyncThread(parent : AsyncThread, engine: EngineContext, body : => Unit) e

override def toString: String = {
if(isNamed) return getName()
if(willLoadHandles.nonEmpty) s"${willLoadHandles.map(_.getName("???")).mkString(", ")} loader" else super.toString
if(willLoadHandles.nonEmpty) s"${willLoadHandles.filter(!_.isLoaded).map(_.getName("???")).mkString(", ")} loader" else super.toString
}
}
127 changes: 96 additions & 31 deletions core/src/main/scala/spinal/core/fiber/Fiber.scala
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package spinal.core.fiber

import spinal.core.GlobalData
import spinal.core.{Area, GlobalData}

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.reflect.{ClassTag, classTag}
import scala.reflect.runtime.universe._

object ElabOrderId{
val INIT = -1000000
Expand All @@ -13,52 +15,115 @@ object ElabOrderId{
}

object Fiber {
def apply[T](orderId : Int)(body : => T) : Handle[T] = {
def apply[T: ClassTag](orderId : Int)(body : => T) : Handle[T] = {
GlobalData.get.elab.addTask(orderId)(body)
}
def setup[T](body : => T) : Handle[T] = apply(ElabOrderId.SETUP)(body)
def build[T](body : => T) : Handle[T] = apply(ElabOrderId.BUILD)(body)
def check[T](body : => T) : Handle[T] = apply(ElabOrderId.CHECK)(body)
def setup[T: ClassTag](body : => T) : Handle[T] = apply(ElabOrderId.SETUP)(body)
def build[T: ClassTag](body : => T) : Handle[T] = apply(ElabOrderId.BUILD)(body)
def check[T: ClassTag](body : => T) : Handle[T] = apply(ElabOrderId.CHECK)(body)

def callback(orderId: Int)(body: => Unit): Unit = {
GlobalData.get.elab.addCallback(orderId)(body)
}

def setupCallback(body: => Unit): Unit = callback(ElabOrderId.SETUP)(body)
def buildCallback(body: => Unit): Unit = callback(ElabOrderId.BUILD)(body)

def await(id : Int): Unit = {
GlobalData.get.elab.await(id)
}

def awaitSetup() = await(ElabOrderId.SETUP)
def awaitBuild() = await(ElabOrderId.BUILD)
def awaitCheck() = await(ElabOrderId.CHECK)
}

class Fiber {
class Fiber extends Area{
var currentOrderId = ElabOrderId.INIT
def addTask[T](orderId : Int)(body : => T) : Handle[T] = {


class Fence(id : Int) extends Area{
val lock = Lock().retain()
assert(currentOrderId <= orderId)
if(currentOrderId == orderId) lock.release()
val (h, t) = hardForkRaw(withDep = false){
val pendings = mutable.ArrayBuffer[AsyncThread]()
def await(): Unit = {
pendings += AsyncThread.current
lock.await()
body
}
lock.setCompositeName(h, "lock")
tasks.getOrElseUpdate(orderId, mutable.Queue[(Lock, Handle[_], AsyncThread)]()) += Tuple3(lock, h, t)
setCompositeName(Fiber.this, s"lock_${id.toString}")
}

val inflightLock = Lock()
val inflight = mutable.LinkedHashSet[AsyncThread]()
val fences = mutable.LinkedHashMap[Int, Fence]()
val callbacks = new mutable.LinkedHashMap[Int, mutable.Queue[() => Unit]]()

private def active(t : AsyncThread): Unit = {
inflight += t
inflightLock.retain()
}

private def idle(): Unit = {
inflight -= AsyncThread.current
inflightLock.release()
}

def addTask[T: ClassTag](body: => T): Handle[T] = {
addTask(ElabOrderId.INIT)(body)
}
def addTask[T: ClassTag](orderId : Int)(body : => T) : Handle[T] = {
val (h, t) = hardForkRawHandle(withDep = true) { h : Handle[T] =>
Fiber.await(orderId)
if(classTag[T].runtimeClass == classOf[Area]) {
GlobalData.get.onAreaInit = Some(a => a.setCompositeName(h))
}
val ret = body
idle()
ret
}
t.setCompositeName(h)
active(t)
h
}
val tasks = new mutable.LinkedHashMap[Int, mutable.Queue[(Lock, Handle[_], AsyncThread)]]()

def await(id : Int) = {
idle()
fences.getOrElseUpdate(id, new Fence(id)).await()
}

def addCallback(orderId : Int)(body : => Unit): Unit = {
callbacks.getOrElseUpdate(orderId, mutable.Queue[() => Unit]()).enqueue(() => body)
}


def runSync(): Unit ={
val e = Engine.get

//Link locks to current thread
tasks.foreach(_._2.foreach{ e =>
e._1.willBeLoadedBy = AsyncThread.current
AsyncThread.current.addSoonHandle(e._1)
})
while(tasks.nonEmpty){
val orderId = tasks.keys.min
fences.values.foreach{ e =>
e.lock.willBeLoadedBy = AsyncThread.current
AsyncThread.current.addSoonHandle(e.lock)
}
while(fences.nonEmpty || callbacks.nonEmpty || inflight.nonEmpty){
inflightLock.await()
assert(inflight.size == 0)

val orderId = (fences.keys ++ callbacks.keys).min
currentOrderId = orderId
val queue = tasks(orderId)
val locks = ArrayBuffer[Handle[_]]()
while(queue.nonEmpty){
val (l, h, t) = queue.dequeue()
h.willBeLoadedBy = t
t.addSoonHandle(h)
l.release()
locks += h

callbacks.get(orderId).foreach{ l =>
l.foreach(_.apply())
callbacks.remove(orderId)
}
locks.foreach(_.await())
tasks.remove(orderId)

fences.get(orderId) match {
case Some(lock) => {
lock.pendings.foreach(active)
lock.lock.release()
fences.remove(orderId)
}
case None =>
}

inflightLock.await()
}
}
}
Expand Down
Loading

0 comments on commit 19725a4

Please sign in to comment.