Chisel 手册(part1)

作者:Jonathan Bachrach, Huy Vo, Krste Asanović;  EECS Department, UC Berkeley

译者:智能物联(CSDN)

1 简介

本文为Chisel手册 (Constructing Hardware In a Scala Embedded Language)。Chisel是一种内置于scala高级编程语言之上的硬件构建语言。我们还提供了一个单独的Chisel Tutorial作为简单的入门课程文档,用于早期阅读。本手册对Chisel语言给出了全面的概述和定义,Chisel实际上仅仅是包括特殊定义的class类,预定义的对象以及scala的使用习惯的一个集合。当你在写Chisel程序的时候,你实际上写的是Scala程序。本手册假定你已经基本掌握Scala语言。如果你尚不熟悉如果使用Scala,我们推荐你查阅优秀的Scala书籍 ([3], [2]).

2 节点(Nodes)

Chisel编写的任何硬件设计最终能用一个节点(node)对象的图表(graph)来表示。Chisel用户代码生成节点的图表,然后传给Chisel后端,翻译成Verilog或者C++ 代码。节点定义如下所示:


class Node { // name assigned by user or from introspection var name: String = "" // incoming graph edges def inputs: ArrayBuffer[Node] // outgoing graph edges def consumers: ArrayBuffer[Node] // node specific width inference def inferWidth: Int // get width immediately inferrable def getWidth: Int // get first raw node def getRawNode: Node // convert to raw bits def toBits: Bits // convert to raw bits def fromBits(x: Bits): this.type // return lit value if inferrable else null def litOf: Lit // return value of lit if litOf is non null def litValue(default: BigInt = BigInt(-1)): BigInt
}

节点的最上面层级参见图1。节点的基本类别如下:

Lit

– 常数或文字

Op

– 逻辑或者算数运算符

Updateable

– 条件更新节点

Data

– typed wires 或者 ports,

Reg

– 正沿触发寄存器

Mem

– 存储器


图1: 节点层次结构


3 Lits

Raw literals 作为 Lit nodes 定义如下:


class Lit extends Node { // original value val inputVal: BigInt
}

Raw literals为bits的集合。用户并不直接创建raw literals,而是使用type constructors,参见Section 5.

4 Ops

Raw operations 作为Op nodes 定义如下:


class Op extends Node { // op name used during emission val op: String
}

Ops运算操作符运算输入的组合函数。

5 Types

一个能够表示硬件设计的Chisel图表包括raw和type节点。Chisel type系统独立于Scala type系统,单独维护,type节点与raw节点杂处,以便Chisel检查和对应到Chisel types。硬件设计被转换成 C++ 或者 Verilog代码以后,Chisel type节点被全部删除。Node基类定义的getRawNode运算符,跳过type nodes,返回第一个raw node。图 2 展示了内建Chisel type层次结构,Data为最顶层的节点(node)


图2:Chisel type层次结构


内建scalar类型包括Bool,SInt,UInt;内建集合(aggregate)类型Bundle和Vec方便用户扩展其他的Chisel数据类型。

Data本身是一个节点:


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类拥有用于type转换的method,代理port method到输入。我们将在第10节讨论port。最后,为了反映克隆所必要的构造参数,用户可以在自己的type节点(比如bundle)里面重载cloneType方法。

Data节点有四种用法:

  • types – UInt(width = 8) – 记录图表的中间态types,使用最小的比特宽度(本节所描述),
  • wires – UInt(width = 8) – 数据的前向声明,可以条件更新 (第6节描述),
  • ports – UInt(dir = OUTPUT, width = 8) – module接口专用wire,另加direction属性(参见第十节),
  • literals – UInt(1) or UInt(1, 8) – 使用type对象构造器生成,指定值和可选的位宽。

5.1 Bits

在Chisel中,Bits的原始集合可以如下定义:


object Bits { def apply(dir: PortDir = null, width: Int = -1): Bits // create literal from BigInt or Int def apply(value: BigInt, width: Int = -1): Bits // create literal from String using // base_char digit+ string format def apply(value: String, width: Int = -1): Bits
} class Bits extends Data with Updateable { // bitwise-not def unary_~(): Bits // bitwise-and def &  (b: Bits): Bits // bitwise-or def |  (b: Bits): Bits // bitwise-xor def ^  (b: Bits): Bits // and-reduction def andR(): Bool // or-reduction def orR():  Bool // xor-reduction def xorR():  Bool // logical NOT def unary_!(): Bool // logical AND def && (b: Bool): Bool // logical OR def || (b: Bool): Bool // equality def ===(b: Bits): Bool // inequality def != (b: Bits): Bool // logical left shift def << (b: UInt): Bits // logical right shift def >> (b: UInt): Bits // concatenate def ## (b: Bits): Bits // extract single bit, LSB is 0 def apply(x: Int): Bits // extract bit field from end to start bit pos def apply(hi: Int, lo: Int): Bits
} def Cat[T <: Data](elt: T, elts: T*): Bits

Bits拥有简单比特操作的method。请注意## 为二进制串接操作,而Cat为任意进制串接操作。为了避免与Scala的内建双联等于号==起冲突,Chisel的按比特比较使用三联等于号===。

宽度为n的比特可以使用单比特和Fill函数生成:


def Fill(n: Int, field: Bits): Bits

两个输入使用Mux来选择:


def Mux[T <: Data](sel: Bits, cons: T, alt: T): T

Constant或者literal值,使用Scala整数或者字符串传递给类型构造器来表示:


UInt(1)       // decimal 1-bit lit from Scala Int.
UInt("ha")    // hex 4-bit lit from string.
UInt("o12")   // octal 4-bit lit from string.
UInt("b1010") // binary 4-bit lit from string.

生成Lit,参见 图3 中最左边的子图

运算符操作返回一个实际的运算符节点,包括一个组合了所有输入type节点的type节点。参见图3,查看连续的更复杂例子。


a = UInt(1) b = a & UInt(2) b | UInt(3)
 

图 3: Chisel Op/Lit 图表


5.2 Bools

布尔值可以定义为 Bools:


object Bool { def apply(dir: PortDir = null): Bool // create literal def apply(value: Boolean): Bool
} class Bool extends UInt

Bool 等同于 UInt(width = 1).

5.3 Nums

Num是定义算数运算的type节点:


class Num extends Bits { // Negation def unary_-(): Bits // Addition def +(b: Num): Num // Subtraction def -(b: Num): Num // Multiplication def *(b: Num): Num // Greater than def >(b: Num): Bool // Less than def <(b: Num): Bool // Less than or equal def <=(b: Num): Bool // Greater than or equal def >=(b: Num): Bool
}

有符号和无符号整数是定点数的子集,分别用SInt和UInt来表示:


object SInt { def apply (dir: PortDir = null, width: Int = -1): SInt // create literal def apply (value: BigInt, width: Int = -1): SInt def apply (value: String, width: Int = -1): SInt
} class SInt extends Num object UInt { def apply(dir: PortDir = null, width: Int = -1): UInt // create literal def apply(value: BigInt, width: Int = -1): UInt def apply(value: String, width: Int = -1): UInt
} class UInt extends Num { // arithmetic right shift override def >> (b: UInt): SInt
}

有符号定点数,包括整数,使用补码表示。

5.4 Bundles

Bundles可以把若干可能不同的数据类型组合在一起,很类似C中的struct:


class Bundle extends Data { // shallow named bundle elements def elements: ArrayBuffer[(String, Data)]
}

Bundle中每个元素的名称和类型通过element方法获取,flatten method返回嵌套aggregate末端的元素。用户可以通过扩展子类来定义新的bundle:


class MyFloat extends Bundle { val sign        = Bool() val exponent    = UInt(width = 8) val significand = UInt(width = 23)
}

Bundle元素访问使用Scala的域field:


val x  = new MyFloat()
val xs = x.sign

C++ 或者Verilog后端内对bundle元素的命名,取自其bundle的域名,使用Scala introspection。

5.5 Vecs

Vecs 生成可索引的元素矢量:


object Vec { def apply[T <: Data](elts: Seq[T]): Vec[T] def apply[T <: Data](elt0: T, elts: T*): Vec[T] def fill[T <: Data](n: Int)(gen: => T): Vec[T] def tabulate[T <: Data](n: Int) (gen: (Int) => T): Vec[T] def tabulate[T <: Data](n1: Int, n2: Int) (gen: (Int, Int) => T): Vec[Vec[T]]
} class Vec[T <: Data](n: Int, val gen: () => T) extends Data { def apply(idx: UInt): T def apply(idx: Int): T def forall(p: T => Bool): Bool def exists(p: T => Bool): Bool def contains[T <: Bits](x: T): Bool def count(p: T => Bool): UInt def indexWhere(p: T => Bool): UInt def lastIndexWhere(p: T => Bool): UInt
}

with n elements of type defined with the gen thunk. Users can access elements statically with an Int index or dynamically using a UInt index, where dynamic access creates a virtual type node (representing a read “port”) that records the read using the given address. In either case, users can wire to the result of a read as follows:


v(a) := d

只读存储可以表示成literal的矢量:


val rom = Vec(UInt(3), UInt(7), UInt(4), UInt(0)) { UInt(width=3) }
val dout = rom(addr)

5.6 位宽推定

用户必须设置端口和寄存器的位宽,但是,节点的位宽是自动推定的,除非由用户手动设置(使用Extract 或者 Cat)。位宽推定引擎从图表的输入端口开始计算节点的输出位宽,按照下列表格所列的规则:

operation bit width
z = x + y wz = max(wx, wy)
z = x - y wz = max(wx, wy)
z = x & y wz = max(wx, wy)
z = Mux(c, x, y) wz = max(wx, wy)
z = w * y wz = wx + wy
z = x << n wz = wx + maxNum(n)
z = x >> n wz = wx - minNum(n)
z = Cat(x, y) wz = wx + wy
z = Fill(n, x) wz = wx * maxNum(n)
 

wz为wire z的位宽,规则适用于所有按比特逻辑操作。

位宽推定持续,直到位宽不再变化。除了向右移位常数个位移,位宽推定规则导致的输出位宽不可能小于输入位宽,因此,输出位宽要么变大,要么保持不变。更进一步,寄存器的宽度必须由用户显式指定,或者通过reset值的位宽指定。通过这两个要求,我们能够确保位宽推定过程将收敛导一个固定的位置。

& 操作不应该返回输入位宽的min()?

Chisel 手册(中文part1)相关推荐

  1. Chisel 手册(中文part2)

    Chisel 手册(中文part2) 作者:Jonathan Bachrach, Huy Vo, Krste Asanović:  EECS Department, UC Berkeley 译者:智能 ...

  2. UE4手册中文翻译速查表

    虚幻中国-UE4 用户文档4.6 首页- 资讯- UE4专区- UE3(UDK)专区- 游戏- 招聘- 开发专区- 博客Blog- 论坛BBS- 专题 入门指南 编辑器手册 编程指南 示例和教程 UE ...

  3. opencv2计算机视觉编程手册(中文)pdf

    opencv2计算机视觉编程手册(中文).pdf高清电子版,非常好的资料,需要的可以下载使用! 下载地址:http://download.csdn.net/download/a5820736/7568 ...

  4. linux获取完整的man(manpages)linux参考手册/中文man的下载和使用/获取buildin 命令的完整帮助文档/多种man手册/man着色colorful man

    文章目录 获取完整的man(manpages)linux参考手册/中文man的下载和使用/获取buildin 命令的完整帮助文档 搜索manpages 相关package 安装扩展man手册 refe ...

  5. 欧姆龙r88d系列服务器说明书,欧姆龙R88D/R88M选型使用手册(中文)

    资料介绍: 欧姆龙,OMRON,R88D/R88M选型使用手册(中文) R88D-KP02H-Z R88D-WN01L-ML2 R88D-KN150H-ECT-Z R88D-GT01H-Z R88D- ...

  6. Spring Framework 开发参考手册中文(在线HTML)

    '原文:http://blog.csdn.net/zfrong/article/details/3971722 Spring Framework 开发参考手册中文(在线HTML) Spring Fra ...

  7. 实用卷积神经网络 运用python pdf_解析卷积神经网络—深度学习实践手册 中文pdf高清版...

    解析卷积神经网络-深度学习实践手册从实用角度着重解析了深度学习中的一类神经网络模型--卷积神经网络,向读者剖析了卷积神经网络的基本部件与工作机理,更重要的是系统性的介绍了深度卷积神经网络在实践应用方面 ...

  8. java part part,java泛型指导手册(part1),指导手册part1

    java泛型指导手册(part1),指导手册part1 index 1.大致了解一下 从java5开始,泛型就被加入了java.泛型的意义在于:在你操作object之前,提供了一种指定特定类型为更加通 ...

  9. libmodbus官方手册中文翻译

    最近做libmodbus相关内容,因为中文没有libmodbus各个函数的详细解释,所以在此把要用的libmodbus的官方手册包括所有的函数都翻译整理一下,给自己和大家们学习,欢迎大家交流指正.手册 ...

最新文章

  1. 进程状态控制-进程创建
  2. 深度学习中的双下降现象
  3. java乌龟_java用swing画可以行走的乌龟
  4. CodeForces 1213F (强联通分量分解+拓扑排序)
  5. asp关于从utf8页面到gb2312页面出现乱码得解决
  6. 训练日志 2019.7.26
  7. 最优化读书笔记R(一)
  8. hashmap put过程_面试官:HashMap 为什么线程不安全?
  9. 面向对象的七种设计原则
  10. 2018-03-22笔记,象棋记谱法
  11. 网站php镜像小偷,网站被镜像了怎么办?
  12. [TopCoder] SRM 587 DIV 2, 250p, 500p, 1000p, Solution
  13. windows压缩卷的操作
  14. 浅谈基于过程与基于对象
  15. 微信小程序学习第8天——自定义组件的数据监听器Observer小案例
  16. vs2022安装dev控件工具箱不显示
  17. 笔记本更换SATA3接口的固态硬盘注意事项
  18. NG_ML_Cousera_Summary
  19. 2019年c++/c,java,python,前端,数据结构,ps等资料大全
  20. 计算机辅助骨科手术的常用简称,大连理工大学创客:计算机辅助骨科手术提高接骨精准度...

热门文章

  1. OpenCV开发笔记(五十八):红胖子8分钟带你深入了解图像的矩(图文并茂+浅显易懂+程序源码)
  2. OpenCV开发笔记(五十九):红胖子8分钟带你深入了解分水岭算法(图文并茂+浅显易懂+程序源码)
  3. 图像处理+机器学习相关资源整合
  4. ubuntu下使用testerSunshine12306抢票程序
  5. JVM 上篇(4):虚拟机栈
  6. 2017杭州云栖大会 智能客服专场预热 — 用心服务客户,用云助力客服
  7. 在自建机房给网站做ICP备案
  8. Android RadarScanView雷达扫描控件
  9. SNS网店软文推广法
  10. iOS 如何获取手机外网IP地址(附内网IP地址)