【问题标题】:How do I create a C/C++ preprocessor style macro in Chisel HDL?如何在 Chisel HDL 中创建 C/C++ 预处理器样式的宏?
【发布时间】:2023-03-13 08:23:01
【问题描述】:

我正在将 Verilog 项目重写为 Chisel HDL。该项目有几个解耦的子组件,例如(ex.vmem.vwb.v)和一个名为defines.v 的配置文件,即子组件中的`included。例如,

defines.v中的内容

`define RstEnable 1'b1
`define RstDisable 1'b0
`define ZeroWord 32'h00000000
`define WriteEnable 1'b1
`define WriteDisable 1'b0
`define ReadEnable 1'b1
`define ReadDisable 1'b0
... ...

ex.v中的内容

`include "defines.v"

module ex(
    input wire                    rst,
    input wire[`AluOpBus]         aluop_i,
    input wire[`AluSelBus]        alusel_i,
    input wire[`RegBus]           reg1_i,
    input wire[`RegBus]           reg2_i,
    ... ...
);

    always @ (*) begin
        if(rst == `RstEnable) begin
            logicout <= `ZeroWord;
        end else begin
            case (aluop_i);
                `EXE_OR_OP:         begin
                    logicout <= reg1_i | reg2_i;
                end
                `EXE_AND_OP:        begin
                    logicout <= reg1_i & reg2_i;
                end
                ... ...
                default:                begin
                    logicout <= `ZeroWord;
                end
            endcase
        end    //if
    end      //always

    ... ...

endmodule

我不熟悉 Scala,所以它新的 LISP 风格的宏系统有点过于强大,我无法完全理解。我想要的只是一个简单的 C/C++ 预处理器样式的宏,它可以进行文本替换。

我尝试过使用变量

package cpu

import chisel3._
import chisel3.util._


object Defines {
  val RstEnable = "b1".U(1.W)
  val RstDisable = "b0".U(1.W)
  ... ...
}

Scala 中使用的变量定义如下

class Ex extends Module {
  val io = IO(new Bundle {
    ... ...
    val aluop_i = Input(UInt(AluOpBus))
    ... ...
  })

  ... ...

  logicout := io.aluop_i match {
    case EXE_OR_OP => logicout
    case _ => 0.U
  }
}

这几乎可以工作,除了以下错误表明match 对变量不满意

[error] /Users/nalzok/Developer/DonkeyMIPS/chisel/src/main/scala/cpu/ex/Ex.scala:88:10: type mismatch;
[error]  found   : chisel3.UInt
[error]  required: Unit
[error]     case EXE_OR_OP => logicout
[error]          ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 3 s, completed Jun 14, 2020 9:42:13 AM

【问题讨论】:

    标签: scala macros verilog hdl chisel


    【解决方案1】:

    您看到的具体错误是您尝试在logicout := io.aluop_i 的返回上进行模式匹配。建立了硬件连接,这将返回 Unit,然后您尝试对其进行模式匹配。

    Chisel 没有将 Scala 条件/模式匹配转换为硬件结构。因此,模式匹配不能用于描述硬件多路复用(Scala match/case 不是 Verilog case)。但是,您确实拥有 Scala 条件/模式匹配的全部功能来描述硬件生成。例如,您可以在 RstEnable 上进行模式匹配,以生成具有或不具有重置功能的硬件。

    您想要的是使用when/.elsewhen/.otherwiseswitch/is。比如:

    when (io.aluop_i === EXE_OR_OP) { 
      logicout := logicout
    }.otherwise {
      logicout := 0.U
    }
    

    您会意识到这很快就会变得冗长,实用程序MuxLookup 提供了一种更简洁的语法来生成具有元组序列的相同内容。:

    logicout := MuxLookup(
      io.aluop_i,
      0.U,
      Seq(EXE_OR_OP -> logicout)
    )
    

    关于参数化

    您使用参数的方式可能最好通过直接参数化Bundles/Modules 而不是定义全局对象来处理。

    例如,您可以有一个抽象的 Parameters 类来定义您的所有参数化。然后为不同版本的 CPU 提供具体的实现。然后,您在构建模块并使用它们需要的东西时将其传递给模块。

    /** An abstract class that defines all the parameters for your CPU */
    abstract class Parameters {
      def RstEnable: Int
      def RstDisable: Int
      def ZeroWord: Int
      def WriteEnable: Int
      def WriteDisable: Int
      def ReadEnable: Int
      def ReadDisable: Int
      def AluOpBusWidth: Int
    }
    
    /** A singleton object that defines the parameters for one instance of your CPU */
    object MyParameters extends Parameters {
      val RstEnable    = 1
      val RstDisable   = 0
      val ZeroWord     = 0
      val WriteEnable  = 1
      val WriteDisable = 0
      val ReadEnable   = 1
      val ReadDisable  = 0
      val AluOpBusWidth = 32
    }
    
    /** The execution unit IO uses one of the parameters to set the bus width */
    class ExIO(a: Parameters) extends Bundle {
      val aluop_i = Input(UInt(a.AluOpBusWidth.W))
      /* ... */
    }
    
    class Ex(a: Parameters) extends Module {
      val io = IO(new ExIO(a))
      /* ... */
    }
    

    然后您将传递一个 Parameters 对象以及模块来构造它:

    (new ChiselStage).emitVerilog(new Ex(MyParameters))
    

    传递所有参数确实很乏味,但是...使用implicit 参数将减少键入的字符。此外,更强大的参数化方法是 Rocket Chip 使用的“上下文相关环境”库。见:chipsalliance/api-config-chipsalliance。大多数项目不需要这个,但对于涉及参数化的复杂情况,它是一种更简洁的方法。

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 1970-01-01
      • 2020-02-09
      • 1970-01-01
      • 2020-03-14
      • 1970-01-01
      • 2011-01-26
      • 1970-01-01
      • 2011-02-10
      相关资源
      最近更新 更多