实现一个查找逻辑。
参考链接:
1. Lookup
各个参数如下:
1) addr: 要查找对象的地址;
2) default: 若没有查到,则使用这个默认值返回;
3) mapping: BitPat与待查找对象的映射;可以理解为被查找对象的集合。
这里把参数转换之后,委托给ListLookup来查找。
Lookup查找的地址处,只有一个值;而ListLookup查找的地址处,有多个值。所以这里委托时,使用.head提取返回的第一个值,实际上也只有一个。
2. ListLookup
各个参数意义与Lookup相似,不同的在于ListLookup查找的地址处有多个值,所以传入了多个默认值。
1) 把mapping转换为是否匹配的映射:val map = mapping.map(m => (m._1 === addr, m._2))
m._1为BitPat,“===”为BitPat的匹配方法,m._1 === addr 返回一个是否匹配的Bool型,与m._2即List[T]一起组成一个新的map;
2) 逐个遍历每一个默认值:default.zipWithIndex map { case (d, i) => ...}
因为查找地址处有多个值(值的个数与传入的默认值的个数一致),所以需要逐个计算并返回。这个map返回的结果即是ListLookup返回的结果,即List[T]。
3)根据BitPat匹配的结果,返回查找到的值:map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n))
a. d为默认值;
b. m._2(i)返回查找地址处的多个值中的第i个;
c. 如果地址匹配,则返回查找到的值:Mux(m._1, m._2(i), n)
d. map.foldRight()()
foldRight有两个参数列表,第一个是初始值z,第二个是一个函数op。
fold的意思为折叠,即把map中所有的元素逐个带入op运算,最终返回一个结果。前一次运算的结果作为下一次运算的z值。第一次运算使用的z值为作为第一个参数列表传入的z。
foldRight从有开始算,foldLeft从左开始算。
在此例中:map.foldRight(d)((m, n) => Mux(m._1, m._2(i), n))
第一次运算:n = d, m = map(length - 1).
第二次运算:n为第一次运算中Mux选择的结果,m = map(length - 1 -1)
...
如此即形成一个查找结构,按map中元素的顺序开始查找,若元素0不匹配,再与元素1匹配,如此直到最后一个元素。如果最后一个元素的BitPat与addr也不匹配,则使用默认值d。
3. 附录