如何在Chisel HDL中创建C / C ++预处理程序样式宏?

问题描述 投票:1回答:1

我正在将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个回答
0
投票
您看到的特定错误是您试图在logicout := io.aluop_i返回时进行模式匹配。进行硬件连接,返回Unit,然后您尝试在其上进行模式匹配。

Chisel并未将Scala条件/模式匹配转换为硬件构造。因此,模式匹配不能用于描述硬件多路复用(Scalamatch/ case不是Verilog case)。但是,您确实具有Scala条件/模式匹配的全部功能来描述

硬件生成。例如,您可以在RstEnable上进行模式匹配以产生具有或不具有复位功能的硬件。

您想要使用when/.elsewhen/.otherwisewhen。类似于:

.elsewhen

您将意识到,它很快就会变得冗长,实用程序.otherwise提供了更简洁的语法,用于通过一系列元组生成相同的事物。:

switch/is

关于参数化

使用参数的方式可能比直接定义全局对象要好,直接对switch s /iss进行参数化处理会更好。

例如,您可能有一个抽象的when (io.aluop_i === EXE_OR_OP) { logicout := logicout }.otherwise { logicout := 0.U } 类,用于定义所有参数化。然后,您可以为不同版本的CPU提供具体的实现。然后,您可以在构建模块时将其传递给模块,并使用所需的模块。

MuxLookup

然后您将MuxLookup对象与模块一起传递以构造它:

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

尽管传递所有参数确实很乏味,但是...使用Bundle参数将减少键入的字符。同样,更强大的参数化方法是Rocket Chip使用的“上下文相关环境”库。参见:Module。大多数项目都不需要这样做,但是对于涉及参数化的复杂情况,这是一种更干净的方法。    
© www.soinside.com 2019 - 2024. All rights reserved.