How to add each element of Vec? - chisel

For example, let's assume that I have following data:
class VectorElemAdd extends Module {
val io = IO (new Bundle {
val input = Input(Vec(64, UInt(64.W)))
val out = Output(UInt(64.W))
})
/*
if the vector data is : 0, 1, 2, 3, 4, 5, ..., 63,
I have to add each element : 0 + 1 + 2 + ... + 63 by indexing Vec,
for example : input(0) + input(1) + ... + input(63),
But, it needs kind of for loop to add all elements of Vec
and the final output(io.out) will be the input(0) + input(1) + ... +
input(63)
*/
The things that I need to do are described in the comment. Is it possible to such kind of operation easily?(for example, using for loop or whatever)

This particular problem is very easy to represent in Scala.
class VectorElemAdd extends Module {
val io = IO (new Bundle {
val input = Input(Vec(64, UInt(64.W)))
val out = Output(UInt(64.W))
})
io.out := io.input.reduce(_ + _)
}

Related

Generate dynamic bundle

In my project, I have many different custom Bundle.
They can be completely different.
For example these ones:
class MyBundle extends Bundle {
val v1 = UInt(8.W)
val v2 = Bool()
val v3 = UInt(4.W)
}
class MyBundle2 extends Bundle {
val v4 = UInt(18.W)
val v5 = UInt(2.W)
}
...
Instead of manually creating new Bundle to perform each operation, I want to be able to generate for all of them the corresponding Bundle.
So for MyBundle, I want to do:
// Must be generated for each Bundle
class MyGenBundle extends Bundle {
val v1 = UInt(log2Ceil(8 + 1).W) // width = MyBundle.v1 width + 1
val v2 = UInt(log2Ceil(1 + 1).W) // width = MyBundle.v2 width + 1
val v3 = UInt(log2Ceil(4 + 1).W) // width = MyBundle.v3 width + 1
}
class MyModule extends Module {
...
...
val w_b = Wire(new MyBundle())
val w_gb = Wire(new MyGenBundle())
// Must be automated for each Bundle
w_gb.v1 := PopCount(w_b.v1)
w_gb.v2 := PopCount(w_b.v2)
w_gb.v3 := PopCount(w_b.v3)
}
My goal is to automatically generate MyGenBundle (or similar directly in MyModule) from MyBundle, and perform in MyModule the same operation to all signals.
It also means that I need to dynamically address all signals in each Bundle.
Finally, I think the solution can have the following form:
val w_b = Wire(new MyBundle())
val w_gb = Wire(new AutoGenBundle(new MyBundle())) // AutoGenBundle generates a Bundle from parameter
val v_sig = Seq(v1, v1, v3) // Can be recovered automatically
// from w_b.elements I think
foreach (s <- v_sig) {
w_gb."s" := PopCount(w_b."s") // Here "s" the dynamic name of the signal
} // But how in the real case ?
Is this working technically possible in Chisel/Scala?
If so, do you have any ideas for implementing it?
Basic solution is to use the MixedVec chisel type for GenericBundle
class MyBundle extends Bundle {
val v1 = UInt(8.W)
val v2 = Bool()
val v3 = UInt(4.W)
}
class GenericBundle[T <: Bundle](data: T) extends Bundle {
val v = MixedVec(data.elements.values.map(x => UInt(log2Ceil(x.getWidth + 1).W)).toList)
def popCount(data: T): Unit = {
data.elements.values.zip(v).foreach { case (left, right) =>
right := PopCount(left.asUInt())
}
}
}
class MyModule extends MultiIOModule {
val w_b = IO(Input(new MyBundle))
val w_gb = IO(Output(new GenericBundle(w_b)))
w_gb.popCount(w_b)
}

test rocket chip util 'Arbiters.scala', got error 'bits operated ... must be hardware ..."

I copied a rocket-chip util module 'Arbiters.scala' to a separate work directory, test with the following code:
object try_arbiter extends App {
chisel3.Driver.execute(args, () => new HellaCountingArbiter(UInt(4.W), 3, 5))
}
There's no problem when compiling. However, in the step 'Elaborating design...', it reported [error] chisel3.core.Binding$ExpectedHardwareException: mux condition 'chisel3.core.Bool#46' must be hardware, not a bare Chisel type"
The related code is
PriorityEncoder(io.in.map(_.valid))
when I change this line to the following one, the error's gone (the scala code still has this kind of errs, but not in this line).
PriorityEncoder(io.in.map(x => Wire(x.valid)))
The rocket chip codes should have been evaluated for many times, right? I think there must have sth I have missed... Some configurations?
Thank you for any hints!
Appendix(the Arbiters.scala):
package rocket_examples
import chisel3._
import chisel3.util._
/** A generalized locking RR arbiter that addresses the limitations of the
* version in the Chisel standard library */
abstract class HellaLockingArbiter[T <: Data](typ: T, arbN: Int, rr: Boolean = false)
extends Module {
val io = new Bundle {
val in = Vec(arbN, Decoupled(typ.cloneType)).flip
val out = Decoupled(typ.cloneType)
}
def rotateLeft[T <: Data](norm: Vec[T], rot: UInt): Vec[T] = {
val n = norm.size
Vec.tabulate(n) { i =>
Mux(rot < UInt(n - i), norm(UInt(i) + rot), norm(rot - UInt(n - i)))
}
}
val lockIdx = Reg(init = UInt(0, log2Up(arbN)))
val locked = Reg(init = Bool(false))
val choice = if (rr) {
PriorityMux(
rotateLeft(Vec(io.in.map(_.valid)), lockIdx + UInt(1)),
rotateLeft(Vec((0 until arbN).map(UInt(_))), lockIdx + UInt(1)))
} else {
PriorityEncoder(io.in.map(_.valid))
}
val chosen = Mux(locked, lockIdx, choice)
for (i <- 0 until arbN) {
io.in(i).ready := io.out.ready && chosen === UInt(i)
}
io.out.valid := io.in(chosen).valid
io.out.bits := io.in(chosen).bits
}
/** This locking arbiter determines when it is safe to unlock
* by peeking at the data */
class HellaPeekingArbiter[T <: Data](
typ: T, arbN: Int,
canUnlock: T => Bool,
needsLock: Option[T => Bool] = None,
rr: Boolean = false)
extends HellaLockingArbiter(typ, arbN, rr) {
def realNeedsLock(data: T): Bool =
needsLock.map(_(data)).getOrElse(Bool(true))
when (io.out.fire()) {
when (!locked && realNeedsLock(io.out.bits)) {
lockIdx := choice
locked := Bool(true)
}
// the unlock statement takes precedent
when (canUnlock(io.out.bits)) {
locked := Bool(false)
}
}
}
/** This arbiter determines when it is safe to unlock by counting transactions */
class HellaCountingArbiter[T <: Data](
typ: T, arbN: Int, count: Int,
val needsLock: Option[T => Bool] = None,
rr: Boolean = false)
extends HellaLockingArbiter(typ, arbN, rr) {
def realNeedsLock(data: T): Bool =
needsLock.map(_(data)).getOrElse(Bool(true))
// if count is 1, you should use a non-locking arbiter
require(count > 1, "CountingArbiter cannot have count <= 1")
val lock_ctr = Counter(count)
when (io.out.fire()) {
when (!locked && realNeedsLock(io.out.bits)) {
lockIdx := choice
locked := Bool(true)
lock_ctr.inc()
}
when (locked) {
when (lock_ctr.inc()) { locked := Bool(false) }
}
}
}
The issue is that almost all of the code in rocket-chip has been written against older Chisel2-style APIs and should be compiled with the compatibility wrapper import Chisel._. I see you used import chisel3._ which has somewhat stricter semantics.
For this specific case, the difference between Chisel2 and Chisel3 is that ports (val io) must be wrapped in IO(...), ie.
val io = IO(new Bundle {
val in = Flipped(Vec(arbN, Decoupled(typ)))
val out = Decoupled(typ)
})
Note that I also changed Vec(arbN, Decoupled(typ.cloneType)).flip to Flipped(Vec(arbN, Decoupled(typ))) and removed the .cloneType on val out. The latter two changes are not required for this to compile but they will be flagged as deprecation warnings as of Chisel 3.1.2.

Using ScalaCheck with PeekPokeTester

Here is chisel3 test that uses ScalaCheck to perform property checking on a simple combinational circuit.
package stackoverflow
import org.scalatest.{ Matchers, FlatSpec, GivenWhenThen}
import org.scalacheck.{ Properties, Gen, Arbitrary}
import org.scalacheck.Prop.{ forAll, AnyOperators, collect}
import chisel3._
import firrtl_interpreter.InterpretiveTester
object G {
val width = 8
}
class Add extends Module {
val io = IO(new Bundle {
val a = Input(UInt(G.width.W))
val b = Input(UInt(G.width.W))
val o = Output(UInt(G.width.W))
})
io.o := io.a + io.b
}
class AddTester {
val s = chisel3.Driver.emit( () => new Add)
val tester = new InterpretiveTester( s)
def run( a : Int, b : Int) = {
val result = (a + b) & ((1 << G.width)-1)
tester.poke( s"io_a", a)
tester.poke( s"io_b", b)
tester.peek( s"io_o") ?= result
}
}
object AddTest extends Properties("Add") {
val t = new AddTester
val gen = Gen.choose(0,(1 << G.width)-1)
property("Add") = forAll( gen, gen) {
case (a:Int,b:Int) => t.run( a, b)
}
}
This uses the firrtl interpreter directly. Does anyone know how to do something similar using the PeekPokeTester so I can use the verilator and vcs backends as well?
Is this close to what you have in mind? It's a lot more scalatesty in form. I haven't been able to get the gen stuff working here (there is some kind of weird interaction with chisel), and I'm more familiar with FreeSpec so I started with it. I also threw a printf and a println in so you could believe it was working. This works with the interpreter backend as well.
import org.scalatest.FreeSpec
import org.scalacheck.Prop.AnyOperators
import chisel3._
import chisel3.iotesters.PeekPokeTester
class Add2 extends Module {
val io = IO(new Bundle {
val a = Input(UInt(G.width.W))
val b = Input(UInt(G.width.W))
val o = Output(UInt(G.width.W))
})
io.o := io.a + io.b
printf("%d = %d + %d\n", io.o, io.a, io.b)
}
class ScalaTestyTester extends FreeSpec {
"scalatest verilator test" in {
iotesters.Driver.execute(Array("--backend-name", "verilator"), () => new Add2) { c =>
new PeekPokeTester(c) {
for(_ <- 0 until 10) {
val a = BigInt(G.width, scala.util.Random)
val b = BigInt(G.width, scala.util.Random)
println(s"testing a = $a b = $b")
val result = (a + b) & ((1 << G.width) - 1)
poke(c.io.a, a)
poke(c.io.b, b)
step(1)
peek(c.io.o) ?= result
}
}
}
}
}

How to store sequence of JsValue into a ArrayBuffer

I have the following json object what contain a list of json objects. Each of these objects contain informations about a station object.
"stations": [
{
"cryptName": "Tv_Gara Nord 1",
"easyName": "Gara de Nord",
"lat": 45.750287,
"lng": 21.207498
},
{
"cryptName": "Tv_R Carol 1",
"easyName": "Regele Carol I",
"lat": 45.745068,
"lng": 21.211034
},
{
"cryptName": "Tv_Mocioni 1",
"easyName": "Piata Mocioni (Sinaia)",
"lat": 45.746343,
"lng": 21.21551
}]
I've tried this and I am unable to convert this to a ArrayBuffer with format:
ArrayBuffer(List("cryptName", "easyName", "lat", "lng"), ...)
[Line 73 .. 77] The problem is with (js \\\ "cryptName")(0) ... (js \\\ "lng")(0).
How to store correctly all of these stations not a single one into my ArrayBuffer?
package backend
import scala.concurrent.duration._
import scala.collection.immutable.Seq
import scala.concurrent.forkjoin.ThreadLocalRandom
import akka.actor.{ ActorRef, Props }
import play.api.libs.json.Json
import play.extras.geojson.{ LineString, LatLng, FeatureCollection }
import play.api.Logger
import actors.GeoJsonBot
import java.net.URL
import akka.actor.Actor
import scala.io.Source
import akka.cluster.Cluster
import play.api.libs.json.JsValue
import org.apache.commons.lang3.Validate
object BotManager
{
def props(regionManagerClient: ActorRef, data: Seq[URL]): Props = Props(new BotManager(regionManagerClient, data))
private case object Tick
}
/**
* Loads and starts GeoJSON bots
*/
class BotManager(regionManagerClient: ActorRef, data: Seq[URL]) extends Actor
{
import BotManager._
var total = 0
val max = Settings(context.system).TotalNumberOfBots
import context.dispatcher
val tickTask = context.system.scheduler.schedule(1.seconds, 3.seconds, self, Tick)
val port = Cluster(context.system).selfAddress.port.get
override def postStop(): Unit = tickTask.cancel()
def receive =
{
case Tick if total >= max => tickTask.cancel()
case Tick =>
val totalBefore = total
val originalTrail = total == 0
println("NODE: " + data)
data.zipWithIndex.foreach
{
case (url, id) =>
val json = Json.parse(Source.fromURL(url).mkString)
println("URL: " + url + "ID: " + id)
Json.fromJson[FeatureCollection[LatLng]](json).fold(
{
invalid =>
Logger.error("Error loading geojson bot: " + invalid)
}, valid => valid.features.zipWithIndex.map
{
feature => feature._1.geometry match
{
case route: LineString[LatLng] if total < max => total += 1
val userId = "bot-" + total + "-" + port + "-" + id + "-" + feature._1.id.getOrElse(feature._2) + "-" + feature._1.properties.flatMap(js => (js \ "name").asOpt[String]).getOrElse("") + feature._1.properties.flatMap(js => (js \ "segment").asOpt[String]).getOrElse("")
val stations = feature._1.properties.flatMap(js => (js \ "stations").asOpt[JsValue])
import play.api.libs.json.JsObject
import play.api.libs.json.JsArray
var stationss = feature._1.properties.flatMap(js => (js \ "stations").asOpt[JsValue])
val crypt = stationss.flatMap(js => (js \\ "cryptName")(0).asOpt[JsValue])
val ename = stationss.flatMap(js => (js \\ "easyName")(0).asOpt[JsValue])
val lat = stationss.flatMap(js => (js \\ "lat")(0).asOpt[JsValue])
val lng = stationss.flatMap(js => (js \\ "lng")(0).asOpt[JsValue])
case class Station(cryptName: String, easyName: String, lat: Float, lng: Float)
implicit val readsStation = Json.reads[Station]
case class Stations(stations: List[Station])
implicit val readsStations = Json.reads[Stations]
val stations = Json.parse(text).as[Stations].stations.map(s => List(s.cryptName, s.easyName, s.lat, s.lng)).to[ArrayBuffer]
println("List: [" + crypt.get + ", " + ename.get + ", " + lat.get + ", " + lng.get + "]")
val offset =
if (originalTrail) (0.0, 0.0)
else (ThreadLocalRandom.current.nextDouble() * 15.0,
ThreadLocalRandom.current.nextDouble() * -30.0)
context.actorOf(GeoJsonBot.props(route, stations, offset, userId, regionManagerClient))
case other =>
}
})
}
println("Started " + (total - totalBefore) + " bots, total " + total)
}
}
I'd do it like this:
case class Station(cryptName: String, easyName: String, lat: Float, lng: Float)
implicit val readsStation = Json.reads[Station]
case class Stations(stations: List[Station])
implicit val readsStations = Json.reads[Stations]
(assuming JSON is { stations: [ ... ] })
Then use the following:
val stations = Json.parse(text).as[Stations].stations
.map(s => List(s.cryptName, s.easyName, s.lat, s.lng)).to[ArrayBuffer])
which'll produce the following (given your sample):
ArrayBuffer(List(Tv_Gara Nord 1, Gara de Nord, 45.750286, 21.207499), List(Tv_R Carol 1, Regele Carol I, 45.745068, 21.211035), List(Tv_Mocioni 1, Piata Mocioni (Sinaia), 45.74634, 21.21551))
Use Reads\Writes macro.
Create case classes, something like,
case class Station(cryptName: String, easyName: String, lat: String, long: String)
case class Stations(stations: Seq[Station])
Create reads,
import play.api.libs.json._
import play.api.libs.functional.syntax._
implicit val stationReads = Json.reads[Station]
implicit val stationsReads = Json.reads[Stations]
And do conversion,
val json: JsValue = Json.parse(jsonString)
Json.fromJson[Stations](json) match {
case JsSuccess(t, _) => ???
case any: JsError => ???
}
Go through read/write combinators and read/write macros

Customizing JSON serialization in Play

I'm using renderJSON(Object) to return some objects as JSON values, and it's working fine except for one field. Is there an easy way to add in that one field without having to manually create the whole json template?
Play uses GSON to build the JSON string. If your one field is a specific object type, then you can easily do this by providing a customised serialisation for that type. See the documentation here
http://sites.google.com/site/gson/gson-user-guide#TOC-Custom-Serialization-and-Deserializ
However, if it is an Integer class for example, that you want to work in one way for one, and another way for another, then you may have a little more difficulty.
Example
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(SpecificClass.class, new MySerializer());
private class MySerializer implements JsonSerializer<DateTime> {
public JsonElement serialize(SpecificClass src, Type typeOfSrc, JsonSerializationContext context) {
String res = "special format of specificClass"
return new JsonPrimitive(res);
}
}
Simply do a
JsonElement elem = new Gson().toJsonTree(yourObject);
JsonObject obj = elem.getAsJsonObject();
obj.remove("xxx");
obj.addProperty("xxx", "what you want");
// other stuff ...
renderJSON(obj.toString());
etc.
After evaluating the play framework we hit a stumbling block and decision choice on serializing JSON for an external API. Allot of articles out there suggest using the Lift framework within play which just seem like extra overhead.After trying some of the frameworks / modules with in the play framework a college and myself decided to write a light weight code block that could cater for our needs.
case class User (
user_id: Int,
user_name: Option[String],
password: Option[String],
salt: Option[String]
) extends Serializable {
def toXml =
<user>
<user_id>{user_id}</user_id>
<user_name>{user_name.getOrElse("")}</user_name>
</user>
override def toJson =
"{" + JSON.key("user_id") + JSON.value(user_id) + ", " + JSON.key("user_name") + JSON.value(user_name) + "}"
}
class Serializable {
def toJson = ""
}
object JSON {
def key(x:String) = value(x) + ": "
def value(x:Any):String = {
x match {
case s:String => "\"" + s + "\""
case y:Some[String] => value(y.getOrElse(""))
case i:Int => value(i.toString)
case s:Serializable => s.toJson
case xs:List[Any] => "[" + xs.map(x => value(x)).reduceLeft(_ + ", " + _) + "]"
}
}
}
def searchUserByName(user_name: String) = {
(for (
u <- Users if u.user_name.like(("%"+user_name+"%").bind)
) yield u.*)
.list
.map(User.tupled(_))
}
def toXml(users:List[User]) = {
<users>
{ users.map(u => u.toXml) }
</users>
}
def toJson(users:List[User]) = {
"[" + users.map(u => u.toJson).reduceLeft(_ + ", " + _) + "]"
}
And from the controller.
// -- http://localhost:9000/api/users/getUser/xml
// -- http://localhost:9000/api/users/getUser/json
def getUser(requestType:String) = {
db withSession{
val user = Users.byUserName("King.Kong")
if(requestType == "xml") {
Xml(user.toXml)
} else {
user.toJson
}
}
}
//--- http://localhost:9000/api/users/searchuser/xml
//--- http://localhost:9000/api/users/searchuser/json
def searchUser(requestType:String) = {
db withSession{
val users = Users.searchUserByName("Doctor.Spoc")
if(requestType == "xml") {
Xml(Users.toXml(users))
} else {
val jsonList = Users.toJson(users)
Json(jsonList)
}
}