Chisel Cannot reassign to read-only - scala

This is a continuation from the other question i asked : Instanciation of a class doesn't work (Chisel/Scala)
Actually, I wanna print the "result" variable. I wrote this command : sbt test, and I don't understand this error :
"chisel3.internal.ChiselException: Cannot reassign to read-only combinedTausworthe.b: OpResult[UInt<32>] "
This is the Test file
import chiseltest._
import org.scalatest.freespec.AnyFreeSpec
class combined_test extends AnyFreeSpec with ChiselScalatestTester {
"combinedTauswhore" in {
test(new combinedTausworthe() ){ c =>
//Initialisation
c.clock.step(1)
println(c.result)
c.clock.step(1)
println(c.result)
}
}
}
This is the class :
import chisel3._
class combinedTausworthe extends Module{
val io = IO(new Bundle {
})
val seed1 = RegInit(322769304.U(32.W))
val seed2 = RegInit(424235419.U(32.W))
val seed3 = RegInit(212119443.U(32.W))
var result= 0.U
var b = ((seed1 << 13)(31,0) ^ seed1)
seed1 := ((seed1 & 4294967294L.U) << 12)(31,0) ^ b
b := ((seed2 << 2)(31,0) ^ seed2) >> 25
seed2 := ((seed2 & 4294967294L.U) << 4)(31,0) ^ b
b := ((seed3<<3)(31,0) ^ seed3) >> 11
seed3 := ((seed3 & 4294967294L.U) <<17)(31,0) ^ b
result := (seed1 ^ seed2 ^ seed3)
}
object Main extends App {
}

In Chisel3, := is the connection operator for driving a signal with some value. Think about it as creating an electrical connection. In your code, it looks like you are trying to reassign to a mutable variable rather than drive the value of that variable with a value, try =:
import chisel3._
class combinedTausworthe extends Module{
val io = IO(new Bundle {
})
val seed1 = RegInit(322769304.U(32.W))
val seed2 = RegInit(424235419.U(32.W))
val seed3 = RegInit(212119443.U(32.W))
var result= 0.U
var b = ((seed1 << 13)(31,0) ^ seed1)
seed1 := ((seed1 & 4294967294L.U) << 12)(31,0) ^ b
// Note using assignment (=), not connection (:=)
b = ((seed2 << 2)(31,0) ^ seed2) >> 25
seed2 := ((seed2 & 4294967294L.U) << 4)(31,0) ^ b
b = ((seed3<<3)(31,0) ^ seed3) >> 11
seed3 := ((seed3 & 4294967294L.U) <<17)(31,0) ^ b
// Same thing here
result = (seed1 ^ seed2 ^ seed3)
}
That being said, as Scala is a functional programming language and we stylistically prefer pure/immutable constructs, try just using values:
import chisel3._
class combinedTausworthe extends Module{
val io = IO(new Bundle {
})
val seed1 = RegInit(322769304.U(32.W))
val seed2 = RegInit(424235419.U(32.W))
val seed3 = RegInit(212119443.U(32.W))
// Note result var removed and replaced with val below
val b1 = ((seed1 << 13)(31,0) ^ seed1)
seed1 := ((seed1 & 4294967294L.U) << 12)(31,0) ^ b1
val b2 = ((seed2 << 2)(31,0) ^ seed2) >> 25
seed2 := ((seed2 & 4294967294L.U) << 4)(31,0) ^ b2
val b3 = ((seed3<<3)(31,0) ^ seed3) >> 11
seed3 := ((seed3 & 4294967294L.U) <<17)(31,0) ^ b3
val result = (seed1 ^ seed2 ^ seed3)
}

Related

Scala for-comprehension yielding result from multiple variable bindings

I am very curious how Scala desugars the following for-comprehension:
for {
a <- Option(5)
b = a * 2
c <- if (b == 10) Option(100) else None
} yield b + c
My difficulty comes from having both b and c in the yield, because they seem to be bound at different steps
This is the sanitized output of desugar - a command available in Ammonite REPL:
Option(5)
.map { a =>
val b = a * 2;
(a, b)
}
.flatMap { case (a, b) =>
(if (b == 10) Option(100) else None)
.map(c => b + c)
}
Both b and c can be present in yield because it does not desugar to chained calls to map/flatMap, but rather to nested calls.
You can even ask the compiler. The following command:
scala -Xprint:parser -e "for {
a <- Option(5)
b = a * 2
c <- if (b == 10) Option(100) else None
} yield b + c"
yields this output
[[syntax trees at end of parser]] // scalacmd7617799112170074915.scala
package <empty> {
object Main extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
def main(args: Array[String]): scala.Unit = {
final class $anon extends scala.AnyRef {
def <init>() = {
super.<init>();
()
};
Option(5).map(((a) => {
val b = a.$times(2);
scala.Tuple2(a, b)
})).flatMap(((x$1) => x$1: #scala.unchecked match {
case scala.Tuple2((a # _), (b # _)) => if (b.$eq$eq(10))
Option(100)
else
None.map(((c) => b.$plus(c)))
}))
};
new $anon()
}
}
}
Taking only the piece you are interested in and improving the readability, you get this:
Option(5).map(a => {
val b = a * 2
(a, b)
}).flatMap(_ match {
case (_, b) =>
if (b == 10)
Option(100)
else
None.map(c => b + c)
})
Edit
As reported in a comment, literally translating from the compiler output seems to highlight a bug in how the desugared expression is rendered. The sum should be mapped on the result of the if expression, rather then on the None in the else branch:
Option(5).map(a => {
val b = a * 2
(a, b)
}).flatMap(_ match {
case (_, b) =>
(if (b == 10) Option(100) else None).map(c => b + c)
})
It's probably worth it to ask the compiler team if this is a bug.
These two codes are equivalent:
scala> for {
| a <- Option(5)
| b = a * 2
| c <- if (b == 10) Option(100) else None
| } yield b + c
res70: Option[Int] = Some(110)
scala> for {
| a <- Option(5)
| b = a * 2
| if (b == 10)
| c <- Option(100)
| } yield b + c
res71: Option[Int] = Some(110)
Since there is no collection involved, yielding multiple values, there is only one big step - or, arguable, 3 to 4 small steps. If a would have been None, the whole loop would have been terminated early, yielding a None.
The desugaring is a flatMap/withFilter/map.

how to cross product of list without OutOfMemory

this is my code
def main(args: Array[String]): Unit = {
genSomeThing.grouped(100).grouped(1000)
// save to MongoDB
}
def genSomeThing: Stream[String] = {
for {
a <- ('A' to 'Z').toStream
b <- ('0' to '9').toStream
c <- ('A' to 'Z').toStream
d <- ('0' to '9').toStream
e <- ('A' to 'Z').toStream
f <- ('A' to 'Z').toStream
} yield s"$a$b$c$d$e$f"
}
and I make bulk insert to MongoDB (100 col, 1000 record), I get exception OutofMemory java heap space or GC limit exceed
how to save to MongoDB without exception (I change Stream to Iterator but useless and get the same exception)
This is what I came up with, trying to follow your desired result strings.
class dataStr extends Iterator[String] {
private val itr: Iterator[BigInt] = Iterator.iterate(0:BigInt)(_ + 1)
override def hasNext = true
override def next = {
val na = itr.next ; val ca: Char = ('A' + na%26).toChar
val nb = na/26 ; val cb: Char = ('A' + nb%26).toChar
val nc = nb/26 ; val cc: Char = ('0' + nc%10).toChar
val nd = nc/10 ; val cd: Char = ('A' + nd%26).toChar
val ne = nd/26 ; val ce: Char = ('0' + ne%10).toChar
val nf = ne/10 ; val cf: Char = ('A' + nf%26).toChar
s"$cf$ce$cd$cc$cb$ca"
}
}
From here you can group and insert as needed.
val ds = new dataStr
ds.next // res0: String = A0A0AA
ds.grouped(100).grouped(1000) // res1: GroupedIterator[Seq[String]] = non-empty iterator
ds.next // res2: String = A0O7YF

Chisel3. Functional Module Mux4

I'm learning Chisel following the documentation on Github
Thus far, everything worked flawlessly. But i'm stuck at chapter 13, "Functional Module Creation"
I can't get the code to work. I created all my .scala classes in a copy of the chisel-template-project. Here is what i wrote / copied to create a Mux4 with variable bit width:
/chisel-template/src/main/scala/Mux4.scala
import Chisel._
class Mux4(w: Int) extends Module {
val io = IO(new Bundle {
val sel = UInt(INPUT, 2)
val in0 = UInt(INPUT, w)
val in1 = UInt(INPUT, w)
val in2 = UInt(INPUT, w)
val in3 = UInt(INPUT, w)
val out = UInt(OUTPUT, w)
})
io.out := Mux2(io.sel(1),
Mux2(io.sel(0), io.in0, io.in1),
Mux2(io.sel(0), io.in2, io.in3))
}
class Mux2(w: Int) extends Module {
val io = IO(new Bundle {
val sel = Bool(INPUT)
val in0 = UInt(INPUT, w)
val in1 = UInt(INPUT, w)
val out = UInt(OUTPUT, w)
})
when(io.sel) {
io.out := io.in0
}.otherwise {
io.out := io.in1
}
}
object Mux2 {
def apply(sel: UInt, in0: UInt, in1: UInt): UInt = {
val m = new Mux2(in0.getWidth)
m.io.sel := sel.toBool()
m.io.in0 := in0
m.io.in1 := in1
m.io.out
}
}
The Tester scala class i wrote:
/chisel-template/src/test/scala/Mux4Test.scala
import Chisel.iotesters.{ChiselFlatSpec, Driver, PeekPokeTester}
class Mux4Test(c: Mux4) extends PeekPokeTester(c) {
val sel = 3
val (in0, in1, in2, in3) = (5, 7, 11, 15)
poke(c.io.sel, sel)
poke(c.io.in0, in0)
poke(c.io.in1, in1)
poke(c.io.in2, in2)
poke(c.io.in3, in3)
step(1)
System.out.println("Circuit: "+peek(c.io.out)
+" Expected: "+TestMux4.result(sel, in0, in1, in2, in3))
}
object TestMux4{
def result(sel: Int, in0: Int, in1: Int, in2: Int, in3: Int): Int = {
val out = sel match{
case 0 => in3
case 1 => in2
case 2 => in1
case 3 => in0
}
out
}
}
class Mux4Tester extends ChiselFlatSpec {
behavior of "Mux4"
backends foreach {backend =>
it should s"do Mux4 $backend" in {
Driver(() => new Mux4(4), backend)(c => new Mux4Test(c)) should be (true)
}
}
}
The important part from the output
STEP 0 -> 1
Circuit: 0 Expected: 5
The Mux4 class (Circuit) returns 0 as output, whereas it should be 5, because the selection process is as follows:
00 -> io.out = in3 = 15
01 -> io.out = in2 = 11
10 -> io.out = in1 = 7
11 -> io.out = in0 = 5
In the Mux4Test.scala class i wrote val sel = 3. The bit representation of this is 11 and therefore i'd expect in0 = 5.
Where am i wrong?
Thank you for your interest in Chisel!
I ran your example, and after scratching my head for a while I found the problem: when you instantiate a Chisel Module, you need to make sure to wrap it in Module(...) (EDIT: The code on the wiki omitted this wrapper. This has been fixed). Thus, object Mux2 should instead be:
object Mux2 {
def apply(sel: UInt, in0: UInt, in1: UInt): UInt = {
val m = Module(new Mux2(in0.getWidth)) // <- See Here
m.io.sel := sel.toBool()
m.io.in0 := in0
m.io.in1 := in1
m.io.out
}
}
With this change, it looks like the code works!
didn't read all your code, but I think the Mux2 arguments are in the wrong order here:
Mux2(io.sel(0), io.in0, io.in1)

Using type parameters in scala

I'm attempting to convert a stack of Strings into a generic Stack .
Here is the Stack of String implementation :
class LinkedStackOfStrings {
var first : Node = _
def isEmpty : Boolean = {
first == null
}
def push(itemName : String) = {
val oldFirst = first
first = new Node(itemName , oldFirst)
}
def pop = {
first = first.next
first.itemName
}
}
class Node(val itemName : String , val next : Node) {}
Here is my Stack of Generic types implementation :
class LinkedStackGeneric[T] {
var first : NodeGeneric[T] = _
def isEmpty : Boolean = {
first == null
}
def push(itemName : T) = {
val oldFirst = first
first = new NodeGeneric(itemName , oldFirst)
}
def pop = {
first = first.next
first.itemName
}
}
class NodeGeneric[T](val itemName : T , val next : NodeGeneric[T]) {}
When I attempt to initialse my new generic class with data :
val generic = new LinkedStackGeneric
generic.push("test")
I receive this syntax error :
type mismatch; found : String("test") required: Nothing
What am I doing wrong ? Since I'm using a type parameter should I not be able to add data of any type including String to method 'push' ?
You can fix this issue by making the Stack object immutable:
object ImmutableStack {
trait ImmutableStack[+A] {
def isEmpty: Boolean
def push[B >: A](item: B): ImmutableStack[B] = new <<(this, item)
def pop: (ImmutableStack[A], Option[A])
def <<[B >: A](item: B) = push(item)
}
case class <<[+A](init: ImmutableStack[A], last: A) extends ImmutableStack[A] {
override def isEmpty = false
override def pop: (ImmutableStack[A], Option[A]) = (init, Some(last))
override def toString = "" + init + " << " + last
}
case object Nst extends ImmutableStack[Nothing] {
override def isEmpty = true
override def pop = (Nst, None)
override def toString = "Nst"
}
}
Then we have:
scala> import ImmutableStack._
import ImmutableStack._
scala> val intStack = Nst << 5 << 4 << 3 << 2 << 1
intStack: ImmutableStack.ImmutableStack[Int] = Nst << 5 << 4 << 3 << 2 << 1
scala> intStack.pop
res0: (ImmutableStack.ImmutableStack[Int], Option[Int]) = (Nst << 5 << 4 << 3 << 2,Some(1))
scala> val firstItems << lastItem = intStack
firstItems: ImmutableStack.ImmutableStack[Int] = Nst << 5 << 4 << 3 << 2
lastItem: Int = 1
scala> val strStack = Nst << "A" << "B" << "C"
strStack: ImmutableStack.ImmutableStack[String] = Nst << A << B << C
scala> val fs << lt = strStack
fs: ImmutableStack.ImmutableStack[String] = Nst << A << B
lt: String = C
scala> val anyStack = Nst << 1 << "Str" << 'Z'
anyStack: ImmutableStack.ImmutableStack[Any] = Nst << 1 << Str << Z
scala> val st << x1 << x2 << x3 = anyStack
st: ImmutableStack.ImmutableStack[Any] = Nst
x1: Any = 1
x2: Any = Str
x3: Any = Z
At first glance I wouldn't expect what you're trying to work.
The type inference has no basis for inferring the type when you instantiate the object. It's not smart enough to see that on the next line you push a String. As a result, you have to do this:
val generic = new LinkedStackGeneric[String]
generic.push("test")
I'd love to be proven wrong.
Scala's type inference engine is notorious for inferring Nothing in cases like yours. To put it briefly, Scala's type hierarchy has both a top (Any) and a bottom (Nothing) that all other types must exist between. All types have a super-type of Any, and Nothing is a common sub-type to all types.
What does this mean for you? Well, when you instantiate your LinkedStackGeneric instance, you omit any type for the type parameter T. This indicates to Scala that it needs to infer the type (as, being a statically typed language, it must determine a type for everything at compile time). In this case, Scala's type inference engine picks poorly (from a user expectation perspective), and selects the bottom type (Nothing) as the type of the parameter T. With this in place, where you go to add your value "test", the Scala compiler (rightly) complains that String cannot be added to a LinkedStackGeneric[Nothing], as even though all Nothings are Strings, not all (or perhaps not any) Strings are Nothings.
A few more notes for the curious. Nothing is actually what is called an uninhabited type, meaning that there can never be an instance of type Nothing. So, even though I said not all Strings are Nothings, it is in fact impossible for a String to be a Nothing.

Grabbing process stderr in scala

When using the scala 2.9 process API, I can do things like
"ls -l"!
which will send the process stdout and stderr into my own.
Or:
val output = "ls -1"!!
which will return whatever was sent to stdout into the val output.
How can I similarly grab stderr?
You can create your own ProcessLogger:
import sys.process._
val logger = ProcessLogger(
(o: String) => println("out " + o),
(e: String) => println("err " + e))
scala> "ls" ! logger
out bin
out doc
out lib
out meta
out misc
out src
res15: Int = 0
scala> "ls -e" ! logger
err ls: invalid option -- e
err Try `ls --help' for more information.
res16: Int = 2
Edit: The previous example simply prints, but it could easily store the output in some structure:
val out = new StringBuilder
val err = new StringBuilder
val logger = ProcessLogger(
(o: String) => out.append(o),
(e: String) => err.append(e))
scala> "ls" ! logger
res22: Int = 0
scala> out
res23: StringBuilder = bindoclibmetamiscsrc
scala> "ls -e" ! logger
res27: Int = 2
scala> out
res28: StringBuilder =
scala> err
res29: StringBuilder = ls: invalid option -- eTry `ls --help' for more information.