|
楼主 |
发表于 2021-10-19 11:11:44
|
显示全部楼层
针对新版本Config源码,因为用了很多scala的语法糖,不是很好理解,我采用step方式一步一步分析,基本上只要看懂我下面的step分析,risc-v的参数配置就能一步到位:
1)implicit val params = new MyConfig
2)class MyConfig extends Config(fv1,v2,v3)=>{case BUSWIDTH=>...}
class Config(parameters) extends Parameters{
3) def this(fView,View,View)=>artialFunction[Any,Any])=this(Parameters(f))
}
object Parameters {
//注意:本第4步返回的是一个PartialParameters,一直到第16步执行完,说明Config的主构造参数p是一个PartialParameters
//因为将来用p(BUSWIDTH)搜索配置值的时候,第29步中会用到Config的主构造参数p.chain,这将会调PartialParameters.chain
4) def apply(fView,View,View)=>artialFunction[Any,Any])arameters = new PartialParameters(f)
}
5)private class PartialParameters(fView,View,View)=>artialFunction[Any,Any]) extends Parameters {..}
6)abstract class Parameters extends View{...}
7)abstract class View{...}
8)回到6
9)再回到5
10)再回到4
11)再加到3
12)因为this(Parameters(f))其实是调用的是主构造器,所以回到class Config(parameters) extends Parameters
13)因12步中调用了Config的主构造器,而Config又extends Parameters,所以再次进到abstract class Parameters extends View
也就是通常new子类时先要构造父类流程一样
14)再到abstract class View, 也是构造Parameters的父类View
15)回到abstract class Parameters extends View,再回到Config的主构造也就是第12步 class Config(parameters) extends Parameters
16)再回到3(因为从12开始到15,就是为了用Config的主构造器(参数为PartialParameters(f))进行初始化)
17)再回到2
18)再回到1
19)val mm = new MyModule
20) class MyModule(implicit parameters){
21) val buswidth:Int = p(BUSWIDTH) //Parametrs中无这种带Field[T]的apply,只有其父类View中有
}
abstract class View{ //其实总的目标就是当用户用p(BUSWIDTH)即调用parameters的apply方法时就开始搜索Field[T]
22) final def apply[T](pname:Field[T]):T=apply(pname,this) //此时this是MyConfig,pname是BUSWIDTH,T是Int
final def apply[T](pname:Field[T],site:View):T = { //site是MyConfig,pname是BUSWIDTH
23) val out = find(pname,site)//因为this是MyConfg,所以find先看MyConfg,发现只有MyConfig的父类
//Parametrs中有find的实现
}
}
abstract class Parametrs extends View {
protected[config] def chain[T](site:View,tail:View,pname:Field[T]):Option[T]
//下句中chain本来应该调用本类的chain方法,但因本Parameters类中chain是抽象方法,
//所以跳到子类Config中,当然因为有new TerminalView,所以先要去newTerminalView
24) protected[config] def find[T](pname:Field[T],site:View):Option[T]=chain(site,new TerminalView,pname)
}
25) private class TerminalView extends View{...}
26) abstract class View {..} //构造TerminalView的父类View
27)再回到25
28)再回到24,此时已构造好TerminalView,要跳到Config中chain
class Config(parametrs) extends Parameters {
//p.chain下步将如何调用呢?根据第4步中注释分析,p的实际类型是PartialParameters,可知会调用PartialParameters.chain
29) protected[config] def chain[T](site:View,tail:View,pname:Field[T]):Option[T]=p.chain(site,tail,pname)
}
private class PartialParameters(fView,View,View)=>artialFunction[Any,Any]) extends Parameters {
//site是MyConfig,tail是TerminalView,pname是BUSWIDTH
protected[config] def chain[T](site:View,tail:View,pname:Field[T]):Option[T] = {
//如何查找呢?先通过将site,tail,this吗?传给f,得到偏函数,然后再查偏函数的isDefinedAt,
//如果本MyConfig对参数有定义,则用PartialFunction的apply直接取值
//如果本MyConfig没有对参数进行定义呢?再从哪些类中搜索呢????
30) val g = f(site,this,tail)
//g.apply(pname)会调用MyConfig中的偏函数取值,需要将Any类型转为需要的T类型即BUSWIDTH类型
//如果MyConfig中无定义参数,则应该用tail.find继续搜索
if(g.isDefinedAt(pname))
Some(g.apply(pname).asInstanceOf[T])
else
tail.find(pname,site)
}
}
31) class MyConfig extends Config((v1,v2,v3)=>{ //本31步不是初始化类,而是进入(v1,v2,v3)=>{..},当然也不是进入函数体内
case BUSWIDTH => 32
})
32)回到30
33)执行30步的后面一句g.isDefinedAt(pname)
34)表面上看是会进入:
clss MyConfig extends Config((v1,v2,v3)=>{
35) case BUSWIDTH => 32
36) case CHIPNAME => "RISC-V"
})
其实是因为偏函数在编译时,编译器将各个case编译之后,还会针对每个case添加true,如果哪个case满足,那么
这种类型参数在用于isDefinedAt时就会返回true值,比如本例中g.isDefinedAt(BUSWIDTH),在偏函数中有case BUSWIDTH,
所以返回true,这样g.apply(pname)时就会返回用户的设置值32。所以35,36步其实是执行isDefinedAt
37)再回到g.isDefinedAt(pname)
38)Some(g.apply(pname).asInstanceOf[T])
class MyConfig extends Config((v1,v2,v3)=>{
39) case BUSWIDTH => 32 //本39步之后不会再象前面那样继续执行case CHIPNAME=>"RISC-V",因为此时不是isDefinedAt
})
40)再回到Some(g.apply(pname).asInstanceOf[T])
41)回到protected[config] def chain[T](site:View,tail:View,pname:Field[T]):Option[T]
42)再回到class Config中的protected[config] def chain[T](site:View,tail:View,pname:Field[T]):Option[T]
= p.chain(site,tail,pname)即29步
43)再回到abstract class Parameters extends View中的def find[T](pname:Field[T],site:View):Option[T]=
p.chain(site,new TerminalView,pname)即24步
abstract class View {
47) final def apply[T](pname:Field[T]):T = apply(pname,this)
final def apply[T](pname:Field[T],site:View):T = {
44) val out = find(pname,site) //out的值是Some(32)
45) require(out.isDefined,s"Key ${pname} is not defined in Parameters")
46) out.get //Option中取值
}
}
class MyModule(implicit parameters) {
48) val buswidth:Int = p(BUSWIDTH)
49) val chipname:String = p(CHIPNAME) //chipname参数配置分析和BUSWIDTH一样,省略
println(buswidth)
println(chipname)
}
|
|