备案域名购买阿里云/青岛设计优化公司

备案域名购买阿里云,青岛设计优化公司,郑州哪里有做网站的,桂林漓江景点介绍上一篇见此: chisel快速入门(一)_沧海一升的博客-CSDN博客简单介绍了chisel,使硬件开发者能快速上手chisel。https://blog.csdn.net/qq_21842097/article/details/121415341 十、运行和测试 现在我们已经定义了模块,…

        上一篇见此:

chisel快速入门(一)_沧海一升的博客-CSDN博客简单介绍了chisel,使硬件开发者能快速上手chisel。https://blog.csdn.net/qq_21842097/article/details/121415341

十、运行和测试

        现在我们已经定义了模块,我们将讨论如何实际运行并测试电路。Chisel代码可以转换为C++或Verilog。 为了编译电路,我们需要调用chiselMain:

object tutorial {def main(args: Array[String]) = {chiselMain(args, () => Module(new Mux2())) }	
}

        测试是电路设计的关键部分,因此在 Chisel 中,我们通过使用 Tester 类的子类在 Scala 中提供测试向量来提供一种测试电路的机制:

class Tester[T <: Module] (val c: T, val isTrace: Boolean = true) {var t: Intval rnd: Randomdef int(x: Boolean): BigInt def int(x: Int): BigIntdef int(x: Bits): BigInt def reset(n: Int = 1)def step(n: Int): Intdef pokeAt(data: Mem[T], index: Int, x: BigInt) def poke(data: Bits, x: BigInt)def poke(data: Aggregate, x: Array[BigInt])def peekAt(data: Mem[T], index: Int)def peek(data: Bits): BigIntdef peek(data: Aggregate): Array[BigInt]def expect (good: Boolean, msg: String): Boolean def expect (data: Bits, target: BigInt): Boolean
}

        它将tester绑定到模块,并允许用户使用给定的调试协议编写测试。用户会用到一下这些:

  • poke: 设置输入端口以及状态值
  • step: 以一个时间单元执行电路
  • peek: 读取端口和状态值
  • expect: 比较peek获得的值和期望的值

        用户使用如下的方式连接tester和模块:

object chiselMainTest { def apply[T <: Module](args: Array[String], comp: () => T)( tester: T => Tester[T]): T
}

        当- -test作为参数传递给chiselMainTest时,tester实例在独立的进程中运行被测器件(DUT),并连接stdin和stdout,这样调试命令可以发送到DUT,响应也可以从DUT接收,如图所示。

        举例说明:

class Mux2Tests(c: Mux2) extends Tester(c) { val n = pow(2, 3).toIntfor (s <- 0 until 2) {for (i0 <- 0 until 2) { for (i1 <- 0 until 2) {poke(c.io.sel, s)poke(c.io.in1, i1)poke(c.io.in0, i0)step(1)expect(c.io.out, (if (s == 1) i1 else i0))}}}
}

         使用poke将Mux2的每个输入的分别设置为合适的值。对于这个例子,我们通过硬编码输入到一些已知的值并检查输出是否对应于已知的值来测试Mux2。为此,在每次迭代中,我们生成模块输入,让模拟将这些值分配给我们正在测试的器件c的输入,单步运行电路并对比期望值。最后,简单说明一下如何调用测试器:

chiselMainTest(args + "--test", () => Module(new Mux2())){ c => new Mux2Tests(c)
}

还有其他的一些命令参数:

  • –targetDir 目标路径名前缀
  • –genHarness 生成C++文件
  • –backend v 生成verilog
  • –backend c 生成C++(默认)
  • –vcd 开启vcd打印
  • –debug 把所有的wire放入class文件

十一、状态元素

        Chisel支持的状态元素的最简单形式是上升沿触发寄存器,可以实例化为:

val reg = Reg(next = in)

        该电路具有输出,该输出是前一个时钟周期的输入信号产生的值。注意,我们不必指定Reg的类型,因为它会在实例化时从输入开始自动推断。在当前版本的Chisel中,时钟和复位是全局信号,在需要时可以隐式包含。

        使用寄存器,我们可以快速定义一些有用的电路结构。 例如,当当前值为true且之前的值为false时,上升沿检测器能够获取到布尔信号并输出true,如下所示:

def risingedge(x: Bool) = x && !Reg(next = x)

        计数器是一个重要的时序电路。 如果想构建一个向上计数器,计数到最大值max后回到零:

def counter(max: UInt) = {val x = Reg(init = UInt(0, max.getWidth))x := Mux(x === max, UInt(0), x + UInt(1))x
}

        计数器复位值为0(宽度大到足以容纳max),当电路的全局复位置位时,寄存器将初始化为该值。

        计数器可用于构建很多有用的时序电路。例如,我们可以通过在计数器达到零时输出true来构建脉冲发生器:

def pulse(n: UInt) = counter(n - UInt(1)) === UInt(0)

        然后可以通过切换方波发生器脉冲序列,在每个脉冲上的true和false之间切换: 

// Flip internal state when input true.
def toggle(p: Bool) = {val x = Reg(init = Bool(false)) x := Mux(p, !x, x)x
}
// Square wave of a given period.
def squareWave(period: UInt) = toggle(pulse(period/2))

1、转发声明

        纯组合电路在节点之间不存在周期,如果检测到这样的周期,则Chisel将报告错误。因为它们不具有周期,所以可以总是以前馈方式构建组合电路,通过添加一些输入从已经定义的节点导出的新节点。

        时序电路在节点之间具有反馈,因此有时需要在生成节点被定义之前输出。因为Scala顺序执行程序语句,所以我们允许数据节点作为wire来提供节点声明,这样可以立即被使用,但其输入将稍后设置。

        如下例所示,在简单的CPU中,我们需要定义pcPlus4和brTarget的线,以便在定义之前引用它们:

val pcPlus4 = UInt()
val brTarget = UInt()
val pcNext = Mux(io.ctrl.pcSel, brTarget, pcPlus4)
val pcReg = Reg(next = pcNext, init = UInt(0, 32)) 
pcPlus4 := pcReg + UInt(4)
...
brTarget := addOut

        接线操作符:=用于在pcReg和addOut定义后连接。

2、条件更新

        在前面使用到寄存器的示例中,我们简单地将组合逻辑块连接到寄存器的输入。当描述状态元素的操作时,指定何时将发生寄存器更新并且用几个单独的语句指明这些更新。

        Chisel以when的形式提供条件更新规则,以支持这种顺序逻辑描述的风格。例如,

val r = Reg(init = UInt(0, 16)) 
when (cond) {r := r + UInt(1) 
}

        其中只有在cond为真时,才在当前时钟周期的结尾更新寄存器r。when的参数是返回Bool值。后面的更新块只能包含使用赋值运算符:=,简单表达式和用val定义的命名引线的更新语句。

        在条件更新序列中,条件为真的最近条件更新优先。 例如:

when (c1) { r := UInt(1) } 
when (c2) { r := UInt(2) }

        上述表达式会根据以下真值表更新r:

        条件更新结构可以嵌套,任何给定块在所有外嵌套条件的联合下才能执行。

        条件可以使用when,.elsewhen,.otherwise来链式表达,对应于Scala中的if, else if, else。例如:

when (c1) { u1 } 
.elsewhen (c2) { u2 } 
.otherwise { ud }
// the same as
when (c1) { u1 }
when (!c1 && c2) { u2 } 
when (!(c1 || c2)) { ud }

        Chisel还允许Wire,即一些组合逻辑的输出,成为条件性更新语句的目标,以允许逐步构建复杂的组合逻辑表达式。Chisel不允许不指定组合输出,并且如果组合输出未遇到无条件更新,则报告错误。

3、有限状态机

        在数字设计中有限状态机(FSM)是时序电路常用的类型。简单FSM的例子就是奇偶校验生成器:

class Parity extends Module { val io = new Bundle {val in = Bool(dir = INPUT)val out = Bool(dir = OUTPUT) }val s_even :: s_odd :: Nil = Enum(UInt(), 2) val state = Reg(init = s_even)when (io.in) {when (state === s_even) { state := s_odd }when (state === s_odd) { state := s_even } }io.out := (state === s_odd)
}

        其中Enum(Uint(), 2)生成两个UInt数。当io.in为true时更新状态。需要注意的是,FSM的所有机制都建立在寄存器,线和条件更新的基础上。

        下面是一个复杂的FSM例子,这是一个自动售货机接收货币的电路:

class VendingMachine extends Module {val io = new Bundle {val nickel = Bool(dir = INPUT)val dime   = Bool(dir = INPUT)val valid  = Bool(dir = OUTPUT)}val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)val state = Reg(init = s_idle) when (state === s_idle) {when (io.nickel) { state := s_5 }when (io.dime) { state := s_10 } }when (state === s_5) {when (io.nickel) { state := s_10 } when (io.dime) { state := s_15 }}when (state === s_10) {when (io.nickel) { state := s_15 }when (io.dime) { state := s_ok } }when (state === s_15) {when (io.nickel) { state := s_ok } when (io.dime) { state := s_ok }}when (state === s_ok) {state := s_idle}io.valid := (state === s_ok) 
}

        采用switch风格代码如下:

class VendingMachine extends Module {val io = new Bundle {val nickle = Bool(dir = INPUT)val dime   = Bool(dir = INPUT)val valid  = Bool(dir = OUTPUT)}val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)val state = Reg(init = s_idle) switch (state) { is (s_idle) {when (io.nickel) { state := s_5 }when (io.dime) { state := s_10 } } is (s_5) {when (io.nickel) { state := s_10 } when (io.dime) { state := s_15 }}is (s_10) {when (io.nickel) { state := s_15 }when (io.dime) { state := s_ok } }is (s_ok) {state := s_idle}}io.valid := (state === s_ok)
}

十二、内存

        Chisel提供了创建只读和读/写存储器的功能。

1、ROM

        用户可以使用Vec定义ROM:

Vec(inits: Seq[T])
Vec(elt0: T, elts: T*)

        其中inits是初始化ROM的初始Data序列。例如,用户可以创建一个初始化为1,2,4,8的小型ROM,并使用计数器作为地址生成器循环访问所有值,如下所示:

val m = Vec(Array(UInt(1), UInt(2), UInt(4), UInt(8))) 
val r = m(counter(UInt(m.length)))

        我们可以使用如下初始化的ROM创建n值正弦查找表:

def sinTable (amp: Double, n: Int) = { val times = Range(0, n, 1).map(i => (i*2*Pi)/(n.toDouble-1) - Pi) val inits = times.map(t => SInt(round(amp * sin(t)), width = 32)) Vec(inits)
}
def sinWave (amp: Double, n: Int) =sinTable(amp, n)(counter(UInt(n))

        其中amp用于缩放存储在ROM中的固定点值。

2、Mem

        存储器在Chisel中被给予特殊处理,因为存储器的硬件实现具有许多变化,例如,FPGA存储器与ASIC存储实例化的结果完全不同。Chisel定义了一个内存抽象,可以映射到简单的Verilog行为描述,也可以映射到从代工厂或IP厂商提供的外部内存生成器获得的内存模块实例。

        Chisel通过Mem结构可以支持随机存取存储器。写入Mems是正边沿触发,读取是组合或正边沿触发。

object Mem {def apply[T <: Data](type: T, depth: Int,seqRead: Boolean = false): Mem
}
class Mem[T <: Data](type: T, depth: Int, seqRead: Boolean = false)extends Updateable { def apply(idx: UInt): T}

        通过使用UInt索引创建到Mems的端口。具有一个写入端口和两个组合读取端口的32-entry的寄存器堆可以如下表示:

val rf = Mem(UInt(width = 64), 32) 
when (wen) { rf(waddr) := wdata } 
val dout1 = rf(waddr1)
val dout2 = rf(waddr2)

        如果设置了可选参数seqRead,当读地址为Reg时,Chisel将尝试推断顺序读端口。

        单读端口,单写端口SRAM可以描述如下:

val ram1r1w = Mem(UInt(width = 32), 1024, seqRead = true)
val reg_raddr = Reg(UInt())
when (wen) { ram1r1w(waddr) := wdata } 
when (ren) { reg_raddr := raddr }
val rdata = ram1r1w(reg_raddr)

        单端口SRAM可以在读和写条件在链中相同时相互排斥时推断:

val ram1p = Mem(UInt(width = 32), 1024, seqRead = true) 
val reg_raddr = Reg(UInt())
when (wen) { ram1p(waddr) := wdata } 
.elsewhen (ren) { reg_raddr := raddr }
val rdata = ram1p(reg_raddr)

        如果相同的Mem地址在相同的时钟沿上被写入和顺序读取,或者如果顺序读取使能被清除,则读取数据为未定义。

十三、接口和批量连接

        对于更复杂的模块,在定义模块的 IO 时定义和实例化接口类通常很有用。

        首先,接口类促进重用,允许用户以有用的形式一次性捕获所有通用接口。 其次,接口允许用户通过模块之间的批量连接来显着减少布线。 最后,用户可以在一个地方对大型接口进行更改,从而减少添加或删除接口部分时所需的更新次数。

1、端口类、子类和嵌套

        正如我们之前看到的,用户可以通过定义一个继承 Bundle 的类来定义他们自己的接口。

         例如,可以为握手数据定义一个简单的链接,如下所示:

class SimpleLink extends Bundle {
val data = UInt(16, OUTPUT)
val valid = Bool(OUTPUT)
}

        然后我们可以通过使用包继承添加奇偶校验位来扩展 SimpleLink:

class PLink extends SimpleLink {
val parity = UInt(5, OUTPUT)
}

        通常,用户可以使用继承将他们的接口组织成层次结构。 从那里我们可以通过将两个 PLink 嵌套到一个新的 FilterIO 包中来定义过滤器接口:

class FilterIO extends Bundle {
val x = new PLink().flip
val y = new PLink()
}

        其中flip递归地改变Bundle的“相性”,将输入改变为输出和将输出改变为输入。

        我们现在可以通过定义一个过滤器类继承模块来定义一个过滤器:

class Filter extends Module {
val io = new FilterIO()
...
}

        其中io包含了FilterIO。

2、Bundle Vector

        除了单个元素之外,元素Vector可以组成更丰富的分层接口。 例如,为了创建一个带有输入向量的交叉开关,产生一个输出向量,并由 UInt 输入选择,我们使用 Vec 构造函数。

class CrossbarIo(n: Int) extends Bundle {val in = Vec.fill(n){ new PLink().flip() } val sel = UInt(INPUT, sizeof(n))val out = Vec.fill(n){ new PLink() }
}

        其中Vec用第一个参获取大小,区块返回一个端口作为第二个参数。

3、批量连接

        我们现在可以将两个过滤器组成一个过滤器块,如下所示:

class Block extends Module { val io = new FilterIO()val f1 = Module(new Filter()) val f2 = Module(new Filter())f1.io.x <> io.x f1.io.y <> f2.io.x f2.io.y <> io.y
}

        其中<>批量连接同级模块之间的相反接口或父/子模块之间的相同接口。批量连接将相同名称的端口彼此连接。在所有连接完成后,Chisel警告用户端口是否只有一个到它们的连接。

4、接口视图

        考虑一个由控制路径和数据路径子模块以及主机和内存接口组成的简单 CPU,如图。

        在这个 CPU 中,我们可以看到控制路径和数据路径各自只连接到一部分指令和数据内存接口。Chisel 允许用户通过部分实现接口来做到这一点。 用户首先定义完整的 ROM 和 Mem 接口如下:

class RomIo extends Bundle { val isVal = Bool(INPUT)val raddr = UInt(INPUT, 32) val rdata = UInt(OUTPUT, 32)
}
class RamIo extends RomIo { val isWr = Bool(INPUT)val wdata = UInt(INPUT, 32)
}

        现在控制逻辑可以根据这些接口构建接口:

class CpathIo extends Bundle { val imem = RomIo().flip() val dmem = 	RamIo().flip() 
}

        而且控制和数据通路模块可以通过部分地分配来给这个接口来构建,如下所示:

class Cpath extends Module { val io = new CpathIo();...io.imem.isVal := ...;io.dmem.isVal := ...; io.dmem.isWr := ...; ...
}
class Dpath extends Module { val io = new DpathIo(); ...io.imem.raddr := ...; io.dmem.raddr := ...; io.dmem.wdata := ...;...
}

        我们现在可以使用批量连接来连接CPU,就像使用其他bundle一样:

class Cpu extends Module {val io = new CpuIo()val c = Module(new CtlPath()) val d = Module(new DatPath()) c.io.ctl <> d.io.ctlc.io.dat <> d.io.dat c.io.imem <> io.imemd.io.imem <> io.imemc.io.dmem <> io.dmemd.io.dmem <> io.dmemd.io.host <> io.host
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/253547.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【WPF】设置TextBox内容为空时的提示文字

原文:【WPF】设置TextBox内容为空时的提示文字<TextBox Width"150" Margin"5"><TextBox.Resources><VisualBrush x:Key"HintText" TileMode"None" Opacity"0.5" Stretch"None" AlignmentX"Le…

读书笔记之《The Art of Readable Code》Part 2

如何写好流程控制语句(if-else/switch/while/for)使得代码更可读些&#xff1f;(chap 7)* 提高条件语句的可读性(if语句, 或者bool型summary变量) if (length > 10) // Good if (10 < length) // Badwhile (bytes_received < bytes_expected) // Good while (b…

chisel快速入门(三)

前一篇见此&#xff1a; chisel快速入门&#xff08;二&#xff09;_沧海一升的博客-CSDN博客简单介绍了chisel&#xff0c;使硬件开发者能快速上手chisel。https://blog.csdn.net/qq_21842097/article/details/121418806 十四、模块的功能创建 制造用于模块构造的功能接口也…

Redis作者摊上事了:多人要求修改Redis主从复制术语master/slave

作者 | ANTIREZ、小智近日&#xff0c;Redis 作者在 GitHub 上发起了一个“用其他词汇代替 Redis 的主从复制术语”的 issue。有人认为 Redis 中的术语 master/slave &#xff08;主人 / 奴隶&#xff09;冒犯到了别人&#xff0c;要求 Redis 作者 ANTIREZ 修改这个术语&#x…

CMOS图像传感器——2021产品选谈

据Yole统计,2020年全球CMOS图像传感器(CIS)市场规模为207亿美元,出货量为70.08亿颗。跟其它半导体器件一样,CIS也因为疫情和生产周期长,以及各种市场因素,而导致采购和供应链紧张。Yole预计2021年将趋于平稳,销售额相比2020年略有增长(3.2%),将达到214亿美元,出货量…

C++匿名对象

匿名对象&#xff1a; string("hello")就是匿名对象&#xff1b; 匿名对象当做参数引用时必须加const; 转载于:https://www.cnblogs.com/achao123456/p/9634810.html

MVC源码分析 - Action查找和过滤器的执行时机

接着上一篇, 在创建好Controller之后, 有一个 this.ExecuteCore()方法, 这部分是执行的. 那么里面具体做了些什么呢? //ControllerBaseprotected virtual void Execute(RequestContext requestContext) {if (requestContext null){throw new ArgumentNullException("req…

CCIE-MPLS基础篇-实验手册

又一部前期JUSTECH&#xff08;南京捷式泰&#xff09;工程师职业发展系列丛书完整拷贝。 MPLS&#xff08;Multi-Protocol Label Switching&#xff09; 目录 1&#xff1a;MPLS 基础实验.... 3 1.1实验拓扑... 3 1.2实验需求&#xff1a;... 3 1.3实验步骤... 3 1.4校验…

RCA/BNC接口

RCA接口&#xff08;消费类市场&#xff09; RCA 是Radio Corporation of American的缩写词&#xff0c;因为RCA接头由这家公司发明的。RCA俗称莲花插座&#xff0c;又叫AV端子&#xff0c;也称AV 接口&#xff0c;几乎所有的电视机、影碟机类产品都有这个接口。它并不是专门为…

2021手机CIS技术趋势总结

手机摄像头CIS&#xff08;CMOS图像传感器&#xff09;自从突破1亿像素以后&#xff0c;再谈像素数量增大&#xff0c;似乎已经很难让市场产生激烈反应了。这两年电子工程专辑对于手机摄像头CIS&#xff0c;以及更多领域不同类型的图像/视觉传感器&#xff08;如ToF、基于事件的…

关于Unity中NGUI的背包实现之Scrollview(基于Camera)

基于UIPanel的scrollview实现方式在移动设备上的性能不如基于camera的方式。因为UIPanel的scrollview实现方式要渲染很多的道具图&#xff0c;性能自然就降低了。如果是用第二个摄像机camera的方式&#xff0c;物体并没有动&#xff0c;只是拖动第二个摄像机摄像机&#xff0c;…

YUV422/420 format

(在本文中&#xff0c;U 一词相当于 Cb&#xff0c;V 一词相当于 Cr。) YUV422 format as shown below 4:2:2 表示 2:1 的水平取样&#xff0c;没有垂直下采样 YUV420 format as shown below4:2:0 表示 2:1 的水平取样&#xff0c;2:1 的垂直下采样. YUV4:2:0并不是说只有U&…

数字后端——ECO

目录 一、概述 二、ECO分类 1、按时间节点 1&#xff09;流片前的ECO 2&#xff09;流片过程的ECO 3&#xff09;流片后的ECO 2、按网表是否改变 1&#xff09;功能ECO 2&#xff09;时序ECO 三、ECO处理内容 1、设计规则违例 1&#xff09;提升标准单元驱动力 2…

电视百科常识 九大视频接口全接触

1 射频 天线和模拟闭路连接电视机就是采用射频&#xff08;RF&#xff09;接口。作为最常见的视频连接方式&#xff0c;它可同时传输模拟视频以及音频信号。RF接口传输的是视频和音频混合编码后的信号&#xff0c;显示设备的电路将混合编码信号进行一系列分离、解码在输出成像。…

数字后端——物理单元介绍

物理单元&#xff08; physical cell&#xff09;指没有逻辑功能但是具有物理实现功能的标准单元&#xff0c; 用于抑制芯片生产过程中的各类物理效应&#xff0c; 保证芯片生产后能够正常工作 。硬核位置确 定后&#xff0c;需要插入物理单元消除影响芯片工作的物 效应&#x…

深入Java内存模型

你可以在网上找到一大堆资料让你了解JMM是什么东西&#xff0c;但大多在你看完后仍然会有很多疑问。happen-before是怎么工作的呢&#xff1f;用volatile会导致缓存的丢弃吗&#xff1f;为什么我们从一开始就需要内存模型&#xff1f; 通过这篇文章&#xff0c;读者可以学习到足…

Matlab 使用GPU加速 转载

在matlab中使用GPU加速&#xff0c;来加速矩阵运算。 首先如前面所说&#xff0c;并不是所有GPU都能在maltab中进行加速的&#xff0c;貌似只有NVDIA的显卡可以吧。 硬件&#xff1a;GeForce GTX 980 软件&#xff1a;Matlab 2015a &#xff08;Matlab 2012以后的版本才带有GP…

数字后端——可制造性设计

随着集成电路制造工艺技术的迅速发展&#xff0c;集成电路集成度迅速攀升&#xff0c;制造流程及工艺步骤日趋复杂&#xff0c;工艺尺寸也在不断缩小。集成电路可制造性设计&#xff08;Design For Manufacturability,DFM&#xff09; 以直接提升集成电路芯片的良品率及降低芯片…

Cloudstack安装(二)

Cloudstack安装 官方文档参考&#xff1a; http://docs.cloudstack.apache.org/projects/cloudstack-installation/en/4.9/qig.html#environment Cloudstack主要分Management和Agent两部分。 系统版本&#xff1a;CentOS 6.8 Management&#xff1a; cpu1&#xff0c;ram 2048M…

Pycharm 输出中文或打印中文乱码现象的解决办法

转载地址&#xff1a;https://www.cnblogs.com/Bro-Young/p/5920884.html 1. 确保文件开头加上以下代码&#xff1a; 1 # -*- coding:utf-8 -*- 还可以加上 1 import sys 2 reload(sys) 3 sys.setdefaultencoding(utf-8) 确保以下。 如果还是没有解决中文乱码&#xff0c;那么进…