-
Notifications
You must be signed in to change notification settings - Fork 49
Home
作者:Jonathan Bachrach, Huy Vo, Krste Asanovi´c EECS Department, UC Berkeley {jrb|huytbvo|krste}@eecs.berkeley.edu April 10, 2016
翻译:redpanda3 EECS Department, UC Berkeley yuda at berkeley.edu 欢迎交流
这篇文档是Chisel(使用scala嵌入式语言构建硬件)。Chisel是一嵌入在高阶语言scala的硬件构建语言。一个分开的Chisel教程文档提供了一个大概的Chisel的介绍,并且应该先读。这个手册提供了一个完整的Chisel语言的概括和功能,这个真的只Scala内部的特殊的类,预先定义的对象,和使用方式的一个集合。当你写Chisel程序的时候你实际上在写一个Scala的程序。在这个手册里,我们假设你真的理解Scala的基础。如果你对Scala不熟悉,我们推荐你看其中一本不错的Scala书。
任何Chisel的硬件语言设计是最终以节点对象的一个图来标识的。用户在Chisel编码生成这个节点图,然后传到Chisel的后端被翻译成Verilog或是C++代码。节点被定义如下:
class Node{
//使用者命名或被纠正
var name: String = ""
//进来的图的边
def inputs: ArrayBuffer[Node]
//出去的图的边
def consumers: ArrayBuffer[Node]
//节点规定的推理宽度
def inferWidth: Int
//得到可直接推理的宽度
def getWidth: Int
//得到第一个未加工的节点
def getRawNode: Node
//转换为未加工的位元
def toBits: Bits
//从未加工的位元转换为该类型
def fromBits(x: Bits): this.type
//返回不变量,如果可推测的话,否则是null
def litOf: Lit
//返回不变量对应的值,如果litOf不是零的话
def litValue(default: BigInt = BigInt(-1)): BigInt
}
最高阶的节点类的层级在图1中表示。基本上的类别是:
Lit(不变量) - 常量或是标称,
Op(操作) - 逻辑或是算术操作,
Updateable(可更新的) - 被条件更新的结点,
Data(数据) - 有类型的线或端口,
Reg(寄存器) - 正向边缘触发的寄存器,和
Mem(存储器) - 存储器。
图1
未经处理的标称被表示为不变量的如下定义:
class Lit extends Node{
//原来的值
val inputVal: BigInt
}
未经处理的标称含有位元的集合。用户不能直接创造未经处理的标称,但是可以使用在第五部分定义的类别创造器取代。
未经处理的操作被表示为Op结点,被如下定义:
class Op extends Node{
//原来的值
val op: string
}
Op计算输入的组合函数。
一个Chisel的图像表示一个含有raw和type的节点的硬件设计。Chisel的类型系统被暗涵的Scala的类型系统分开保存,所以类型节点被穿插在未经处理的节点用来允许Chisel检查和响应给Chisel的类型。Chisel的类型结点在硬件设计被翻译为C++或Verilog前被擦除。_getRawNode_操作在基础的Node类中被定义,忽略类型节点并返回发现的第一个发现的未经处理的节点。图片2表示内置的Chisel类型的层级,Data作为最高的节点。
内置的Scala类型包括Bool(逻辑),SInt(有符号整型),和UInt(无符号整型)以及内置的扩展类型Bundle(束) 和Vec(矢量)允许用户使用其它几种类型拓展Chisel的数据类型集合。
数据本身作为一个节点:
abstract class Data extends Node {
override def cloneType(): this.type =
this.getClass.newInstance.
asInstanceOf[this.type]
// simple conversions
def toSInt: SInt
def toUInt: UInt
def toBool: Bool
def toBits: Bits
// flatten out to leaves of tree
def flatten: Array[(String, Data)]
// port direction if leaf
def dir: PortDir
// change dir to OUTPUT
def asOutput: this.type
// change dir to INPUT
def asInput: this.type
// change polarity of dir
def flip: this.type
// assign to input
def :=[T <: Data](t: T)
// bulk assign to input
def <>(t: Data)
}
Data的类有转换类型的方法和对其输入指派端口的方法。我们会在第十部分讨论端口。最后,用户可以覆盖cloneType的方法变为它们自己的节点类型(例如,束),为了传递有必要克隆的构成参数。