纤程框架(Fiber Framework)
目前还在发展中。
纤程(Fiber)可以以乱序行为运行硬件生成, 其与Makefile类似, 用户可以定义运行命令时所需的规则和依赖。这和Scala Future的特性很像。
这样的框架将一些简单的事物复杂化但也为复杂情况提供了一些强特性:
用户可以在知道需求前定义某些事物, 例如:可以在知道需要多少行中断前例化一个中断控制器。
抽象/懒惰化(lazy)/部分化 SoC架构定义可以允许SoC模板未来的特定化。
以去中心化方式对多个任务进行自动需求仲裁, 例如:在一个内存总线的主端口和从端口之间。
该框架主要组成为:
Handle[T], 可用于存储T类型的值。
handle.load允许设置句柄(handle)值的加载(将重新调度所有等待它的任务)。
handle.get, 返回给定句柄的值。如果该句柄尚未加载, 则会阻塞任务执行。
Handle{ code }, 分支出将执行给定代码的新任务。该代码的结果将加载到句柄中
soon(handle), 允许当前任务宣布, 其将加载一个值的句柄(用于跟踪句柄)
警告, 这不是通常的RTL描述, 并针对大型系统生成。它目前被用作SaxonSoC中的顶层集成工具。
一、简单的样例(Simple dummy example)
这里有一个简单的例子:
import spinal.core.fiber._
// 创建两个空句柄
val a, b = Handle[Int]
// 创建一个异步加载所给定值的句柄
val calculator = Handle {
a.get + b.get // .get 将会锁定他们直到它们被加载
// Same as above
val printer = Handle {
println(s"a + b = ${calculator.get}") // .get 将会锁定直到计算主体被完成
}
// 同步加载a和b, 这将锁定a.get和b.get
a.load(3)
b.load(4)
它的运行步骤将会是:
创建a和b
创建计算器任务分支, 但在执行a.get时被阻塞
创建打印任务分支, 但在执行calculator.get时被阻塞
加载a和b, 重新调度计算器任务(因为它正在等待a)
计算器完成a+b操作, 并将结果载入它的句柄, 这将重新调度打印任务
打印任务打印其结果
完成所有
所以, 这个例子主要是为了展示SpinalHDL可以克服顺序执行等, 因为a和b可以在计算器的定义后被加载。
二、Handle[T]
Handle[T]类似于scala的Future[T], 它们允许在某个对象存在之前就调用它, 并等待它。
val x,y = Handle[Int]
val xPlus2 : Handle[Int] = x.produce(x.get + 2) //x.produce 可以被用来当x加载时创建一个新句柄
val xPlus3 : Handle[Int] = x.derivate(_ + 3) //x.derivate 和 x.produce类似, 但也要提供x.get作为lambda函数的参数
x.load(3) //x 将会包含值为3
soon(handle)
为了维护一个正确的任务和句柄之间的依赖关系图, 任务可以预先指明它将加载一个给定的句柄。这在生成程序发生饥饿(Starvation)/死锁(deadlock)的情况下非常有用, 以便SpinalHDL准确地报告问题所在。