Используйте общий тип, чтобы отключить логику в пути данных (Chisel)

Я работаю над RISCV-процессором Z-Scale, где я реализовал новые функции и логику в пути данных. Мне интересно, существует ли простой способ «отключить» определенные части кода без использования множества циклов if? Я хотел бы упростить переключение между обычной реализацией процессора Z-шкалы и реализацией с расширенной реализацией.

Новая логика, которую я реализовал, не заменяет основные компоненты пути данных, а расширяет функциональность.


person Mrchacha    schedule 17.11.2016    source источник


Ответы (2)


Этот вопрос действительно затрагивает суть того, что делает Chisel мощным. Как DSL, встроенный в Scala, вы имеете доступ ко всей мощи объектно-ориентированного и функционального языка программирования.

Хотя я не уверен, что именно вы делаете, это похоже на хорошее место для использования наследования. Вы можете создать новый класс модуля, который расширяет модуль пути данных и добавляет дополнительные функции.

Пример игрушки:

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
}

Модуль Top параметризуется типом модуля, который он создает: родительский или дочерний. Таким образом, вы можете условно создать Parent или Child, а не всю логику, которая их различает. Если вы хотите, чтобы дочерний элемент переопределял определенные функции родителя, семантика последнего соединения Chisel позволяет любым соединениям в дочернем элементе переопределять соединения в родительском элементе.

person Jack Koenig    schedule 17.11.2016
comment
Спасибо за ответ! Мне интересно, возможно ли иметь переменную, которая может управлять параметром модуля Top, поэтому она будет создавать экземпляр Child, если для переменной установлено значение 1, и Parent в противном случае? Я пробовал разные идеи, но не получил того, что хочу. - person Mrchacha; 18.01.2017
comment
Я ответил на stackoverflow.com/questions/ 41720320/ - person Jack Koenig; 19.01.2017
comment
@JackKoenig Привет, я попробовал ваш способ, но получил следующую ошибку: Error:(210, 21) overriding lazy value io in class SPadCommonModule of type SPadCommonModuleIO; lazy value io has incompatible type override lazy val io = new SPadModuleIO (dataWidth = DataWidth, padSize = PadSize), интересно, как переопределить ввод-вывод в этом случае. - person Frederick Hong; 10.06.2020
comment
Я думаю, это говорит о том, что вы переопределяете lazy val io типом, который не является подтипом. Например, если lazy val io = IO(new Animal) допустимо переопределять с помощью override lazy val io = IO(new Cat), но не с override lazy val io = IO(new Apple), убедитесь, что класс Bundle, экземпляр которого вы создаете в переопределении, расширяет Bundle, используемый родителем, который вы расширяете. - person Jack Koenig; 10.06.2020

Похоже, ваш код выглядит так:

val a = Wire(UInt())
if (extension)
    a := 1.U
else
    a := 2.U

Что вы могли бы сделать, так это создать класс Z-шкалы и класс, расширенный 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()

По сути, это замена условных операторов полиморфизмом. https://sourcemaking.com/refactoring/replace-conditional-with-polymorphism

person Sebastian Bøe    schedule 17.11.2016
comment
Я просто хотел указать, что первый пример не будет компилироваться из-за переназначения на a вместо соединения, должно быть a := 1.U и a := 2.U - person Jack Koenig; 18.11.2016
comment
Да, это было набросано быстро, чтобы продемонстрировать точку зрения, хотя это исправим. - person Sebastian Bøe; 19.11.2016