【问题标题】:Chisel code transformation凿码改造
【发布时间】:2023-03-08 13:29:01
【问题描述】:

所以,我有一个关于 Chisel 代码转换的理论问题。

我知道 Chisel 实际上是一组 Scala 定义,所以它被编译成 Java 字节码,然后在 JVM 中运行,就像魔术一样,它会吐出 Verilog 等效描述,甚至是旧版本的 C++ 描述凿子。

关键是我无法弄清楚这种“魔法”是如何运作的。我的猜测是,从 Chisel 到 Verilog/C++ 的代码转换都是基于 Scala 反射的。但我不确定,因为我找不到与此主题相关的任何内容。

那么,是关于反射吗?如果是这样,它是编译时我们的运行时反射吗? 有人可以给我一个线索吗?

非常感谢。

【问题讨论】:

    标签: chisel


    【解决方案1】:

    从根本上说,编写 Chisel 就是编写一个 Scala 程序来生成一个电路。你所描述的听起来有点像与 Chisel 完全不同的高级合成。 Chisel 不是将 Scala(或 Java)原语映射到硬件,而是执行 Scala 代码来构造 hardware AST,然后将其编译为 Verilog。

    我将尝试通过一个带注释的示例来说明这一点。

    // The body of a Scala class is the default constructor
    // MyModule's default constructor has a single Int argument
    // Superclass Module is a chisel3 Class that begins construction of a hardware module
    // Implicit clock and reset inputs are added by the Module constructor
    class MyModule(width: Int) extends Module {
      // io is a required field for subclasses of Module
      // new Bundle creates an instance of an anonymous subclass of Chisel's Bundle (like a struct)
      // When executing the function IO(...), Chisel adds ports to the Module based on the Bundle object
      val io = IO(new Bundle {
        val in = Input(UInt(width.W)) // Input port with width defined by parameter
        val out = Output(UInt()) // Output port with width inferred by Chisel
      }) 
    
      // A Scala println that will print at elaboration time each time this Module is instantiated
      // This does NOT create a node in the Module AST
      println(s"Constructing MyModule with width $width")
    
      // Adds a register declaration node to the Module AST
      // This counter register resets to the value of input port io.in
      // The implicit clock and reset inputs feed into this node
      val counter = RegInit(io.in)
    
      // Adds an addition node to the hardware AST with operands counter and 1
      val inc = counter + 1.U // + is overloaded, this is actually a Chisel function call
    
      // Connects the output of the addition node to the "next" value of counter
      counter := inc
    
      // Adds a printf node to the Module AST that will print at simulation time
      // The value of counter feeds into this node
      printf("counter = %d\n", counter) 
    }
    

    【讨论】:

    • 但是 Chisel 会检查自己以生成 FIRRTL 吗?当您编译并运行您给出的示例时,Chisel 中的硬件描述如何解释自己并导出 firrtl?我只能认为它适用于反射。
    • 我会尽量说得更具体些。当您用 Chisel 编写时,Scala 描述本身是否会导出 firrtl?或者是否有另一个外部工具可以扫描 Chisel 源代码并将其转换为 firrtl?不管怎样,谢谢你的回答。
    • 导出Firrtl的是Scala描述本身。这不是真的反射;像 UInt:= 这样的 Chisel 函数调用实际上会改变由 Chisel 在给定模块内构造的 AST。 Chisel 从顶层模块开始遍历这个 AST,以发出 Firrtl。我们确实实际上使用反射,但仅用于命名线路和寄存器,而不用于构造 AST。
    【解决方案2】:

    这也是我感兴趣的问题。我认为“构建硬件AST”被编程编译为*.class。生成类时,如 firrtl.执行完这些类后,就会生成 rtl,感觉就像嵌入了一个工具链。但我不知道怎么做。希望大家多多介绍。

    【讨论】:

      【解决方案3】:

      Chisel 与“代码转换”或“代码反射”无关。 Chisel 本身就是一个RTL。 Verilog、vhdl 和 firrtl 是描述 RTL 的不同类型的语言。 RTL 表示注册传输级别。任何直接描述寄存器操作的语言都可以归类为 RTL。

      在 Chisel 中,寄存器被定义为 Reg,线被定义为 Wires,程序员直接操作这些寄存器和线,就像在 verilog 中一样。所以难怪chisel为什么可以直接解释成verilog rtl。

      chisel 比 verilog 做得更好的是 外交模式设计,这意味着,与其声明电路的每个细节,如位宽或寄存器延迟,chisel 会自动执行此操作,它可以自动推断接口连接,从而“生成”您想要的电路。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-02-26
        相关资源
        最近更新 更多