Spinal Netlist API相关介绍

Overview

Instance

从DSL层面,一个component内包含两种语句statement

  • Declaration:声明,对应于出现的各个Data
  • Assignment:赋值,除了声明Data、子模块外的,所有语句均作为表达式的容器 ExpressionContainer
    • 逻辑计算
    • 连接
      • 模块端口连接
      • 寄存器连接
  • Tree:控制流
    • When
    • Switch
  • 断言:

语句和实际写在scala里的一个语句不同。Scala语句,往往嵌套多个Spinal语句。

语句作为容器,装载不同类型的表达式 Expression

  • 数据:直接对应表达式中涉及的Data
  • 操作符:逻辑计算的各种一元、二元操作符 Operator;操作符同样是 表达式容器,包含其涉及的操作数。

Operation

遍历

  • foreach,遍历容器内的元素,但只迭代一级
  • walk,迭代至最底层

置换

  • remap,将一个Expression,通过一个function映射到新的一个Expression

删除

  • remove

语句容器 ScopeStatement

每个语句都处于一个 parentScope 中,这样一个Scope,以 ScopeStatement 的形式出现。

定义:class ScopeStatement(var parentStatement: TreeStatement)

每个Component都有一个 dslBody 作为其Scope,容纳Statement。每个 dslBodyparentStatement 都是null,因为其直接是模块第一层容器。Scope也包含一个指向其Component的引用 component

WhenSwitch 语句也可以张开一个Scope,在 dslBody 的基础上。相当于入栈一个新的Scope。

Scope以环形链表来组织其内部的语句,每个scope有一个 headlast 指针,指向链表头尾两条语句。其以 prependappend 的方法来插入语句。语句作为链表的节点,有 nextScopeStatementlastScopeStatement 两个引用来指向其上一个和下一个节点语句。语句的 parentScope 指向自己所属的Scope。

当一条语句写在一个Scope内时,其首先会把自己加入到当前Scope中。如BaseType,就是这么做的

1
2
3
4
DslScopeStack.get match {
case null =>
case scope => scope.append(this) //当你声明一个数据 自动加入栈顶Scope
}

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 表达式。
  • 二元:包含 leftright 两个子表达式。

多选符Multiplexer

包含一个选择表达式 select 和待选的表达式数组 inputs

二选符BinaryMultiplexer

包含一个条件 cond , 以及两个带选项, whenTruewhenFalse

访问符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

方法:删除自己

语句安排为两个分类,TreeStatementLeafStatement

Leaf

直接继承Statement。几种最底层的语句,

  • DeclarationStatement, 数据节点

数据节点对foreach、remap子表达式的操作进行了覆写,这两种操作被无效了,因为它们没有子表达式。

  • AssignmentStatement ,赋值连接

赋值包含 targetsource 两个表达式。

  • Memory Port,读写端口,伪数据节点

Tree

继承Statement,但自己同样包含语句的容器 ScopeStatement,区分为两种

  • WhenStatement, 包含两个语句子容器 whenTruewhenFalse ,以及作为条件表达式的 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