Chisel 手册(中文part1)

2023-11-06

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

– 存储器


pict 

图1: 节点层次结构


Lits

Raw literals 作为 Lit nodes 定义如下:

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

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

 

Ops

Raw operations 作为Op nodes 定义如下:

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

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

 

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)


pict 

图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,查看连续的更复杂例子。


 

pict pict pict
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()?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Chisel 手册(中文part1) 的相关文章

  • 后端即服务BaaS

    Bmob LeanCloud 腾讯TAB APICloud 作为移动开发者 你应该了解Baas 后端即服务 移动端免费可用的BaaS接入方案 通过Bmob Android轻松制作一个APP Android高效率编码 第三方SDK详解系列 二

随机推荐

  • Multi-Object Tracking with Multiple Cues and Switcher-Aware Classification 论文笔记

    Multi Object Tracking with Multiple Cues and Switcher Aware Classification 似乎是商汤投 CVPR2019的论文 文中提出了一个统一的多目标跟踪 MOT 框架 学习充
  • MFC实现图片浏览器

    MFC实现图片浏览器 源代码可以加微信 DDDDYKAJ 一 功能介绍 该程序是基于对话框的图片管理的程序 改程序有以下几个功能 1 获取加载图片的图片数目 2 按下 下一张 浏览所有图片 3 图片按照序号定位 并显示 4 获取每一张图片的
  • 前端练习项目

    30 Web Projects 30 多个带有 HTML CSS 和 JavaScript 的 Web 项目 由 Packt Publishing 提供 https github com PacktPublishing 30 Web Pro
  • Greenplum 查看连接与锁信息数据字典

    Greenplum 查看连接与锁信息数据字典 目录 查看系统中会话 连接 SQL与锁情况 1 查看当前活动的客户端连接数 2 查询客户端连接的情况 3 查看持有锁和等待锁的一些信息 已经修改验证 4 查询系统中正在执行的或者等待执行的事务
  • 怎么给word文档注音_怎么为整篇word文字添加拼音标注

    类型 教育学习大小 21 8M语言 中文 评分 10 0 标签 立即下载 有时候一篇文章时给小朋友或者中文初学者看的 那么怎样给整篇文章每个字批量添加拼音标注呢 下面小编就来教一下大家 由于对word宏命令不太熟悉 我将个任务分解为三部分
  • 使用Opencv+Python的AR小demo

    摘要 浅浅了解一下 Python OpenCV 试着给自己的 iphone 8 做一下相机标定 github 源码 https github com aeeeeeep OpenCvArDemo 定义 增强现实 AR 是一种真实世界环境的交互
  • java 读取svg_Java Batik操作SVG,实现svg读取,生成,动态操作

    SVG在现在的应用场景中还是很常见的 例如绘制复杂的矢量图形 说到SVG 就不得提下Canvas 在这里我就不详细列举它们之间的不同之处 以及为什么要选择SVG或Canvas了 首先 我的项目是一个Maven项目 所以只需要导入batik的
  • Vuex的简单使用--累加器

    简介 Vuex 是一个专为 Vue js 应用程序开发的 状态管理模式 它采用集中式存储管理应用的所有组件的状态 并以相应的规则保证状态以一种可预测的方式发生变化 安装 在项目根目录执行如下命令来安装 Vuex依赖包 npm install
  • Windows10通过局域网共享文件的方法

    要实现局域网共享 必须两台电脑必须在同一个网段 就是要同时连接同一个路由器 两台电脑最好都使用以下设置 在主电脑和需要复制文件的电脑中 点击 开始 菜单 选择 设置 打开后点击 网络 选择共享中心 在主电脑中需要共享的文件夹中做以下设置 要
  • ROS STAGE教程2(地图定义和GMAPPING建图)

    目前用在ROS Kinetic上的stage版本为4 1 官方教程http rtv github io Stage modules html 用户可以用stage或者gazebo来创建地图和机器人 传感器模型来进行仿真 并与自己的SLAM模
  • 在运行hive时报错 权限问题

    在运行hive时报错 tmp hive on HDFS should be writable Current permissions are rwx 这是 tmp hive文件夹权限不够 须要提升权限 操作例如以下命令就可以解决这个问题 h
  • R语言如何导入数据

    在使用R的时候 我们肯定需要导入数据 现在总结一下如何导入不同类型的数据 1 使用键盘输入数据 在导入数据比较少的时候 我们使用这种方法 R中的函数 edit 会自动调用一个允许手动输入数据的文本编辑器 具体步骤如下 1 创建一个空数据框
  • python基础(第六章)文件读写+算法

    文件读写 1 文件 1 Python2 File Python3 TextIOWrapper 2 一定要有file文件路径 路径 文件名 文件格式 否则 TypeError Required argument file pos 1 not
  • 记录基于STM32的独轮车测试板构建(一)电机篇

    今年是学校第一次参加智能车竞赛 毫无传承下想要脱颖而出那必定得先发制人 预选的是独轮车组 得用完全陌生的英飞凌单片机搞全新的独轮车模 难度不小 前些天看了看龙邱的库 在配套的母版上确实很简单好用 但独轮车母版和配套工程还不知道啥时候才有 如
  • 流水线合成材料依赖表的生成算法

    前不久玩了一个烧脑的游戏 异星工厂 就是开局一农民 然后通过建造自动化的流水线 最后合成宇宙飞船飞回故乡的故事 其中自动化的流水线需要玩家自己规划 比如这样的 下面的这个是游戏中的一个物品 电力机械臂 的合成配方 可以看到 这里合成一个 电
  • 配置网卡和修改ip地址

    修改ip地址有两种方法 1 临时修改 执行命令 ifconfig eth0 需要修改的ip地址 重新启动网络 systemctl restart network 2 永久修改 vim etc sysconfig network script
  • Java使用IO流读取TXT文件

    通过BufferedReader读取TXT文件 window系统默认的编码是GBK 而IDE的编码多数为UTF 8 如果没有规定new InputStreamReader new FileInputStream file GBK 为GBK会
  • 创建型模式之简单工厂模式——接口和抽象类

    本文收录于专栏 源码中的设计模式 理论与实战的完美结合 作者其它优质专栏推荐 技术专家修炼 搞技术 进大厂 聊人生三合一专栏 leetcode 300题 每天一道算法题 进大厂必备 糊涂算法 从今天起 迈过数据结构和算法这道坎 从实战学py
  • Visual Studio Community2019的安装过程

    Visual Studio Community2019的安装过程 一 下载安装包 浏览器搜索 visual studio community 选择一个合适的版本或者搜索网址 https visualstudio microsoft com
  • Chisel 手册(中文part1)

    Chisel 手册 part1 作者 Jonathan Bachrach Huy Vo Krste Asanovi EECS Department UC Berkeley 译者 智能物联 CSDN 1 简介 本文为Chisel手册 Cons