How do I make an individual Rocket tile asynchronous to the rest of the system - chisel

I have a multicore rocket-chip system. However I'd like one of those rocket tiles to be asynchronous from the rest.
We're trying to do that with the following:
class WithTilesCrossing extends Config((site, here, up) => {
case RocketCrossingKey => site(RocketTilesKey).head.hartId match {
case 2 => up(RocketCrossingKey) map { r =>
r.copy(crossingType = AsynchronousCrossing(),
master = TileMasterPortParams())}
case _ => up(RocketCrossingKey) map { r =>
r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
master = TileMasterPortParams())}
}
})
So that is the hart with hartId = 2 should be async, the rest should be synchronous.
The above, when added to our config, doesn't appear to do anything.
However, if I use the WithAsynchronousRocketTiles from src/main/scala/subsystem/Config.scala then I get all of the tiles converted to async.
So, how would I do just a single tile?
Update based on Jack's suggestion:
Trying that code straight up gave:
[error] Config.scala:189:16: not found: value crossingType
[error] r.copy(crossingType = AsynchronousCrossing(),
[error] ^
[error] Config.scala:190:11: not found: value master
[error] master = TileMasterPortParams())
[error] ^
[error] Config.scala:192:16: not found: value crossingType
[error] r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
[error] ^
[error] Config.scala:193:11: not found: value master
[error] master = TileMasterPortParams())
[error] ^
[error] four errors found
Which is surprising. So I thought I might need to do the up() thing and tried this:
case RocketCrossingKey => site(RocketTilesKey).map { r =>
r.hartId match {
case 2 => up(RocketCrossingKey) map { k => k.copy(crossingType = AsynchronousCrossing(), master = TileMasterPortParams()) }
case _ => up(RocketCrossingKey) map { k => k.copy(crossingType = SynchronousCrossing(BufferParams(1)), master = TileMasterPortParams()) }
}
}
However that results in an elab error:
[error] Caused by: java.lang.ClassCastException: scala.collection.immutable.$colon$colon cannot be cast to freechips.rocketchip.subsystem.RocketCrossingParams
[error] at freechips.rocketchip.subsystem.HasRocketTiles.$anonfun$rocketTiles$1(RocketSubsystem.scala:41)
[error] at scala.collection.TraversableLike.$anonfun$map$1(TraversableLike.scala:234)
[error] at scala.collection.immutable.List.foreach(List.scala:389)
[error] at scala.collection.TraversableLike.map(TraversableLike.scala:234)
[error] at scala.collection.TraversableLike.map$(TraversableLike.scala:227)
[error] at scala.collection.immutable.List.map(List.scala:295)
[error] at freechips.rocketchip.subsystem.HasRocketTiles.$init$(RocketSubsystem.scala:41)
[error] at freechips.rocketchip.subsystem.RocketSubsystem.<init>(RocketSubsystem.scala:70)
So still stuck on how to modify this original RocketCrossingParams on a per-tile basis and return it.

Looking at the definition of RocketCrossingKey:
case object RocketCrossingKey extends Field[Seq[RocketCrossingParams]](List(RocketCrossingParams()))
You'll notice that the type is Seq[RocketCrossingParams]. This implies (although I may be wrong), that we have 1 RocketCrossingParams per tile. In your code snippet, you are only looking at the first of the this Seq (via .head) checking if it's hartId is equal to 2, and then if so, iterating on all of the RocketCrossingKeys and setting them to AsynchronousCrossing.
Try something like the following where we iterate on them and only replace the index for the one with hartId == 2:
case RocketCrossingKey => site(RocketTilesKey).map { r =>
if (r.hartId == 2) { // or you can match on it, whatever
r.copy(crossingType = AsynchronousCrossing(),
master = TileMasterPortParams())
} else {
r.copy(crossingType = SynchronousCrossing(BufferParams(1)),
master = TileMasterPortParams())
}
}
EDIT: I missed the fact that there is both RocketCrossingKey and RocketTilesKey
So the issue here is that there are two parallel Seqs of parameters:
RocketTilesKey which gives us RocketTileParams, 1 for each tile
RocketCrossingKey which gives us RocketCrossingParams, 1 for each tile OR if there's only 1, it applies to all
It's also possible that there is no RocketTileParams containing hartId == 2, so let's handle everything appropriately:
case RocketCrossingKey =>
val tileParams = site(RocketTilesKey)
val crossingParams = site(RocketCrossingKey)
// One might assume hartId 2 == index 2 but that may not be the case
// Also there may not even *be* a tile with hartId == 2
val indexOfHartId2: Option[Int] =
tileParams.zipWithIndex.collectFirst { case (r, idx) if r.hartId == 2 => idx }
indexOfHartId2.map { idx =>
// This duplicates logic from HasTiles.perTileOrGlobalSetting
// If there's only 1, it applies to all
val crossings = site(RocketCrossingKey) match {
case Seq(one) => List.fill(tileParams.size)(one)
case many => many
}
// Back to the original answer using the proper index for hartId == 2
crossings.zipWithIndex.map { case (c, i) =>
if (i == idx) { // or you can match on it, whatever
c.copy(crossingType = AsynchronousCrossing(),
master = TileMasterPortParams())
} else {
c.copy(crossingType = SynchronousCrossing(BufferParams(1)),
master = TileMasterPortParams())
}
}
}.getOrElse(crossingParams) // If we don't even have hardId == 2, return original value

Related

Cannot update or delete many in ReactiveMongo 0.16

I'm having some difficulty with delete.many and update.many using the new builders whilst trying to convert my previous version's (working) code into reactivemongo 0.16.5 ("org.reactivemongo" %% "play2-reactivemongo" % "0.16.5-play26", "org.reactivemongo" %% "reactivemongo-akkastream" % "0.16.5". As you'll see; I'm using this within the Play plugin so dealing with JSON (rather than BSON)
I'm going from the official documentation here. My errors are similar for both update & delete so I'll just post for update here to keep it trim.
Update command
def updateMany(collName: String)(quJsa: JsArray)(orderedBool: Boolean = false): Future[MultiBulkWriteResult] = {
lazy val updateBuilder = getCollection(collName).map(_.update(orderedBool))
quJsa.asOpt[Seq[JsObject]].map(
_.map(
x => x.as[MongoUpdateBuilder]
)
).map(
_.map(
x => updateBuilder.flatMap(
_.element(q = x.q, u = x.getSetUpdate, upsert = x.upsertBool, multi = x.multiBool)
)
)
).map(
x => Future.sequence(x)
).map(
_.flatMap(
x => updateBuilder.flatMap(
_.many(x)
)
)
).getOrElse(getMultiBulkWriteResultErrorF("input not recognised as jsarr"))
}
Custom update builder model
case class MongoUpdateBuilder(q: JsObject, u: JsObject, upsertBool: Boolean, multiBool: Boolean) {
def getSetUpdate = Json.obj("$set" -> u)
}
object MongoUpdateBuilder {
implicit val mongoUpdateBuilderFormat = Json.format[MongoUpdateBuilder]
}
Error container
def getMultiBulkWriteResultErrorF(errStr: String): Future[MultiBulkWriteResult] = {
val mbwr = MultiBulkWriteResult(
ok = false,
n = 0,
nModified = 0,
upserted = Seq(),
writeErrors = Seq(WriteError(index = 0, code = 404, errmsg = errStr)),
writeConcernError = None,
code = Some(404),
errmsg = Some(errStr),
totalN = 0
)
Future.successful(mbwr)
}
And the main issue:
no type parameters for method flatMap: (f: reactivemongo.play.json.collection
.JSONCollection#UpdateBuilder => scala.concurrent.Future[S])(implicit executor: scala.concurrent.ExecutionContext)scala.concurrent.Future[S] exist so that it can be applied to arguments (reactivemongo.play.json.collection.JSONCollection#UpdateBuilder => scala.concurrent.Future[_1.UpdateCommand.UpdateElement] forSome { val _1: reactivemongo.play.json.collection.J
SONCollection }) [error] --- because ---
[error] argument expression's type is not compatible with formal parameter type;
[error] found : reactivemongo.play.json.collection.JSONCollection#UpdateBuilder => scala.concurrent.Future[_1.UpdateCommand.UpdateElement] forSome { val _1: reactivemongo.play.jso
n.collection.JSONCollection }
[error] required: reactivemongo.play.json.collection.JSONCollection#UpdateBuilder => scala.concurrent.Future[?S]
[error] x => updateBuilder.flatMap(
So the issue seems to be this line - updateBuilder.flatMap. The Future cannot be flattened with these types (JSONCollection#UpdateBuilder & JSONCollection#UpdateCommand.UpdateElement). So I'm struggling with this one. Please reach out if you can see the issue here. Many thanks!

Exception patterns must be at the top level of a match case

This compiles:
let inputFile = open_in("test.txt");
let line = try(input_line(inputFile)) {
| End_of_file => "end of file"
};
print_endline(line);
But not this:
let inputFile = open_in("test.txt");
try(input_line(inputFile)) {
| line => print_endline(line)
| exception End_of_file => print_endline("end of file")
};
For the latter I get an error: "Exception patterns must be at the top level of a match case"
I'm confused because it seems like an identical pattern to the one in the docs (https://reasonml.github.io/docs/en/exception.html)
let theItem = "a";
let myItems = ["b","a","c"];
switch (List.find((i) => i === theItem, myItems)) {
| item => print_endline(item)
| exception Not_found => print_endline("No such item found!")
};
Which compiles without error.
Changing the order of the match cases, or removing the "exception" keyword, doesn't change the error.
What does this error mean? I'm not sure what "top level" means.
try is used with exception(s) handling similar to try/catch in JavaScript. In your case, you want to do pattern matching and also catch an exception (which reasonml allows), so you could just use switch.
let inputFile = open_in("test.txt");
switch(input_line(inputFile)) {
| line => print_endline(line)
| exception End_of_file => print_endline("end of file")
};

Correctly joining tables and interating over results using Slick 2.1.0

I'm maintaing an old legacy application on Slick 2.1.0. When writing one piece, I ran into trouble with joins and made a query per each row in a query with the intent of fixing it later, but forgot to add a //TODO
row.code.flatMap(code => Option(getBundlesForCollection(code))),
row.code.flatMap(c => Option(getPricesForCollection(c)))
We've hit some preformance issues as this data set grew, so I wanted to fix it and get it right, but I rememebred all the issues I ran into. Right now my Slick queries are really simple. They look like the following:
def pricesForCollection(collectionCode : String)(implicit session : SessionDef) =
prices.filter(_.collectionCode === collectionCode).run
So I looked back at the documentation and tried again to get a working join. If I do something like the following:
def getCollections(code : String)(implicit session: SessionDef) = {
for {
c <- collections.filter(_.code === code)
pc <- prices if c.code === pc.collectionCode
br <- collectionBundleRestrictions if c.code === br.collectionCode
} yield(c, pc, br).run
}
I get compile errors I totally don't understand:
[error] Possible causes: T in Table[T] does not match your * projection. Or you use an unsupported type in a Query (e.g. scala List).
[error] Required level: scala.slick.lifted.FlatShapeLevel
[error] Source type: com.example.db.CollectionsRow
[error] Unpacked type: T
[error] Packed type: G
[error] br <- collectionBundleRestrictions if c.code === br.collectionCode
[error] ^
I've seen examples where you specify every column name (which makes sense) so I tried the following:
def getNewCollection(code : String)(implicit session: SessionDef) = {
for {
c <- collections.filter(_.code === code)
pc <- prices if c.code === pc.collectionCode
br <- collectionBundleRestrictions if c.code === br.collectionCode
} yield(c.name, c.code,
pc.priceCode, pc.iptcCategory, br.bundleRestrictionId,
br.bundleRestrictionId).run
}
But then I get the following cryptic error at runtime:
[info] scala.slick.SlickException: No type for symbol s2 found for Ref s2
[info] at scala.slick.ast.Ref.nodeWithComputedType2(Node.scala:501) ~[slick_2.11-2.1.0.jar:na]
[info] at scala.slick.ast.Ref.nodeWithComputedType2(Node.scala:495) ~[slick_2.11-2.1.0.jar:na]
[info] at scala.slick.ast.Node$class.nodeWithComputedType(Node.scala:101) ~[slick_2.11-2.1.0.jar:na]
[info] at scala.slick.ast.Ref.nodeWithComputedType(Node.scala:495) ~[slick_2.11-2.1.0.jar:na]
There is a ton of documentation on how to make joins, but absoilutely none on iterating over the result set. How do I write and execute this join correctly?
Ideally I'd like a a tuple of (Collection,Seq[Prices],Seq[BundleRestrictions]), or something else that makes sense in a join process.

Using Future inside a View in play 2.3.2

I'm writing a Play 2.3.2 application.
In my controller I've an asynchronous method that calculate a Future[Option[(String, Int)]].
Because the calculation is slow I want to begin to create my view and when the computation is completed finish to construct the view.
In the same controller I've an action that call this method and load a view passing the results, like this:
def max = Action.async {
calculateMax.flatMap(result =>
Future{Ok(recommendationsystem.views.html.manager.statistics.max(result))
)
}
My max view is implemented like this:
#(max: scala.concurrent.Future[Option[(String, Int)]])
#import util._
#recommendationsystem.views.html.main("Max tag")(recommendationsystem.views.html.nav.navbar("statistics")) {
<h1>Most used tag</h1>
#max flatMap {result => result match {
case Some(x) => {
<p>
<ul>
<li>Tag: #x._1</li>
<li>Occurrencies: #x._2</li>
</ul>
</p>
}
case None => {
<p>No one tag present in the db</p>
}
}
}
<p> </p>
}
But this code don't compile, the compiler gives me the following compile errors:
[error] /Users/alberto/git/bdrim/modules/recommendation-system/app/recommendationsystem/views/manager/statistics/max.scala.html:8: ')' expected but 'case' found.
[error] case Some(x) => {
[error] ^
[error] /Users/alberto/git/bdrim/modules/recommendation-system/app/recommendationsystem/views/manager/statistics/max.scala.html:18: ')' expected but 'case' found.
[error] case None => {
[error] ^
[error] /Users/alberto/git/bdrim/modules/recommendation-system/app/recommendationsystem/views/manager/statistics/max.scala.html:26: ';' expected but ',' found.
[error] <p> </p>
[error] ^
[error] three errors found
[error] /Users/alberto/git/bdrim/modules/recommendation-system/target/scala-2.11/twirl/main/recommendationsystem/views/html/manager/statistics/max.template.scala:27: ')' expected but 'case' found.
[error] """),_display_(/*7.6*/max),format.raw/*7.9*/(""" """),format.raw/*7.10*/("""flatMap """),format.raw/*7.18*/("""{"""),format.raw/*7.19*/("""result => result match """),format.raw/*7.42*/("""{""")/*8.5*/case Some(x) =>/*8.20*/ {_display_(Seq[Any](format.raw/*8.22*/("""
[error] ^
[error] /Users/alberto/git/bdrim/modules/recommendation-system/target/scala-2.11/twirl/main/recommendationsystem/views/html/manager/statistics/max.template.scala:36: ')' expected but 'case' found.
[error] """)))}/*18.5*/case None =>/*18.17*/ {_display_(Seq[Any](format.raw/*18.19*/("""
[error] ^
[error] /Users/alberto/git/bdrim/modules/recommendation-system/target/scala-2.11/twirl/main/recommendationsystem/views/html/manager/statistics/max.template.scala:40: ';' expected but ',' found.
[error] """)))},format.raw/*23.5*/("""}"""),format.raw/*23.6*/("""
[error]
Seems that the view cannot see the Future type.
What's wrong??
The compilation errors here are from your twirl syntax, and not the Future. Twirl templates are very picky with spacing and new lines. The #max flatMap with the space is definitely going to break some things, because twirl doesn't know if it should print out max, or look for more code. It may be best to surround the whole block with #{ ... }.
Some of this is irrelevant though, because you should never be passing a Future to a view in the first place. The template isn't going to partially render and then fill in the Future value later. Wrapping recommendationsystem.views.html.manager.statistics.max in Future.apply essentially does nothing. The key thing to note here is that result isn't even a Future. Presuming that calculateMax returns Future[Option[(String, Int)]], when you call map, you're asynchronously operating on the Option[(String, Int)] result of that Future.
So your controller function should look like this:
def max = Action.async {
calculateMax.map(result =>
Ok(recommendationsystem.views.html.manager.statistics.max(result))
)
}
And your view something like this:
#(max: Option[(String, Int)])
#max match {
case Some(x) => {
...
}
case None => {
<p>No one tag present in the db</p>
}
}

MongoDB: How to deal with invalid ObjectIDs

Here below is my code to find a document by ObjectID:
def find(selector: JsValue, projection: Option[JsValue], sort: Option[JsValue],
page: Int, perPage: Int): Future[Seq[JsValue]] = {
var query = collection.genericQueryBuilder.query(selector).options(
QueryOpts(skipN = page * perPage)
)
projection.map(value => query = query.projection(value))
sort.map(value => query = query.sort(value.as[JsObject]))
// this is the line where the call crashes
query.cursor[JsValue].collect[Vector](perPage).transform(
success => success,
failure => failure match {
case e: LastError => DaoException(e.message, Some(DATABASE_ERROR))
}
)
}
Now let's suppose we invoke this method with an invalid ObjectID:
// ObjectId 53125e9c2004006d04b605abK is invalid (ends with a K)
find(Json.obj("_id" -> Json.obj("$oid" -> "53125e9c2004006d04b605abK")), None, None, 0, 25)
The call above causes the following exception when executing query.cursor[JsValue].collect[Vector](perPage) in the find method:
Caused by: java.util.NoSuchElementException: JsError.get
at play.api.libs.json.JsError.get(JsResult.scala:11) ~[play-json_2.10.jar:2.2.1]
at play.api.libs.json.JsError.get(JsResult.scala:10) ~[play-json_2.10.jar:2.2.1]
at play.modules.reactivemongo.json.collection.JSONGenericHandlers$StructureBufferWriter$.write(jsoncollection.scala:44) ~[play2-reactivemongo_2.10-0.10.2.jar:0.10.2]
at play.modules.reactivemongo.json.collection.JSONGenericHandlers$StructureBufferWriter$.write(jsoncollection.scala:42) ~[play2-reactivemongo_2.10-0.10.2.jar:0.10.2]
at reactivemongo.api.collections.GenericQueryBuilder$class.reactivemongo$api$collections$GenericQueryBuilder$$write(genericcollection.scala:323) ~[reactivemongo_2.10-0.10.0.jar:0.10.0]
at reactivemongo.api.collections.GenericQueryBuilder$class.cursor(genericcollection.scala:342) ~[reactivemongo_2.10-0.10.0.jar:0.10.0]
at play.modules.reactivemongo.json.collection.JSONQueryBuilder.cursor(jsoncollection.scala:110) ~[play2-reactivemongo_2.10-0.10.2.jar:0.10.2]
at reactivemongo.api.collections.GenericQueryBuilder$class.cursor(genericcollection.scala:331) ~[reactivemongo_2.10-0.10.0.jar:0.10.0]
at play.modules.reactivemongo.json.collection.JSONQueryBuilder.cursor(jsoncollection.scala:110) ~[play2-reactivemongo_2.10-0.10.2.jar:0.10.2]
at services.common.mongo.MongoDaoComponent$MongoDao$$anon$1.find(MongoDaoComponent.scala:249) ~[classes/:na]
... 25 common frames omitted
Any idea? Thanks.