Scala&Chisel学习笔记

Scala&Chisel学习笔记

注:本人学习Chisel和Scala的笔记

材料主要来源:https://github.com/freechipsproject/chisel-bootcamp

欢迎留言讨论


  1. Interpolated string

    println(s”wordwordword$var”)

    printf(p”$io”)

    s”wordwordword${max + max}”

  2. seq操作

    1
    2
    3
    4
    5
    6
    7
    val seq = Seq("a", 1, 0.0)

    seq.foreach { x => {

    ...}

    }
  1. map操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    val intList = List(1, 2, 3)
    val stringList = intList.map { i =>
    i.toString
    }//或者写成.map {_.tostring} _代表下标

    val map = Map("a" -> 1)

    map.get("a") //= Some(1)
    map.get("b") //= None
    map("a") // = 1
    map("b") //报错
    //Some和None都是抽象类Option的子类
    Option
  2. Option的方法

    • get方法,对None执行get会报错
    • getOrElse(default)方法,找不到时返回default
    • isDefined,对Some返回真,对None返回假

    Option[UInt] = None常用于可选参数,比如optionResetValue

    1
    2
    3
    4
    val reg = resetValue match {
    case Some(r) => RegInit(r)
    case None => Reg(UInt())
    }
  3. reduce操作

    list.reduce(\_+\_)

    list.fold(initial)(\_+\_)带初值的reduce

    list.scan(initial)(_prev+_next)把reduce的每一步生成列表

    也有reduceRight等等

  4. Vec使用

    优先推荐Seq或List,除非以下情形:

    • Bundle的集合
    • 访问Vec的索引i和电路有关

    两个Vec对应元素的操作

    (vec_a zip vec_b).map {case (a, b) => a * b}

    list.zipWithIndex:List((‘a’, 0), (‘b’, 1), …)

    Vec初始化0

    RegInit( Vec(32, UInt(32.W)).fromBits(0.U) )

  5. class

    class Passthrough(param1 : Int, param2) extends Module {

    }

  6. tester代码模版

    1
    2
    3
    4
    5
    6
    7
    8
    9
    class MyOperatorsTester(c: MyOperators) extends PeekPokeTester(c) {
    expect(c.io.out_add, 5)
    expect(c.io.out_sub, 1)
    expect(c.io.out_mul, 8)
    //using peek if you don't want to compare out signal
    }
    val testResult = Driver(() => new MyOperators) {c => new MyOperatorsTester(c)}
    assert(testResult)
    println("SUCCESS!!")
  7. 查看firrtl

    println(getVerilog(new Passthough))

    println(getFirrtl(new Passthrough))

  8. print的几种出现场合

  • println(s”${io.in}”)在电路中:出现在generation的环节,即编译器Design Elaborating时,可以知道io.in是chisel3.core.UInt@e
  • printf(p”$io”)在电路中,出现在simulation环节,显示Bundle(in->3, out->3)
  • printf()在testbench中,显示[info] blabla
  1. Arbiter的逻辑

    FIFO的输入,一分为二输出

    1
    2
    pe0_valid := fifo_valid & pe0_ready
    pe1_valid := fifo_valid & pe1_ready & (~pe0_ready)`
  2. list

    列表的值一旦被定义,就不能被改变

    var site: List[Int] = List(1, 2, 3, 4) //=1 :: (2 :: (3 :: (4 :: Nil)))

    连接列表listcat = List.concat(l1, l2) //l1 ::: l2

    list.fill(3)("abc")

    list.tabulate(6)(n => n * n)通过给定的函数创建列表

    List(1, 2, 3, 4).permutations.foreach { case i0 :: i1 :: i2 :: i3 :: Nil => ... }实现四个数的全排列

    list.filter(s => s.length == 3)输出指定条件的所有元素

    list.foreach(s => s)将函数应用到列表的所有元素

常用的函数式语法:map, zip, reduce, fold, scan

  1. 状态机

    val idle :: coding :: writing :: grad :: Nil = Enum(4)

  2. RegNext(next: T, init: T)用法

    生成一个隐式的reg用于储存括号内的数,在下一拍生效

  3. 在写时序的时候注意一个状态的分步写,很可能被认为是重复赋值,只取最后一次赋值!

  4. 多时钟/reset

    1
    2
    3
    4
    5
    6
    7
    import chisel3.experimental.{withClock, withReset, withClockAndReset}

    withClock(io.alternateClock) {
    val altClk = RegInit(0.U(10.W))
    altClk := io.in
    io.outAlternateClock := altClk
    }
  5. 参数检查:在Elaboration前

    1
    2
    3
    4
    class className(Param1: Int) extends Module {
    require(Param1 >= 0)
    val io = blabla
    }
  6. Match/Case语句

    用处:

    • switch case
    1
    2
    3
    4
    5
    6
    7
    val x = y match {
    case 0 => "zero"
    case 1 => {
    "one"
    }
    case _ => "many"
    }
    • type matching

      1
      2
      3
      4
      x match {
      case _: String => blabla
      case _: Int => blabla
      }
  7. 可选硬件IO条目

    val carryIn = if (hasCarry) Some(Input(UInt(1.W))) else None

    或者这样写(访问0位宽的变量总得到0):

    val carryIn = Input(if (hasCarry) UInt(1.W) else UInt(0.W))

  8. 隐式参数

    个人感觉没大用处。。

    具体写法详见bootcamp.3.1_parameters.ipynb

    事先声明一个隐变量。一个类型只能指定一个隐变量的值

    在定义函数时加隐式参数声明

    在调用函数时可以不写隐参数(也可以写),让编译器自己去找该类型对应的隐变量的声明的值。

    提到的一个用处:做日志显示的开关

  9. 函数也可以做参数/变量

    在自动机的例子中,转换表成为自动机的参数,这样写:stateTransition: (Int, Int) => Int

    电路实现时,使用函数stateTransition(i, j)得到Int值

    调用电路时,定义函数stateTransition

  10. 闭包与匿名函数

    1
    2
    var factor = 3
    val multiplier = (i:Int) => i * factor

    生成的multipiler是一个函数,multiplier(x) = 3x

  11. Trait特征

    类似于Java的抽象类,可以被多重继承

    构造顺序:

    • 超类的构造
    • 特征从左到右构造
      • 先构造父特征、父特征不会被重复构造
    • 构造子类
  12. Decoupled

    Decoupled(任何对象)成为DecoupledIO Bundle

    增加valid: Output(Bool), ready: Input(Bool), bits: Output(任何对象)

  13. Queue:即FIFO,注意FIFO是时序逻辑

    val io.out = Decoupled(UInt(8.W))

    val io.in = Flipped(Decoupled(UInt(8.W)))Flipped对调输入输出

    val queue = Queue(io.in, 2)

    io.out <> queue

    保证io.in和io.out都是DecoupledIO

  14. Arbiters:把n个DecoupledIO送入1个DecoupledIO

    分为Arbiter: 优先考虑低索引的生产者,和RRArbiter:Round-robin挑选

    这是纯组合逻辑

    1
    2
    3
    4
    5
    6
    7
    val io = IO(new Bundle {
    val in = Flipped(Vec(2, Decoupled(UInt(8.W))))
    val out = Decoupled(UInt(8.W))
    })
    val arbiter = Module(new Arbiter(UInt(8.W), 2)) // 2 to 1 Priority Arbiter
    arbiter.io.in <> io.in
    io.out <> arbiter.io.out

    Arbiter.io(i).ready恒为0

  15. 内置Utility函数

    • PopCount(sth)
    • Reverse(sth)
    • Integer.parseInt(“00000000”, 2)转为2进制
    • io.out.toInt.toBinaryString
    • UInt和OneHot相互转化:UIntToOH(), OHToUInt()
  16. Muxes

    Priority Mux:PriorityMux低索引的优先(List[Bool, Data])

    OneHot Mux:Mux1H必须保证输入是OneHot的

    Mux也可以接收Vec型的条件和输入,达到多选的效果

  17. Counter

    val counter = Counter(3)Range是[0..2]

    conunter.inc()

    counter.value

  18. def和val生成的函数的区别

    val x = Random.nextInt不会重复执行(成为值)

    def y = Random.nextInt会生成新的随机值(类似指针指向该函数)

  19. 11/08/18这天看完了3.4_functional_programming.ipynb

---以上---