下面的 chisel 语句是如何解码的?
How is the following chisel statement decoded?
我正在学习 SonicBoom。下面这句要根据解码table来分配对应的解码信号
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
}
}
但是我想知道这一步是如何实现的。 sigs zip decoder map {case(s,d) => s := d}
这个代码是什么意思?
Zip 和 map 似乎是 Vec 中的函数。我试着查看了它的官方手册。
https://www.chisel-lang.org/api/latest/chisel3/index.html?search=zip这本手册是我见过最难的手册
他只给出了如下解释:
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
我完全看不懂说明书在说什么?我再次检查了 Chisel 的书。这两个功能目前还没有介绍。有人可以介绍一下吗?非常感谢!
zip
是一个 standard Scala method。它以 2 元组(值对)的序列将两个序列连接在一起。想想夹克拉链。
map
也是一个standard scala method。它对序列的每个成员应用一个函数。
这里给map的函数是case(s,d) => s := d
这个函数使用模式匹配得到两个元组成员s
和d
。
该函数返回的值是d
到s
的赋值(连接):s := d
.
为了更好地理解Chisel,我认为我们必须先了解一点Scala。
我没有尝试编译它,老实说,我对 Chisel 的作用只有很模糊的理解,所以这只是一个有根据的猜测:
sigs
是上面那行定义的序列Seq(legal, fp_val, ..., csr_cmd)
decoder
也是一些实体的序列,可以出现在 :=
. 的右侧
zip
对 sigs
和 decoder
序列元素,即 [s1, s2, s3, ..., sN]
和 [d1, d2, d3, ..., dN]
被压缩成一个序列对 [(s1, d1), (s2, d2), ..., (sN, dN)]
.
map
遍历序列,并对每一对做一些事情。由于结果未使用,我认为它实际上应该是 foreach
.
case
将对解构为第一和第二部分 s
和 d
s := d
以某种方式将 s
和 d
连接在一起(如果您正在使用 Chisel,您可能比我更了解 :=
的含义)
它可以用for-yield
重写:
for ((s, d) <- sigs.zip(decoder))
yield s := d
但由于结果未被使用,它可能被写成
sigs.zip(decoder).foreach { case (s, d) => s := d }
或使用相应的 for
-语法:
for ((s, d) <- sigs.zip(decoder)) {
s := d
}
关于手动输入:这是一个非常典型的 Scala 集合库签名。泛型参数堆是一种类型级别的规范,可确保 returned 集合的类型“尽可能精确”。这样做的好处是可以为一大堆集合编写泛型方法,而不必 return 千篇一律 - List
无处不在。不幸的是,这也使得新手无法破译签名。
这是签名:
def zip[A1 >: T, B, That](that: GenIterable[B])(implicit bf: CanBuildFrom[IndexedSeq[T], (A1, B), That]): That
以下是您阅读这些签名的方式:
- 找出所有只出现在
implicit
参数中的类型变量。在这种情况下,这些将是 A1
和 That
.
- 识别出现在return类型中的所有类型变量。在本例中,它是
That
.
现在:
- 如果类型变量只出现在
implicit
参数的类型中,而不出现在return类型中,那么只需忽略它们:this只是一种为最合适的隐式参数指定搜索 space 的方法。您可以忽略它们,除非您是试图将您的馆藏插入标准馆藏库的图书馆作者。认为这是不相关的图书馆作者到图书馆作者的闲聊。
- 如果某些类型变量
X
同时出现在 implicit
参数的类型和 return 类型中,那么你可以假设它是“最好的 X
你能想到的。
应用于此签名:
T
是你原始向量的元素类型
B
是第一个参数的元素类型(您正在压缩的集合)
A1
只出现在隐式参数的类型中:忽略它。
That
出现在隐式参数和 return 类型中:假设它是“最佳可能的集合类型”。
总而言之,它给你:
- 您从一个元素类型为
T
的向量开始
- 您正在使用
B
类型的元素序列对其进行压缩
- 您可以假设
That
将是最精确类型的集合,类似于 Vec[(T, B)]
或至少 IndexedSeq[(T, B)]
。它是什么并不重要,因为无论如何你都在调用 foreach
。
更一般地说,这个想法是您可以简单地依赖类型推断,并假设它会在任何地方找出最合适的结果类型。
我正在学习 SonicBoom。下面这句要根据解码table来分配对应的解码信号
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
}
}
但是我想知道这一步是如何实现的。 sigs zip decoder map {case(s,d) => s := d}
这个代码是什么意思?
Zip 和 map 似乎是 Vec 中的函数。我试着查看了它的官方手册。
https://www.chisel-lang.org/api/latest/chisel3/index.html?search=zip这本手册是我见过最难的手册
他只给出了如下解释:
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
我完全看不懂说明书在说什么?我再次检查了 Chisel 的书。这两个功能目前还没有介绍。有人可以介绍一下吗?非常感谢!
zip
是一个 standard Scala method。它以 2 元组(值对)的序列将两个序列连接在一起。想想夹克拉链。
map
也是一个standard scala method。它对序列的每个成员应用一个函数。
这里给map的函数是case(s,d) => s := d
这个函数使用模式匹配得到两个元组成员s
和d
。
该函数返回的值是d
到s
的赋值(连接):s := d
.
为了更好地理解Chisel,我认为我们必须先了解一点Scala。
我没有尝试编译它,老实说,我对 Chisel 的作用只有很模糊的理解,所以这只是一个有根据的猜测:
sigs
是上面那行定义的序列Seq(legal, fp_val, ..., csr_cmd)
decoder
也是一些实体的序列,可以出现在:=
. 的右侧
zip
对sigs
和decoder
序列元素,即[s1, s2, s3, ..., sN]
和[d1, d2, d3, ..., dN]
被压缩成一个序列对[(s1, d1), (s2, d2), ..., (sN, dN)]
.map
遍历序列,并对每一对做一些事情。由于结果未使用,我认为它实际上应该是foreach
.case
将对解构为第一和第二部分s
和d
s := d
以某种方式将s
和d
连接在一起(如果您正在使用 Chisel,您可能比我更了解:=
的含义)
它可以用for-yield
重写:
for ((s, d) <- sigs.zip(decoder))
yield s := d
但由于结果未被使用,它可能被写成
sigs.zip(decoder).foreach { case (s, d) => s := d }
或使用相应的 for
-语法:
for ((s, d) <- sigs.zip(decoder)) {
s := d
}
关于手动输入:这是一个非常典型的 Scala 集合库签名。泛型参数堆是一种类型级别的规范,可确保 returned 集合的类型“尽可能精确”。这样做的好处是可以为一大堆集合编写泛型方法,而不必 return 千篇一律 - List
无处不在。不幸的是,这也使得新手无法破译签名。
这是签名:
def zip[A1 >: T, B, That](that: GenIterable[B])(implicit bf: CanBuildFrom[IndexedSeq[T], (A1, B), That]): That
以下是您阅读这些签名的方式:
- 找出所有只出现在
implicit
参数中的类型变量。在这种情况下,这些将是A1
和That
. - 识别出现在return类型中的所有类型变量。在本例中,它是
That
.
现在:
- 如果类型变量只出现在
implicit
参数的类型中,而不出现在return类型中,那么只需忽略它们:this只是一种为最合适的隐式参数指定搜索 space 的方法。您可以忽略它们,除非您是试图将您的馆藏插入标准馆藏库的图书馆作者。认为这是不相关的图书馆作者到图书馆作者的闲聊。 - 如果某些类型变量
X
同时出现在implicit
参数的类型和 return 类型中,那么你可以假设它是“最好的X
你能想到的。
应用于此签名:
T
是你原始向量的元素类型B
是第一个参数的元素类型(您正在压缩的集合)A1
只出现在隐式参数的类型中:忽略它。That
出现在隐式参数和 return 类型中:假设它是“最佳可能的集合类型”。
总而言之,它给你:
- 您从一个元素类型为
T
的向量开始
- 您正在使用
B
类型的元素序列对其进行压缩
- 您可以假设
That
将是最精确类型的集合,类似于Vec[(T, B)]
或至少IndexedSeq[(T, B)]
。它是什么并不重要,因为无论如何你都在调用foreach
。
更一般地说,这个想法是您可以简单地依赖类型推断,并假设它会在任何地方找出最合适的结果类型。