Overview Instance 从DSL层面,一个component内包含两种语句statement,
Declaration:声明,对应于出现的各个Data
Assignment:赋值,除了声明Data、子模块外的,所有语句均作为表达式的容器 ExpressionContainer
Tree:控制流
断言:
语句和实际写在scala里的一个语句不同。Scala语句,往往嵌套多个Spinal语句。
语句作为容器,装载不同类型的表达式 Expression
数据:直接对应表达式中涉及的Data
操作符:逻辑计算的各种一元、二元操作符 Operator;操作符同样是 表达式容器,包含其涉及的操作数。
Operation 遍历
foreach,遍历容器内的元素,但只迭代一级
walk,迭代至最底层
置换
remap,将一个Expression,通过一个function映射到新的一个Expression
删除
语句容器 ScopeStatement 每个语句都处于一个 parentScope 中,这样一个Scope,以 ScopeStatement 的形式出现。
定义:class ScopeStatement(var parentStatement: TreeStatement)
每个Component都有一个 dslBody 作为其Scope,容纳Statement。每个 dslBody 的parentStatement 都是null,因为其直接是模块第一层容器。Scope也包含一个指向其Component的引用 component 。
When、Switch 语句也可以张开一个Scope,在 dslBody 的基础上。相当于入栈 一个新的Scope。
Scope以环形链表来组织其内部的语句,每个scope有一个 head 和 last 指针,指向链表头尾两条语句。其以 prepend 和 append 的方法来插入语句。语句作为链表的节点,有 nextScopeStatement 和 lastScopeStatement 两个引用来指向其上一个和下一个节点语句。语句的 parentScope 指向自己所属的Scope。
当一条语句写在一个Scope内时,其首先会把自己加入到当前Scope中。如BaseType,就是这么做的
1 2 3 4 DslScopeStack .get match { case null => case scope => scope.append(this ) }
Scope提供迭代语句的迭代器方法,以及foreach和walk的迭代方法。进一步,可以只迭代 DeclarationStatement。
表达式容器 仅仅提供容器基本操作。
一级遍历 遍历内部表达式,仅仅一级遍历,不会对内部表达式做进一步遍历。
1 2 def foreachExpression(func: (Expression) => Unit): Unit def foreachDrivingExpression(func: (Expression) => Unit): Unit = foreachExpression(func)
全部遍历 遍历内部表达式,直至最底层。
def walkExpression(func: (Expression) => Unit): Unit
def walkExpressionPostorder(func: (Expression) => Unit): Unit
def walkDrivingExpressions(func: (Expression) => Unit): Unit
置换元素 给一个置换函数,可以将容器内的表达式根据函数置换为新的表达式。
1 2 def remapExpressions(func: (Expression) => Expression): Unit def remapDrivingExpressions(func: (Expression) => Expression): Unit = remapExpressions(func)
遍历置换 遍历的同时,做置换。
def walkRemapExpressions(func: (Expression) => Expression): Unit
def walkRemapDrivingExpressions(func: (Expression) => Expression): Unit
表达式 Expression 定义,继承BaseNode,一个表达式自己也是表达式容器。
trait Expression extends BaseNode with ExpressionContainer
覆写了foreachDrivingExpression。
数据 这里的数据,不是 Data
数字信号 BaseType
即Spinal最基本,最单元的几种数据类型,Bool、BitVector、枚举、结构体。
注意到,数字信号本身即是表达式,也是一条声明语句。
模拟信号 AnalogDriver
包含一个data expression,一个enable expression。因此遍历和置换操作就发生在这两个表达式上。
字面值 Literal
各种数据类型的字面值。数字信号的字面量。表达式遍历和置换操作被取消。
修饰符 Modifier 是Expression 的别名,包括下面两种:
类型转换, Cast
在不同的基本数据类型之间做类型转换。包含一个 input ,遍历和置换发生在input
操作符 ,Operator
也是Expression 的别名。进一步分为:
一元,常数:两个实现基本一样,只包含一个 source 表达式。
二元:包含 left 和 right 两个子表达式。
多选符 ,Multiplexer
包含一个选择表达式 select 和待选的表达式数组 inputs
二选符 ,BinaryMultiplexer
包含一个条件 cond , 以及两个带选项, whenTrue 和 whenFalse
访问符 ,SubAccess
取出bitvector中的一个bitfiled,其首先包含被访问的 source 。和赋值类似,访问操作可以是静态的和动态的,可以访问一个bit或者一段bitfield。
静态访问 Fixed,访问的位置固定
Bit access:包含固定整数 bitId
Range access:包含固定整数 hi, lo
动态访问 Floating,访问的位置由表达式指定
Bit access: 包含 bitId 表达式
Range access:包含 offset 表达式,以及固定整数 size。
位宽 Resize 不同数据类型的位宽调整。包含被调节位宽的 input
赋值AssignmentExpression 赋值分为两种,静态索引和动态索引。BitVectorAssignmentExpression直接 继承 AssignmentExpression ,包含被赋值的数据 out 。因此迭代映射均作用在 out 上面。而对 driving expression的处理则被取消。
Fixed,除开包含 out 外
BitAssignmentFixed, 包含一个index来选择一个bit
RangedAssignmentFixed, 包含hi和lo来选择一个bit field
Floating,除开包含 out 外,
BitAssignmentFloating, 还包含 bitId 表达式用来索引一个单独的bit
RangedAssignmentFixed, 还包含 offset表达式用来索引一个范围
语句 Statement定义
trait Statement extends ExpressionContainer with ContextUser with ScalaLocated with BaseNode
方法:删除自己
语句安排为两个分类,TreeStatement 和 LeafStatement
Leaf 直接继承Statement。几种最底层的语句,
DeclarationStatement, 数据节点
数据节点对foreach、remap子表达式的操作进行了覆写,这两种操作被无效了,因为它们没有子表达式。
AssignmentStatement ,赋值连接
赋值包含 target 和 source 两个表达式。
Tree 继承Statement,但自己同样包含语句的容器 ScopeStatement,区分为两种
WhenStatement, 包含两个语句子容器 whenTrue 和 whenFalse ,以及作为条件表达式的 cond 。
SwitchStatement,包含 value 表达式,以及多个 SwitchStatementElement 。每个 SwitchStatementElement 包含一个 key 表达式,和一个语句子容器 scopeStatement 。
Tree意味着包含子tree,最后到leaf。因此额外提供针对语句的遍历操作(依赖Scope的遍历) :
def foreachStatements(func: Statement => Unit)
def walkStatements(func : Statement => Unit): Unit
也有进一步,只针对leaf的遍历:
def walkLeafStatements(func: LeafStatement => Unit): Unit
更进一步,只针对leaf中的非memory port:
def foreachDeclarations(func: DeclarationStatement => Unit): Unit
def walkDeclarations(func: DeclarationStatement => Unit): Unit