您当前的位置: 首页 > 

耐心的小黑

暂无认证

  • 1浏览

    0关注

    323博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

chisel打印函数(printf/println)使用详解(更新)

耐心的小黑 发布时间:2021-06-25 14:43:09 ,浏览量:1

主体内容摘自:https://blog.csdn.net/qq_34291505/article/details/87905379

一、chisel的printf 基本介绍

Chisel提供了一个“ printf ”函数来打印信息,用于电路调试。它有Scala和C两种风格。如果在when语句块里,只有条件成立时才运行。隐式的全局复位信号有效时也不会触发。

printf函数会转换成Verilog的系统函数“$fwrite”,包含在宏定义块“ ifndef SYNTHESIS...... endif ”里。通过Verilog的宏定义,可以取消这部分不可综合的代码。

Ⅰ、Scala风格

该风格类似于Scala的字符串插值器。Chisel自定义了一个p插值器,该插值器可以对字符串内的一些自定义表达式进行求值、Chiel类型转化成字符串类型等。

①简单格式,Binary、Decimal、Hexadecimal、Character可以将Bits类型的数据转换成想要的格式,这在调试时很有用。

val myUInt = 33.U
// 显示Chisel自定义的类型的数据
printf(p"myUInt = $myUInt") // myUInt = 33 默认是十进制
//printf(p"myUInt = ${Decimal(myUInt)}") // myUInt = 33 
// 显示成十六进制
printf(p"myUInt = 0x${Hexadecimal(myUInt)}") // myUInt = 0x21
// 显示成二进制
printf(p"myUInt = ${Binary(myUInt)}") // myUInt = 100001
// 显示成字符(ASCⅡ码)
printf(p"myUInt = ${Character(myUInt)}") // myUInt = !

②聚合数据类型

val myVec = Vec(5.U, 10.U, 13.U)
printf(p"myVec = $myVec") // myVec = Vec(5, 10, 13)

val myBundle = Wire(new Bundle {
    val foo = UInt()
    val bar = UInt()
})
myBundle.foo := 3.U
myBundle.bar := 11.U
printf(p"myBundle = $myBundle") // myBundle = Bundle(a -> 3, b -> 11)

③自定义打印信息

对于自定义的Bundle类型,可以重写toPrintable方法来定制打印内容。当自定义的Bundle配合其他硬件类型例如Wire构成具体的硬件,并且被赋值后,可以用p插值器来求值该硬件,此时就会调用重写的toPrintable方法。例如:

class Message extends Bundle {
  val valid = Bool()
  val addr = UInt(32.W)
  val length = UInt(4.W)
  val data = UInt(64.W)
  override def toPrintable: Printable = {
      val char = Mux(valid, 'v'.U, '-'.U)
      p"Message:\n" +
      p"  valid  : ${Character(char)}\n" +
      p"  addr   : 0x${Hexadecimal(addr)}\n" +
      p"  length : $length\n" +
      p"  data   : 0x${Hexadecimal(data)}\n"
  }
}

val myMessage = Wire(new Message)
myMessage.valid := true.B
myMessage.addr := "h1234".U
myMessage.length := 10.U
myMessage.data := "hdeadbeef".U

printf(p"$myMessage")

注意,重写的toPrintable方法的返回类型固定是Printable,这是因为p插值器的返回类型就是Printable,并且Printable类里定义了一个方法“+”用于将多个字符串拼接起来。在最后一个语句里,p插值器会求值myMessage,这就会调用Message类的toPrintable方法。因此,最终的打印信息如下:

Message:
     valid  : v
     addr   : 0x00001234
     length : 10
     data   : 0x00000000deadbeef
Ⅱ、C风格

Chisel的printf也支持C的部分格式控制符和转义字符。如下所示: 在这里插入图片描述

val myUInt = 32.U
printf("myUInt = %d", myUInt) // myUInt = 32

注:

二、关于打印函数使用的一些细节 1、chisel的prinf、scala的printf和println都可以使用,但:
  • chisel的printf只能写在用户定义的Module中;并且必须要有时钟和复位,否则生成verilog报错,因此如果使用了RawModule,那么需要自定义时钟和复位域;
  • scala的printf和println既可以用在Module中,也可以用在主函数中,但是它们的运行时机不一样,下面会说;
  • 因为后导入的chisel3包覆盖了Scala的标准包,所以Scala里的printf函数要写成“Predef.printf”的完整路径形式;
2、打印函数运行的时机
  • chisel的printf写在Module中,只在运行测试的时候才有效,并且clk每走一次(也即step(1)),打印一次,必须要有step,否则printf不工作!!!因为从生成的verilog代码中就可以看出来,它是随clk和reset变化的。即使你其他的逻辑都是组合逻辑,生成的verilog代码中prinf对应的部分也是时序逻辑。如果只是运行的生成verilog的代码,它不会输出信息,最多只是会被转换成Verilog的系统函数“$fwrite”。
  • 写在主函数中的打印函数,只要运行主函数,就会输出信息。
  • scala的打印函数,如果写在Module里,那么只在Elaborating design阶段有效,并且无论是测试还是生成verilog时都可以,因为它们都有Elaborating design阶段。
3、举例说明
import chisel3._
import chisel3.util._
import chiseltest._
import chiseltest.RawTester.test

class PrintingModule extends Module {
    val io = IO(new Bundle {
        val in = Input(UInt(4.W))
        val out = Output(UInt(4.W))
    })
    io.out := io.in

    printf("Print during simulation: Input is %d\n", io.in)
    // chisel printf has its own string interpolator too
    printf(p"Print during simulation: IO is $io\n")

    println(s"Print during generation: Input is ${io.in}")
}


object PrintTester extends App {
    println("Start Testing")

    test(new PrintingModule ) { c =>
        c.io.in.poke(3.U)
        c.clock.step(5) // circuit will print
        
        println(s"Print during testing: Input is ${c.io.in.peek()}")
        }
}

wzx@No_3:/SSD/wzx/chisel-examples$ sbt “runMain simple.PrintTester” [info] welcome to sbt 1.4.7 (Ubuntu Java 11.0.11) [info] loading project definition from /SSD/wzx/chisel-examples/project [info] loading settings for project chisel-examples from build.sbt … [info] set current project to chisel-examples (in build file:/SSD/wzx/chisel-examples/) [info] compiling 1 Scala source to /SSD/wzx/chisel-examples/target/scala-2.12/classes … [warn] there were 6 feature warnings; re-run with -feature for details [warn] one warning found [info] running simple.PrintTester Start Testing Elaborating design… Print during generation: Input is UInt(IO in unelaborated PrintingModule) Done elaborating. Print during simulation: Input is 3 Print during simulation: IO is AnonymousBundle(in -> 3, out -> 3) Print during simulation: Input is 3 Print during simulation: IO is AnonymousBundle(in -> 3, out -> 3) Print during simulation: Input is 3 Print during simulation: IO is AnonymousBundle(in -> 3, out -> 3) Print during simulation: Input is 3 Print during simulation: IO is AnonymousBundle(in -> 3, out -> 3) Print during simulation: Input is 3 Print during simulation: IO is AnonymousBundle(in -> 3, out -> 3) Print during testing: Input is UInt(3) Print during simulation: Input is 0 Print during simulation: IO is AnonymousBundle(in -> 0, out -> 0) test PrintingModule Success: 0 tests passed in 7 cycles in 0.055612 seconds 125.87 Hz [success] Total time: 9 s, completed Jun 25, 2021, 2:31:23 PM

仔细分析打印结果,就可以发现实际的情况和上面的分析是一致的!!!

关注
打赏
1640088279
查看更多评论
立即登录/注册

微信扫码登录

0.0437s