可视化 Chisel 硬件译码器代码生成工具。通过图形界面将 RISC-V 指令映射到控制信号(OneHot / Binary / Gray),自动生成 Chisel CtrlEnum + DecodeField 代码。
git clone --recursive <repo-url>
cd VisualDecoder
make init # 拉取子模块 → 生成指令数据库 → 创建虚拟环境
make run # 启动应用或使用独立脚本(可在任意目录下运行):
./run.sh- 选择/创建 Profile — 设置包名和 Ctrl.scala 输出路径
- 勾选扩展 — 选择需要解码的 RISC-V 指令集(RV32I、M、Zicsr 等)
- 新建 Decoder — 命名(如
InstType),选择编码模式:Binary / OneHot / Gray - 创建分组 — 添加 ALU、LSU、BRU 等指令分组,通过下拉菜单或批量操作分配指令
- 实时预览 — 右侧面板实时显示生成的 Chisel 代码,支持语法高亮
- 保存 (
Ctrl+S) — 保存到 JSON 配置文件,Ctrl.scala文件按需导出
package mq.util.decoder
import chisel3._
import chisel3.util._
import mq.util.CtrlEnum
import chisel3.util.experimental.decode._
object InstTypeCtrl extends CtrlEnum(CtrlEnum.OneHot) {
val ALU = Value
val LSU = Value
val BRU = Value
def isALU: Seq[String] = Seq("ADD", "ADDI", "SUB", "AND", ...)
def isLSU: Seq[String] = Seq("LW", "SW", "LB", ...)
def isBRU: Seq[String] = Seq("BEQ", "BNE", "JAL", ...)
}
object InstTypeField extends DecodeField[InstructionPattern, UInt] {
override def name: String = "InstTypeField"
override def chiselType: UInt = UInt(InstTypeCtrl.getWidth.W)
override def genTable(op: InstructionPattern): BitPat = {
BitPat(op.nameMatch(map, 0.U(InstTypeCtrl.getWidth.W)))
}
}导出时同时生成 DecodeFields.scala 和 Instructions.scala。可选生成 CtrlEnum.scala(CtrlEnum 基类,含 Binary/OneHot/Gray 编码、Mux、PriorityMux):
// DecodeFields.scala — 聚合所有 DecodeField
object DecodeFields {
def all: Seq[DecodeField[InstructionPattern, UInt]] = {
Seq(
InstTypeField,
ALUOpField,
...
)
}
}
// Instructions.scala — 指令数据库(数据来源:riscv-opcodes/inst.chisel)
object Instructions {
val IType = Map(
"ADD" -> BitPat("b0000000??????????000?????0110011"),
...
)
val MType = Map(...)
def db(): Seq[InstructionPattern] = { ... }
def print() = { ... }
}
// CtrlEnum.scala — 可选生成的基类文件(Profile 中勾选"生成 CtrlEnum.scala")
object CtrlEnum extends Enumeration {
type enumType = Value
val Binary, OneHot, Gray = Value
}
abstract class CtrlEnum(mode: CtrlEnum.enumType) {
def Value: Int = { ... } // 编码生成(Binary/OneHot/Gray)
def Values: Seq[UInt] = { ... } // 所有编码值
def getWidth: Int = { ... } // 位宽
object Mux { ... } // 硬件多路选择器
object PriorityMux { ... } // 优先级选择器(仅 OneHot)
}在硬件中使用:
val table = new DecodeTable(Instructions.db(), DecodeFields.all())
val result = table.decode(io.inst)
io.iType := result(InstTypeField)
io.alu.op := result(ALUOpField)在 Profile 设置中勾选"生成 CtrlEnum.scala"并指定包名(默认 mq.util)和输出路径(留空则使用上方输出路径),导出时会同时生成 CtrlEnum.scala 基类文件,包含 CtrlEnum 抽象类(Binary/OneHot/Gray 编码、Mux、PriorityMux)。该文件是所有解码器代码的依赖基础。
菜单 视图 → 切换主题 在暗色/亮色(Tokyo Night 配色)之间切换。
所有数据保存在 ~/.config/VisualDecoder/:
| 文件 | 说明 |
|---|---|
config.json |
全局设置:主题、最后使用的 Profile、指令数据库路径 |
profiles/<name>.json |
Profile 数据:包名、输出路径、扩展、Decoder 和分组定义 |
chisel-demo/ 目录包含一个独立的 SBT Chisel 演示工程,展示从 VisualDecoder 生成的解码器代码到硬件解码的完整流程(与 mini-mq 的译码方式一致):
cd chisel-demo
make test # 6 个测试用例(ChiselSim 硬件仿真)
make verilog # 生成 Verilog → build/DecoderDemo.sv演示内容:
InstTypeCtrl/ALUOpCtrl— VisualDecoder 导出的代码格式(CtrlEnum 分组 + DecodeField),可直接替换复用DecoderDemo模块 —new DecodeTable(Instructions.db(), DecodeFields.all())硬件解码指令,输出 iType / aluOp / aluRes- OneHot 按位判断(
iType(InstTypeCtrl.ALU))+CtrlEnum.Mux选通 ALU 结果
- Python >= 3.10
- PyQt6(自动安装)
- Chisel 演示需 JDK 和 SBT
| 快捷键 | 功能 |
|---|---|
Ctrl+S |
保存 Profile |