主体内容摘自:https://blog.csdn.net/qq_34291505/article/details/87905379
函数是编程语言的常用语法,即使是Verilog这样的硬件描述语言,也会用函数来构建组合逻辑。对于Chisel这样的高级语言,函数的使用更加方便,还能节省不少代码量。不管是用户自己写的函数、Chisel语言库里的函数还是Scala标准库里的函数,都能帮助用户节省构建电路的时间。
零、scala函数基础 1、普通函数// No inputs or outputs (two versions).
def hello1(): Unit = print("Hello!")
def hello2 = print("Hello again!")
// Math operation: one input and one output.
def times2(x: Int): Int = 2 * x
// Inputs can have default values, and explicitly specifying the return type is optional.
// Note that we recommend specifying the return types to avoid surprises/bugs.
def timesN(x: Int, n: Int = 2) = n * x
// Call the functions listed above.
hello1()
hello2
times2(4)
timesN(4) // no need to specify n to use the default value
timesN(4, 3) // argument order is the same as the order where the function was defined
timesN(n=7, x=2) // arguments may be reordered and assigned to explicitly
Hello!Hello again! defined function hello1 defined function hello2 defined function times2 defined function timesN res2_6: Int = 8 res2_7: Int = 8 res2_8: Int = 12 res2_9: Int = 14
2、函数字面量Scala中的函数是一等对象。这意味着我们可以将一个函数分配给一个Val,并将它作为参数传递给类、对象或其他函数。
// These are normal functions.
def plus1funct(x: Int): Int = x + 1
def times2funct(x: Int): Int = x * 2
// These are functions as vals.
// The first one explicitly specifies the return type.
val plus1val: Int => Int = x => x + 1
val times2val = (x: Int) => x * 2
// Calling both looks the same.
plus1funct(4)
plus1val(4)
plus1funct(x=4)
//plus1val(x=4) // this doesn't work
defined function plus1funct defined function times2funct plus1val: Int => Int = ammonite. s e s s . c m d 3 sess.cmd3 sess.cmd3HelperKaTeX parse error: Can't use function '$' in math mode at position 7: Lambda$̲3224/925602942@…Lambda$3225/1395281840@1c22db5a res3_4: Int = 5 res3_5: Int = 5 res3_6: Int = 5
为什么要创建一个Val而不是def?因为使用Val,可以将该函数传递给其他函数,如下所示。您甚至可以创建接受其他函数作为参数的自己的函数。形式上,接受或产生函数的函数称为高阶函数。
3、高阶函数// create our function
val plus1 = (x: Int) => x + 1
val times2 = (x: Int) => x * 2
// pass it to map, a list function
val myList = List(1, 2, 5, 9)
val myListPlus = myList.map(plus1)
val myListTimes = myList.map(times2)
// create a custom function, which performs an operation on X N times using recursion
def opN(x: Int, n: Int, op: Int => Int): Int = {
if (n Int = ammonite.
s
e
s
s
.
c
m
d
4
sess.cmd4
sess.cmd4HelperKaTeX parse error: Can't use function '$' in math mode at position 7: Lambda$̲3249/997984377@…Lambda$3250/1596149926@bf801a7 myList: List[Int] = List(1, 2, 5, 9) myListPlus: List[Int] = List(2, 3, 6, 10) myListTimes: List[Int] = List(2, 4, 10, 18) defined function opN res4_6: Int = 10 res4_7: Int = 56
当使用没有参数的函数时,1/2两种情况可能会出现混淆的情况。如下所示:
import scala.util.Random
// both x and y call the nextInt function, but x is evaluated immediately and y is a function
val x = Random.nextInt
def y = Random.nextInt
// x was previously evaluated, so it is a constant
println(s"x = $x")
println(s"x = $x")
// y is a function and gets reevaluated at each call, thus these produce different results
println(s"y = $y")
println(s"y = $y")
x = 1775160696 x = 1775160696 y = 804455125 y = 958584765
可以看到,x其实就是一个常量,是调用Random.nextInt
返回的一个常量;而y是你定义的一个函数,该函数的函数体就是执行Random.nextInt
这个函数,所以每次调用y都会执行Random.nextInt
,也就会出现不一样的结果。
4、匿名函数
顾名思义,匿名函数是匿名的。如果我们只使用它一次,就没有必要为函数创建Val。
val myList = List(5, 6, 7, 8)
// add one to every item in the list using an anonymous function
// arguments get passed to the underscore variable
// these all do the same thing
myList.map( (x:Int) => x + 1 )
myList.map(_ + 1)
// a common situation is to use case statements within an anonymous function
val myAnyList = List(1, 2, "3", 4L, myList)
myAnyList.map {
case (_:Int|_:Long) => "Number"
case _:String => "String"
case _ => "error"
}
myList: List[Int] = List(5, 6, 7, 8) res6_1: List[Int] = List(6, 7, 8, 9) res6_2: List[Int] = List(6, 7, 8, 9) myAnyList: List[Any] = List(1, 2, “3”, 4L, List(5, 6, 7, 8)) res6_4: List[String] = List(“Number”, “Number”, “String”, “Number”, “error”)
一、用自定义函数抽象组合逻辑
与Verilog一样,对于频繁使用的组合逻辑电路,可以定义成Scala的函数形式,然后通过函数调用的方式来使用它。这些函数既可以定义在某个单例对象里,供多个模块重复使用,也可以直接定义在电路模块里。例如:
// function.scala
import chisel3._
class UseFunc extends Module {
val io = IO(new Bundle {
val in = Input(UInt(4.W))
val out1 = Output(Bool())
val out2 = Output(Bool())
})
def clb(a: UInt, b: UInt, c: UInt, d: UInt): UInt =
(a & b) | (~c & d)
io.out1 := clb(io.in(0), io.in(1), io.in(2), io.in(3))
io.out2 := clb(io.in(0), io.in(2), io.in(3), io.in(1))
}
二、用工厂方法简化模块的例化
在Scala里,往往在类的伴生对象里定义一个工厂方法,来简化类的实例化。同样,Chisel的模块也是Scala的类,也可以在其伴生对象里定义工厂方法来简化例化、连线模块。例如用双输入多路选择器构建四输入多路选择器:
// mux4.scala
import chisel3._
class Mux2 extends Module {
val io = IO(new Bundle {
val sel = Input(UInt(1.W))
val in0 = Input(UInt(1.W))
val in1 = Input(UInt(1.W))
val out = Output(UInt(1.W))
})
io.out := (io.sel & io.in1) | (~io.sel & io.in0)
}
object Mux2 {
def apply(sel: UInt, in0: UInt, in1: UInt) = {
val m = Module(new Mux2)
m.io.in0 := in0
m.io.in1 := in1
m.io.sel := sel
m.io.out
}
}
class Mux4 extends Module {
val io = IO(new Bundle {
val sel = Input(UInt(2.W))
val in0 = Input(UInt(1.W))
val in1 = Input(UInt(1.W))
val in2 = Input(UInt(1.W))
val in3 = Input(UInt(1.W))
val out = Output(UInt(1.W))
})
io.out := Mux2(io.sel(1),
Mux2(io.sel(0), io.in0, io.in1),
Mux2(io.sel(0), io.in2, io.in3))
}
注:
其实就是把例化模块和端口连接的代码放入了伴生对象的apply方法里,这样可以被重复使用。当然也可以只定义一个普通函数,不使用伴生对象。函数的输入输出其实就是待使用的模块的输入输出。
三、用Scala的函数简化代码
Scala的函数也能在Chisel里使用,只要能通过Firrtl编译器的检查。比如在生成长的序列上,利用Scala的函数就能减少大量的代码。
假设要构建一个译码器:
- 在Verilog里需要写多条case语句,当n很大时就会使代码显得冗长而枯燥。
- 利用Scala的for、yield组合可以产生相应的判断条件与输出结果的序列,再用zip函数将两个序列组成一个对偶序列,再把对偶序列作为MuxCase的参数,就能用几行代码构造出任意位数的译码器。例如:
// decoder.scala
package decoder
import chisel3._
import chisel3.util._
import chisel3.experimental._
class Decoder(n: Int) extends RawModule {
val io = IO(new Bundle {
val sel = Input(UInt(n.W))
val out = Output(UInt((1
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?