val a = Wire(UInt(4.W)) a := 0.U// legal: chisel UInt a := 0// illegal: scala Int
Boolean vs. Bool
1 2 3 4 5 6 7 8
val bool = Wire(Bool()) val boolean: Boolean = false // legal when (bool) { ... } if (boolean) { ... } // illegal if (bool) { ... } when (boolean) { ... }
Type Coercion
Scala
x.asInstanceOf[T] casts the object x to the type T. It throws an exception if the given object cannot be cast to type T.
1 2 3 4 5 6 7 8 9
val x: UInt = 3.U // We can't cast UInt to Int try { println(x.asInstanceOf[Int]) } catch { case e: java.lang.ClassCastException => println("As expected, we can't cast UInt to Int") } // But we can cast UInt to Data since UInt inherits from Data. println(x.asInstanceOf[Data])
Chisel
Chisel has a set of type casting functions. The most general is asTypeOf(). Some chisel objects also define asUInt() and asSInt() as well as some others.
1 2 3 4 5 6 7
classTypeConvertDemoextendsModule{ val io = IO(newBundle { val in = Input(UInt(4.W)) val out = Output(SInt(4.W)) }) io.out := io.in.asTypeOf(io.out) }
Match
Type Match
1 2 3 4 5 6 7 8 9 10
classConstantSum(in1: Data, in2: Data) extendsModule{ val io = IO(newBundle { val out = Output(chiselTypeOf(in1)) // in case in1 is literal then just get its type }) (in1, in2) match { case (x: UInt, y: UInt) => io.out := x + y case (x: SInt, y: SInt) => io.out := x + y case _ => thrownewException("I give up!") } }
Value Match
It is good to remember that Chisel types generally should not be value matched. Scala’s match executes during circuit elaboration, but what you probably want is a post-elaboration comparison. The following gives a syntax error:
1 2 3 4 5 6 7 8 9 10 11
classInputIsZeroextendsModule{ val io = IO(newBundle { val in = Input(UInt(16.W)) val out = Output(Bool()) }) io.out := (io.in match { // note that case 0.U is an error case (0.U) => true.B case _ => false.B }) }
Unapply
value matching with case classes
1 2 3 4 5 6
caseclassSomething(a: String, b: Int) val a = Something("A", 3) a match { caseSomething("A", value) => value caseSomething(str, 3) => 0 }
Scala unapply methods are another form of syntactic sugar that give match statements the ability to both match on types and extract values from those types during the matching
defdelay(p: SomeGeneratorParameters): Int = p match { case sg @ SomeGeneratorParameters(_, _, true) => sg.totalWidth * 3 caseSomeGeneratorParameters(_, sw, false) => sw * 2 case sg @ SomeGeneratorParameters(_, _, true) if sg.pipelineMe => sg.totalWidth * 3 }
All these syntaxes are enabled by a Scala unapply method contained in a class’s companion object. If you want to unapply a class but do not want to make it a case class, you can manually implement the unapply method. The following example demonstrates how one can manually implement a class’s apply and unapply methods:
defgetSmallBoats(seq: Seq[Boat]): Seq[Boat] = seq.filter { b => b match { caseBoat(_, length) if length < 60 => true caseBoat(_, _) => false } }
val boats = Seq(Boat("Santa Maria", 62), Boat("Pinta", 56), Boat("Nina", 50)) println(getSmallBoats(boats).map(_.name).mkString(" and ") + " are small boats!")