I am learning SonicBoom. The following sentence should be based on the decoding table to assign the corresponding decoding signal.
class CtrlSigs extends Bundle
{
val legal = Bool()
val fp_val = Bool()
val fp_single = Bool()
val uopc = UInt(UOPC_SZ.W)
val iq_type = UInt(IQT_SZ.W)
val fu_code = UInt(FUC_SZ.W)
val dst_type = UInt(2.W)
val rs1_type = UInt(2.W)
val rs2_type = UInt(2.W)
val frs3_en = Bool()
val imm_sel = UInt(IS_X.getWidth.W)
val uses_ldq = Bool()
val uses_stq = Bool()
val is_amo = Bool()
val is_fence = Bool()
val is_fencei = Bool()
val mem_cmd = UInt(freechips.rocketchip.rocket.M_SZ.W)
val wakeup_delay = UInt(2.W)
val bypassable = Bool()
val is_br = Bool()
val is_sys_pc2epc = Bool()
val inst_unique = Bool()
val flush_on_commit = Bool()
val csr_cmd = UInt(freechips.rocketchip.rocket.CSR.SZ.W)
val rocc = Bool()
def decode(inst: UInt, table: Iterable[(BitPat, List[BitPat])]) = {
val decoder = freechips.rocketchip.rocket.DecodeLogic(inst, XDecode.decode_default, table)
val sigs =
Seq(legal, fp_val, fp_single, uopc, iq_type, fu_code, dst_type, rs1_type,
rs2_type, frs3_en, imm_sel, uses_ldq, uses_stq, is_amo,
is_fence, is_fencei, mem_cmd, wakeup_delay, bypassable,
is_br, is_sys_pc2epc, inst_unique, flush_on_commit, csr_cmd)
sigs zip decoder map {case(s,d) => s := d}
rocc := false.B
this
}
}
But I want to know how this step is achieved. sigs zip decoder map {case(s,d) => s := d}
What does this code mean?
Zip and map seem to be functions within Vec. I tried to check its official manual.
https://www.chisel-lang.org/api/latest/chisel3/index.html?search=zip This manual is the most difficult manual I have ever seen.
He only gave the following explanation:
defzip[A1 >: T, B, That](that: GenIterable[B])(implicit bf: CanBuildFrom[IndexedSeq[T], (A1, B), That]): That
Definition Classes
IterableLike → GenIterableLike
defmap[B, That](f: (T) ⇒ B)(implicit bf: CanBuildFrom[IndexedSeq[T], B, That]): That
Definition Classes
TraversableLike → GenTraversableLike → FilterMonadic
I can't understand what the manual is saying at all? I checked Chisel's books again. There is still no introduction to these two functions. Can someone please introduce? Many thanks!
CodePudding user response:
zip
is a standard Scala method. It join two sequences together in a sequence of 2-Tuples (Couple of values). Think about jacket zipper.
map
is also a standard scala method. It apply a function to each membre of the sequence.
The function given to map here is case(s,d) => s := d
this function use pattern matching to get the two tuple members s
and d
.
The value returned by this function is an assignation (connection) of d
to s
: s := d
.
For better understanding of Chisel, I think that we must know a bit of Scala before.
CodePudding user response:
I have not attempted to compile it, and to be honest, I have only a vary vague understanding of what Chisel does at all, so this is just an educated guess:
sigs
is the sequenceSeq(legal, fp_val, ..., csr_cmd)
defined in the line abovedecoder
is also a sequence of some entities that can appear on the right hand side of:=
.zip
pairssigs
anddecoder
-sequences elementwise, i.e.[s1, s2, s3, ..., sN]
and[d1, d2, d3, ..., dN]
are zipped into a sequence of pairs[(s1, d1), (s2, d2), ..., (sN, dN)]
.map
goes through the sequence, and does something to each pair. Since the result is unused, I assume that it actually should have been aforeach
.case
deconstructs the pairs into first and second componentss
andd
s := d
somehow wires togethers
andd
(if you are working with Chisel, you probably know better than me what the:=
means)
It could have been rewritten with a for-yield
:
for ((s, d) <- sigs.zip(decoder))
yield s := d
but since the result is unused, it probably could have been written as
sigs.zip(decoder).foreach { case (s, d) => s := d }
or with the corresponding for
-syntax:
for ((s, d) <- sigs.zip(decoder)) {
s := d
}
Regarding the manual entry: that's a signature which is quite typical for Scala collection libraries. The pile of generic parameters is a type-level specification that ensures that the type of the returned collection is "as precise as possible". This has the advantage that one can write generic methods for a whole bunch of collections, without having to return one-size-fits-all-List
s everywhere. Unfortunately, this also makes the signatures undecipherable to the novices.
This is the signature:
def zip[A1 >: T, B, That](that: GenIterable[B])(implicit bf: CanBuildFrom[IndexedSeq[T], (A1, B), That]): That
Here is how you read those signatures:
- Identify all the type variables that occur only in the
implicit
parameters. In this case, those would beA1
andThat
. - Identify all the type variables that occur in the return type. In this case, it's the
That
.
Now:
- If a type variable occurs only in the type of the
implicit
parameters, but not in the return type, then simply ignore them: this is just a way to specify the search space for the most appropriate implicit argument. You can ignore them, unless you are a library author who is attempting to plug-in your collections into the standard collection library. Consider it to be irrelevant library-author-to-library-author chatter. - If some type variable
X
occurs both in the type of theimplicit
parameters and in the return type, then you can assume that it's "the best possibleX
you can think of".
Applied to this signature:
T
is the element type of your original vectorB
is the element type of the first argument (the collection you are zipping with)A1
occurs only in the type of the implicit parameter: ignore it.That
occurs in implicit parameter and in return type: assume it's "the best possible collection type".
All together, it gives you:
- You are starting with a vector with elements of type
T
- You are zipping it with a sequence of elements of type
B
- You can assume that
That
will be a collection of the most precise type, something likeVec[(T, B)]
or at leastIndexedSeq[(T, B)]
. What it is, doesn't really matter, because you are invokingforeach
on it anyway.
More generally, the idea would be that you can simply rely on the type inference, and assume that it will figure out the most appropriate result types everywhere.