Scala 使用泛型类型关闭数据路径中的逻辑(凿子)

Scala 使用泛型类型关闭数据路径中的逻辑(凿子),scala,generic-programming,hdl,riscv,chisel,Scala,Generic Programming,Hdl,Riscv,Chisel,我正在开发一个Z-Scale RISCV处理器,在该处理器中,我在数据路径中实现了新的功能和逻辑。我想知道是否有一种简单的方法可以在不使用一堆if循环的情况下“关闭”代码的某些部分?我希望能够轻松地在Z-scale处理器的常规实现和扩展实现之间切换 我实现的新逻辑并没有替换数据路径的主要组件,而是扩展了功能 听起来您的代码如下所示: val a = Wire(UInt()) if (extension) a := 1.U else a := 2.U 您可以做的是创建一个Z比例类

我正在开发一个Z-Scale RISCV处理器,在该处理器中,我在数据路径中实现了新的功能和逻辑。我想知道是否有一种简单的方法可以在不使用一堆if循环的情况下“关闭”代码的某些部分?我希望能够轻松地在Z-scale处理器的常规实现和扩展实现之间切换


我实现的新逻辑并没有替换数据路径的主要组件,而是扩展了功能

听起来您的代码如下所示:

val a = Wire(UInt())
if (extension)
    a := 1.U
else
    a := 2.U
您可以做的是创建一个Z比例类 以及实现 一种包含两种性格差异的性格特征 这两种设计

trait RISC_V_Processor {
    def do_a : UInt
}

class Z_Scale with RISC_V_Processor {
    def do_a : UInt = 2.U
}

class Z_Scale_extended with RISC_V_Processor {
    def do_a : UInt = 1.U
}

val processor = new Z_Scale_extended()
val a = processor.do_a()
这实质上是用多态性替换条件句。

这个问题真正触及了凿子强大的核心。作为一个嵌入Scala的DSL,您可以使用面向对象和函数式编程语言的全部功能

虽然我不确定您到底在做什么,但这似乎是一个使用继承的好地方。您可以创建一个新的模块类来扩展datapath模块并添加附加功能

玩具示例:

import Chisel._

class ParentIO extends Bundle {
  val foo = UInt(width = 32).asInput
  val bar = UInt(width = 32).asOutput
}

class Parent extends Module {
  // Note the use of lazy val
  // Due to Scala initialization order (http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html)
  //   this cannot be a val
  // Due to quirks of Chisel, this cannot be a def
  lazy val io = new ParentIO
  io.bar := io.foo
}

class ChildIO extends ParentIO {
  val isOdd = Bool().asOutput
}

class Child extends Parent {
  override lazy val io = new ChildIO
  io.isOdd := io.foo(0)
}

// Note use of call-by-name for passing gen
// Chisel Modules must be constructed within a call to the Module(...) function
class Top(gen: => Parent) extends Module {
  val dut = Module(gen)
  val io = dut.io.cloneType
  io <> dut.io
}
导入凿子_
类ParentIO扩展包{
val foo=UInt(宽度=32)。作为输入
val bar=UInt(宽度=32)。A输出
}
类父扩展模块{
//注意lazy val的用法
//由于Scala初始化命令(http://docs.scala-lang.org/tutorials/FAQ/initialization-order.html)
//这不能是val
//由于凿子的怪癖,这不能是def
lazy val io=新的ParentIO
io.bar:=io.foo
}
类ChildIO扩展了ParentIO{
val isOdd=Bool().asOutput
}
类子级扩展父级{
覆盖延迟值io=新子项io
io.isOdd:=io.foo(0)
}
//注意:使用名称调用传递gen
//凿子模块必须在对模块(…)函数的调用中构造
类Top(gen:=>Parent)扩展模块{
val dut=模块(发电机)
val io=dut.io.cloneType
木卫一
}

模块Top由其实例化的模块类型参数化:父模块或子模块。因此,您可以有条件地实例化父级或子级,而不是区分它们的所有逻辑。如果您希望子对象覆盖父对象的某些功能,那么凿子的最后一个连接语义允许子对象中的任何连接覆盖父对象中的连接。

我只想指出,第一个示例不会编译,因为重新分配到
a
而不是连接,它应该是
a:=1.U
a:=2.U
是的,这是为了证明一点而快速绘制的,但会解决它。谢谢你的回复!我想知道是否可能有一个变量可以控制模块Top的参数,因此如果变量设置为1,它将实例化子变量,否则将实例化父变量?我尝试了不同的想法,但没有得到我想要的。我回应了@JackKoenig Hi,我尝试了你的方式,但出现了以下错误,
error:(210,21)重写SPADComonModuleIO类型的SPADComonModule类中的惰性值io;lazy value io具有不兼容的类型重写lazy val io=new SPadModuleIO(dataWidth=dataWidth,padSize=padSize)
,想知道在这种情况下如何重写io。我想这是说您正在用一个非子类型的类型重写
lazy val io
。例如,如果
lazy val io=io(新动物)
,使用
override lazy val io=io(新猫)
覆盖是合法的,但不能使用
override lazy val io=io(新苹果)
,请确保在覆盖中实例化的Bundle类扩展正在扩展的父级使用的Bundle。