4
votes

I was trying to create control logic for a circuit in chisel when I received multiple errors related to the switch statements I was using. I decided to run the switch statement sample code provided on pages 9 and 10 of the official chisel tutorial to isolate the problem.

Scala code:

package Testbed

import Chisel._


class Testbed extends Module {
  val io = new Bundle {
    val nickel = Bool(dir = INPUT)
    val dime = Bool(dir = INPUT)
    val rdy = Bool(dir = OUTPUT) }

  val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UFix(), 5)
  val state = Reg(init = s_idle)

  switch (state) {
    is (s_idle) {
      when (io.nickel) { state := s_5 }
      when (io.dime) { state := s_10 }
    } is (s_5) {
      when (io.nickel) { state := s_10 }
      when (io.dime) { state := s_15 }
    } is (s_10) {
      when (io.nickel) { state := s_15 }
      when (io.dime) { state := s_ok }
    } is (s_15) {
      when (io.nickel) { state := s_ok }
      when (io.dime) { state := s_ok }
    } is (s_ok) {
      state := s_idle
    }
  }
  io.rdy := (state === s_ok)
}


class TestbedTests(c: Testbed) extends Tester(c) {
}

object Testbed {
  def main(args: Array[String]): Unit = {
    val tutArgs = args.slice(1, args.length)
    chiselMainTest(tutArgs, () => Module(new Testbed())) {
      c => new TestbedTests(c) }
  }
}

But I get errors related to UFix:

[error] /home/chisel-tutorial/test/Testbed.scala:12: not found: value UFix
[error]   val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UFix(), 5)
[error]                                                           ^
[error] /home/chisel-tutorial/test/Testbed.scala:13: inferred type arguments [Any] do not conform to method apply's type parameter bounds [T <: Chisel.Data]
[error]   val state = Reg(init = s_idle)
[error]               ^
[error] /home/chisel-tutorial/test/Testbed.scala:16: overloaded method value apply with alternatives:
[error]   (v: Iterable[Chisel.Bits])(block: => Unit)Unit <and>
[error]   (v: Chisel.Bits,vr: Chisel.Bits*)(block: => Unit)Unit <and>
[error]   (v: Chisel.Bits)(block: => Unit)Unit
[error]  cannot be applied to (Any)
[error]     is (s_idle) {
[error]     ^
[error] three errors found
[error] (compile:compile) Compilation failed

The tutorial actually had it written as UFIx with a capital I but I tried it both ways to no avail. I assumed this is just an old type and so I replaced UFix with UInt but left everything else the same. Then I get the following errors:

[error] /home/chisel-tutorial/test/Testbed.scala:19: value is is not a member of Unit
[error] possible cause: maybe a semicolon is missing before `value is'?
[error]     } is (s_5) {
[error]       ^
[error] one error found
[error] (compile:compile) Compilation failed

Heeding the error message, I attempted to resolve the error by adding semicolons prior to every "is" statement except for the first:

package Testbed

import Chisel._


class Testbed extends Module {
  val io = new Bundle {
    val nickel = Bool(dir = INPUT)
    val dime = Bool(dir = INPUT)
    val rdy = Bool(dir = OUTPUT) }

  val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)
  val state = Reg(init = s_idle)

  switch (state) {
    is (s_idle) {
      when (io.nickel) { state := s_5 }
      when (io.dime) { state := s_10 }
    }; is (s_5) {
      when (io.nickel) { state := s_10 }
      when (io.dime) { state := s_15 }
    }; is (s_10) {
      when (io.nickel) { state := s_15 }
      when (io.dime) { state := s_ok }
    }; is (s_15) {
      when (io.nickel) { state := s_ok }
      when (io.dime) { state := s_ok }
    }; is (s_ok) {
      state := s_idle
    }
  }
  io.rdy := (state === s_ok)
}


class TestbedTests(c: Testbed) extends Tester(c) {
}

object Testbed {
  def main(args: Array[String]): Unit = {
    val tutArgs = args.slice(1, args.length)
    chiselMainTest(tutArgs, () => Module(new Testbed())) {
      c => new TestbedTests(c) }
  }
}

and the resulting code was finally successful in generating verilog. Then I also tried removing the semicolon but putting the closing curly bracket from the previous switch statement in the line above which also worked:

package Testbed

import Chisel._


class Testbed extends Module {
  val io = new Bundle {
    val nickel = Bool(dir = INPUT)
    val dime = Bool(dir = INPUT)
    val rdy = Bool(dir = OUTPUT) }

  val s_idle :: s_5 :: s_10 :: s_15 :: s_ok :: Nil = Enum(UInt(), 5)
  val state = Reg(init = s_idle)

  switch (state) {
    is (s_idle) {
      when (io.nickel) { state := s_5 }
      when (io.dime) { state := s_10 }}
    is (s_5) {
      when (io.nickel) { state := s_10 }
      when (io.dime) { state := s_15 }}
    is (s_10) {
      when (io.nickel) { state := s_15 }
      when (io.dime) { state := s_ok }}
    is (s_15) {
      when (io.nickel) { state := s_ok }
      when (io.dime) { state := s_ok }}
    is (s_ok) {
      state := s_idle
    }
  }
  io.rdy := (state === s_ok)
}


class TestbedTests(c: Testbed) extends Tester(c) {
}

object Testbed {
  def main(args: Array[String]): Unit = {
    val tutArgs = args.slice(1, args.length)
    chiselMainTest(tutArgs, () => Module(new Testbed())) {
      c => new TestbedTests(c) }
  }
}

My concern now is whether the version of the switch statement as presented in the chisel tutorial works for other people, and if it does, does anyone know why I have to be careful to format my switch statements in a very particular way in order for them to work properly? If that is the case, what can I do to fix it?

2

2 Answers

2
votes

The reason is related to scala syntax. Its important to remember that you are coding in scala and Chisel simultaneously. Your error with 'is' is similar to the following scala syntax:

hashmap getOrElse (foo, bar)

'is' is defined as an object in https://github.com/ucbbar/chisel/blob/master/src/main/scala/when.scala

essentially scala is interpreting it as:

is().is

which doesn't exist so it thinks you meant to define it as a val and just screwed up

0
votes

As you noticed, UFix is no longer in use. Instead use UInt.

Second, the "is" must start on its own line. It can't be preceded by a {.