• Chisel 学习笔记(七)


    Chisel 学习笔记(七)

    集合

    在Chisel中,我们既可以使用Scala中自带的集合,包括List,Seq,ArrayBuffer——List的使用方式在学习笔记(一)中有所体现;Seq与List类似,但是在Chisel中,我们更常使用Seq来表述某个模块的参数;ArrayBuffer的特性是不用描述出长度,且通过+就可以简单的添加元素(-可以删除元素),较为方便——也可以使用Chisel中所有的特殊集合Vec,Vec与其他Scala中的集合功能类似,但是可以更贴合Chisel。

    List,Seq,ArrayBuffer

    正如上文所说

    1. List是最原初的列表类,当然也有各种操作,不过较为繁琐
    2. Seq经常作为Chisel中构造函数的参数
    3. ArrayBuffer有着更简便的对集合的操作

    List&Seq

    class ScalaFirFilter(taps: Seq[Int]) {
      var pseudoRegisters = List.fill(taps.length)(0)		//构造一个taps.length长度的数组,将初始设为0
    
      def poke(value: Int): Int = {
        pseudoRegisters = value :: pseudoRegisters.take(taps.length - 1)	//取出pseudoRegister中前taps.length-1个元素,并在列表头插入value的值
        var accumulator = 0
        for(i <- taps.indices) {
          accumulator += taps(i) * pseudoRegisters(i)	//对Seq和List中元素的访问方式一样
        }
        accumulator
      }
    }
    

    Seq&ArrayBuffer

    在Chisel中,更常用的是通过Seq传参

    class MyManyElementFir(consts: Seq[Int], bitWidth: Int) extends Module {	//参数为一个不定长的Seq集合
      val io = IO(new Bundle {
        val in = Input(UInt(bitWidth.W))
        val out = Output(UInt(bitWidth.W))
      })
    
      val regs = mutable.ArrayBuffer[UInt]()	//ArrayBuffer的使用,先初始化成空
      for(i <- 0 until consts.length) {
          if(i == 0) regs += io.in							//通过加法可以很方便地添加元素到ArrayBuffer末尾
          else       regs += RegNext(regs(i - 1), 0.U)
      }
      
      val muls = mutable.ArrayBuffer[UInt]()
      for(i <- 0 until consts.length) {
          muls += regs(i) * consts(i).U
      }
    
      val scan = mutable.ArrayBuffer[UInt]()
      for(i <- 0 until consts.length) {
          if(i == 0) scan += muls(i)
          else scan += muls(i) + scan(i - 1)		//对元素的访问与Seq,List一样
      }
    
      io.out := scan.last
    }
    

    Chisel的特性——Vec

    Vec也是集合,且是为Chisel专门打造的。在某些情况下,scala中的集合并不支持Chisel的操作,主要是以下两种情况:

    1. 在Bundle中,特别是IO Bundle中,scala中的集合不再起作用
    2. 在某些需要用到Chisel特性进行访问或更改的操作中,例如处理器的寄存器堆设计,scala中的集合不再起作用

    Vec的使用如下

    class MyManyDynamicElementVecFir(length: Int) extends Module {
     val io = IO(new Bundle {
       val in = Input(UInt(8.W))
       val out = Output(UInt(8.W))
       val consts = Input(Vec(length, UInt(8.W)))
     })
    
     val regs = RegInit(Vec.fill(length - 1)(0.U(8.W)))	//对Vec的初始化和List操作类似,说明长度和初始值
    //val regs = RegInit(VecInit(Seq.fill(length - 1)(0.U(8.W))))    最新一版中的Vec初始化要这样写
     for(i <- 0 until length - 1) {
         if(i == 0) regs(i) := io.in									//对Vec中元素的访问也和List一样
         else       regs(i) := regs(i - 1)
     }
     
     val muls = Wire(Vec(length, UInt(8.W)))		//对一组导线的定义
     for(i <- 0 until length) {
         if(i == 0) muls(i) := io.in * io.consts(i)
         else       muls(i) := regs(i - 1) * io.consts(i)
     }
    
     val scan = Wire(Vec(length, UInt(8.W)))
     for(i <- 0 until length) {
         if(i == 0) scan(i) := muls(i)
         else scan(i) := muls(i) + scan(i - 1)
     }
    
     io.out := scan(length - 1)
    }
    

    RISC-V中寄存器堆的实现

    package Passthrough
    
    import chisel3._
    
    class RegisterFile (readPorts: Int) extends Module{
     val io = IO(new Bundle{
       val wen = Input(Bool())
       val waddr = Input(UInt(5.W))
       val wdata = Input(UInt(32.W))
       val raddr = Input(Vec(readPorts, UInt(5.W)))
       val rdata = Output(Vec(readPorts, UInt(32.W)))
     })
    
    //  val regs = RegInit(Vec(32, UInt(32.W)).fromBits(0.U)) 另外一种初始化方法
     val regs = RegInit(VecInit(Seq.fill(32)(0.U(32.W))))
    
     when(io.wen & io.waddr=/=0.U){
       regs(io.waddr) := io.wdata
     }
    
     for(i<-0 until readPorts){
       io.rdata(i) := regs(io.raddr(i))
     }
    
    }
    
  • 相关阅读:
    jquery-validate v1.19.2 源码分析
    jquery之遍历-Section04
    jquery之元素-Section03
    jquery之效果-Section02
    jquery之入门-Section01
    CSS世界(七)思维导图
    shell文件处理awk
    jquery插件懒加载
    jquery插件改变背景色
    jquery多库共存
  • 原文地址:https://www.cnblogs.com/JamesDYX/p/10082385.html
Copyright © 2020-2023  润新知