首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Chisel传递枚举类型作为IO

Chisel传递枚举类型作为IO
EN

Stack Overflow用户
提问于 2021-02-12 10:20:01
回答 1查看 136关注 0票数 1

这是一个关于chisel enum的相关主题,我已经看过chisel "Enum(UInt(), 5)" failed了。

我正在建立一个RISC-V在凿,并运行到一个路障。我想将算术逻辑单元操作码从操作码、funct3和funct7的组合中抽象为实际的算术逻辑单元操作。下面我有一个SystemVerilog模块,它显示了我想要模拟的行为类型

代码语言:javascript
复制
// Defined in a types file
typedef enum bit [2:0] {
    alu_add = 3'b000,
    alu_sll = 3'b001,
    alu_sra = 3'b010,
    alu_sub = 3'b011,
    alu_xor = 3'b100,
    alu_srl = 3'b101,
    alu_or  = 3'b110,
    alu_and = 3'b111
} alu_ops;

module alu
(
    input alu_ops aluop,
    input [31:0] a, b,
    output logic [31:0] f
);

always_comb
begin
    unique case (aluop)
        alu_add:  f = a + b;
        alu_sll:  f = a << b[4:0];
        alu_sra:  f = $signed(a) >>> b[4:0];
        alu_sub:  f = a - b;
        alu_xor:  f = a ^ b;
        alu_srl:  f = a >> b[4:0];
        alu_or:   f = a | b;
        alu_and:  f = a & b;
    endcase
end

endmodule : alu

这是我正在使用的当前凿文件

AluType.scala

代码语言:javascript
复制
import chisel3._
import chisel3.Driver
import chisel3.experimental.ChiselEnum

package ALUType {

  object AluOP extends ChiselEnum {
//    type AluOP = Value
    val ADDI, SLTI, SLTIU, XORI, ORI, ANDI, SLLI, SLRI, SRAI, ADD, SUB, SLL, SLT, SLTU, XOR, SRL, SRA, OR, AND = Value
  }

}

AluFile.scala

代码语言:javascript
复制
import chisel3._
import chisel3.Driver
import chisel3.experimental.ChiselEnum
import ALUType.AluOP._

class ALUFile(val dl_size: Int, val op_size: Int, val funct3_size: Int, val funct7_size: Int) extends Module {
  val io = IO(new Bundle {
    val val_a       =  Input(UInt(dl_size.W))
    val val_b       =  Input(UInt(dl_size.W))
    val aluop       =  Input(ALUType.AluOP.Type)
    //val opcode      =  Input(UInt(op_size.W))
    //val funct3      =  Input(UInt(funct3_size.W))
    //val funct7      =  Input(UInt(funct7_size.W))
    val val_out     = Output(UInt(dl_size.W))
  })

// Actual function
}

这是sbt运行的结果

代码语言:javascript
复制
$ sbt run
[info] welcome to sbt 1.4.7 (Oracle Corporation Java 1.8.0_281)
[info] loading project definition from C:\Chisel\Test1\RegFile\project
[info] loading settings for project regfile from build.sbt ...
[info] set current project to regfile (in build file:/C:/Chisel/Test1/RegFile/)
[info] compiling 1 Scala source to C:\Chisel\Test1\RegFile\target\scala-2.12\classes ...
[error] C:\Chisel\Test1\RegFile\src\main\scala\ALUFile.scala:43:30: inferred type arguments [ALUType.AluOP.Type.type] do not conform to method apply's type parameter bounds [T <: chisel3.Data]
[error]     val aluop       =  Input(Wire(ALUType.AluOP.Type))
[error]                              ^
[error] C:\Chisel\Test1\RegFile\src\main\scala\ALUFile.scala:43:49: type mismatch;
[error]  found   : ALUType.AluOP.Type.type
[error]  required: T
[error]     val aluop       =  Input(Wire(ALUType.AluOP.Type))
[error]                                                 ^
[error] two errors found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 4 s, completed Feb 11, 2021 8:35:18 PM

我是否只需要将其分配给更高级别的UInt,然后再次解码?为了把它从一个模块传递到下一个模块,必须先进行编码,然后再进行解码,这似乎很愚蠢。有没有办法让AluOP.Type符合T?我本以为它会这么做,因为它是一个ChiselEnum。

编辑::1

我尝试过使用UInt枚举,但它显示这是一个非文字类型

代码语言:javascript
复制
[info] running ALUFile
[info] [0.000] Elaborating design...
[error] chisel3.internal.ChiselException: AluOp defined with a non-literal type
[error]         ...
[error]         at AluOp$.<init>(ALUFile.scala:41)
[error]         at AluOp$.<clinit>(ALUFile.scala)
[error]         at ALUFile$$anon$1.<init>(ALUFile.scala:49)
[error]         at ALUFile.<init>(ALUFile.scala:46)
[error]         at ALUFile$.$anonfun$new$6(ALUFile.scala:80)
代码语言:javascript
复制
object AluOp extends ChiselEnum {
    val addi, slti, sltiu, xori, ori, andi, slli, slri, srai, add, sub, sll, slt, sltu, xor, srl, sra, or, and = Value(UInt()) // Line where error occurs
}
import AluOp._

class ALUFile(val dl_size: Int, val op_size: Int, val funct3_size: Int, val funct7_size: Int) extends Module {
  val io = IO(new Bundle {
    val val_a       =  Input(UInt(dl_size.W))
    val val_b       =  Input(UInt(dl_size.W))
    val aluop       =  Input( AluOp() )
    val val_out     = Output(UInt(dl_size.W))
  })

  switch (io.aluop) {
    is (addi) {
      io.val_out  := 1.U
    }
    is (slti) {
      io.val_out  := 2.U
    }
  }

  // Output result
  io.val_out  := 0.U

}

来自https://github.com/chipsalliance/chisel3/blob/dd6871b8b3f2619178c2a333d9d6083805d99e16/src/test/scala/chiselTests/StrongEnum.scala

他们在switch语句中使用枚举的唯一示例,但他们手动将值映射到不是enum的类型!

代码语言:javascript
复制
object StrongEnumFSM {
  object State extends ChiselEnum {
    val sNone, sOne1, sTwo1s = Value

    val correct_annotation_map = Map[String, BigInt]("sNone" -> 0, "sOne1" -> 1, "sTwo1s" -> 2)
  }
}

class StrongEnumFSM extends Module {
  import StrongEnumFSM.State
  import StrongEnumFSM.State._

  // This FSM detects two 1's one after the other
  val io = IO(new Bundle {
    val in = Input(Bool())
    val out = Output(Bool())
    val state = Output(State())
  })

  val state = RegInit(sNone)

  io.out := (state === sTwo1s)
  io.state := state

  switch (state) {
    is (sNone) {
      when (io.in) {
        state := sOne1
      }
    }
    is (sOne1) {
      when (io.in) {
        state := sTwo1s
      } .otherwise {
        state := sNone
      }
    }
    is (sTwo1s) {
      when (!io.in) {
        state := sNone
      }
    }
  }
}

一种可能存在的解决方案可以在https://github.com/chipsalliance/chisel3/issues/885中找到,在这里他定义了自己的Scala对象,并允许调用返回一个UInt。

此外,如果我只使用Enum,我可以编译它,这可能是目前最好的解决方案。我希望看到ChiselEnum能够轻松地在UInts中定义状态或操作,并能够将它们作为IO传递,这样我就可以摆脱使用数字来定义状态,并使它们更具可读性。

代码语言:javascript
复制
object AluOp {
        val addi :: slti :: sltiu :: xori :: ori :: andi :: slli :: slri :: srai :: add :: sub :: sll :: slt :: sltu :: xor :: srl :: sra :: or :: and :: Nil = Enum(19)
    }
import AluOp._

class ALUFile(val dl_size: Int, val op_size: Int, val funct3_size: Int, val funct7_size: Int) extends Module {
  val io = IO(new Bundle {
    val val_a       =  Input(UInt(dl_size.W))
    val val_b       =  Input(UInt(dl_size.W))
//    val aluop       =  Input( UInt(AluOp.getWidth.W) )
    val aluop       =  Input(UInt(5.W))
//    val opcode      =  Input(UInt(op_size.W))
//    val funct3      =  Input(UInt(funct3_size.W))
//    val funct7      =  Input(UInt(funct7_size.W))
    val val_out     = Output(UInt(dl_size.W))
  })
  //  val reg_last = RegNext()

  switch (io.aluop) {
    is (addi) {
      io.val_out  := 1.U
    }
    is (slti) {
      io.val_out  := 2.U
    }
  }
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2021-02-12 13:37:09

我认为你所需要做的就是使用

代码语言:javascript
复制
val aluop       =  Input(AluOP())

chisel3 unit tests中可以找到一些简单的示例代码

操作编辑::

通过添加映射:

代码语言:javascript
复制
import chisel3._
import chisel3.Driver
import chisel3.util._
import chisel3.experimental.ChiselEnum

package ALUType {
//    object AluOp {
//        val addi :: slti :: sltiu :: xori :: ori :: andi :: slli :: slri :: srai :: add :: sub :: sll :: slt :: sltu :: xor :: srl :: sra :: or :: and :: Nil = Enum(19)
//    }
    object AluOp extends ChiselEnum {
        val add, sub, sll, slt, sltu, xor, srl, sra, or, and = Value

        val correct_annotation_map = Map[String, UInt](
            "add"  -> 0.U,
            "sub"  -> 1.U,
            "sll"  -> 2.U,
            "slt"  -> 3.U,
            "sltu" -> 4.U,
            "xor"  -> 5.U,
            "srl"  -> 6.U,
            "sra"  -> 7.U,
            "or"   -> 8.U,
            "and"  -> 9.U
        )
    }
}

该值可以作为输入传递:

代码语言:javascript
复制
import ALUType.AluOp._

class ALUFile(val dl_size: Int, val op_size: Int, val funct3_size: Int, val funct7_size: Int) extends Module {
  import ALUType._
  import ALUType.AluOp._
  val io = IO(new Bundle {
    val val_a       =  Input(UInt(dl_size.W))
    val val_b       =  Input(UInt(dl_size.W))
    val aluop       =  Input( AluOp() )
//    val aluop       =  Input(UInt(5.W))
//    val opcode      =  Input(UInt(op_size.W))
//    val funct3      =  Input(UInt(funct3_size.W))
//    val funct7      =  Input(UInt(funct7_size.W))
    val val_out     = Output(UInt(dl_size.W))
  })
//  switch (io.aluop) {
//    is (add) {
//      io.val_out  := io.val_a + io.val_b
//    }
//    is (slt) {
//      io.val_out  := 2.U
//    }
//  }

  switch (io.aluop) {
    is (add) {
      io.val_out  := io.val_a + io.val_b
    }
    is (slt) {
      io.val_out  := 2.U
    }
  }

  // Output result
  io.val_out  := 0.U

}

这仍然不是很理想,因为我希望不必手动将字符串映射到UInt值,但它就是这样。也许Scala foreach循环可以消除繁琐的赋值,谁知道呢。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66165591

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档