joe 发表于 2021-10-18 16:40:59

rocketchip高级参数化机制--新版本Config调试实验(11)

以前的Config是低版本rocket chip中的代码,现在用新版本做实验:
1)源码:
/**
* @Author Joe_Liang
* @Date 2021/10/18 15:16
* @Version 1.0
*/
// See LICENSE.SiFive for license details.

package freechips.rocketchip.config

abstract class Field[T] private (val default: Option[T])
{
def this() = this(None)
def this(default: T) = this(Some(default))
}

abstract class View {
final def apply[T](pname: Field[T]): T = apply(pname, this)
final def apply[T](pname: Field[T], site: View): T = {
    val out = find(pname, site)
    require (out.isDefined, s"Key ${pname} is not defined in Parameters")
    out.get
}

final def lift[T](pname: Field[T]): Option[T] = lift(pname, this)
final def lift[T](pname: Field[T], site: View): Option[T] = find(pname, site).map(_.asInstanceOf[T])

protected def find[T](pname: Field[T], site: View): Option[T]
}

abstract class Parameters extends View {
final def ++ (x: Parameters): Parameters =
    new ChainParameters(this, x)

final def alter(f: (View, View, View) => PartialFunction[Any,Any]): Parameters =
    Parameters(f) ++ this
final def alterPartial(f: PartialFunction[Any,Any]): Parameters =
    Parameters((_,_,_) => f) ++ this
final def alterMap(m: Map[Any,Any]): Parameters =
    new MapParameters(m) ++ this
protected def chain[T](site: View, tail: View, pname: Field[T]): Option[T]
protected def find[T](pname: Field[T], site: View) = chain(site, new TerminalView, pname)
}

object Parameters {
def empty: Parameters = new EmptyParameters
def apply(f: (View, View, View) => PartialFunction[Any,Any]): Parameters = new PartialParameters(f)
}

class Config(p: Parameters) extends Parameters {
def this(f: (View, View, View) => PartialFunction[Any,Any]) = this(Parameters(f))

protected def chain[T](site: View, tail: View, pname: Field[T]) = p.chain(site, tail, pname)
override def toString = this.getClass.getSimpleName
def toInstance = this
}

// Internal implementation:

private class TerminalView extends View {
def find[T](pname: Field[T], site: View): Option[T] = pname.default
}

private class ChainView(head: Parameters, tail: View) extends View {
def find[T](pname: Field[T], site: View) = head.chain(site, tail, pname)
}

private class ChainParameters(x: Parameters, y: Parameters) extends Parameters {
def chain[T](site: View, tail: View, pname: Field[T]) = x.chain(site, new ChainView(y, tail), pname)
}

private class EmptyParameters extends Parameters {
def chain[T](site: View, tail: View, pname: Field[T]) = tail.find(pname, site)
}

private class PartialParameters(f: (View, View, View) => PartialFunction[Any,Any]) extends Parameters {
protected def chain[T](site: View, tail: View, pname: Field[T]) = {
    val g = f(site, this, tail)
    if (g.isDefinedAt(pname)) Some(g.apply(pname).asInstanceOf[T]) else tail.find(pname, site)
}
}

private class MapParameters(map: Map[Any, Any]) extends Parameters {
protected def chain[T](site: View, tail: View, pname: Field[T]) = {
    val g = map.get(pname)
    if (g.isDefined) Some(g.get.asInstanceOf[T]) else tail.find(pname, site)
}
}

2)实验代码:
import freechips.rocketchip.config.{Config, Field, Parameters}

/**
* @Author Joe_Liang
* @Date 2021/10/18 15:18
* @Version 1.0
*/
case object BUSWIDTH extends Field[Int]
case object CHIPNAME extends Field[String]
case class cc(s:String)
case object co
class MyConfig extends Config((v1,v2,v3)=>{
case BUSWIDTH => 32
case CHIPNAME => "RISC-V"
})
class MyModule(implicit p:Parameters) {
val buswidth:Int = p(BUSWIDTH)
val chipname:String = p(CHIPNAME)
println(buswidth)
println(chipname)


}
object Main {
def main(args: Array[String]): Unit = {
    implicit val params = new MyConfig
    val mm = new MyModule
}
}


joe 发表于 2021-10-19 11:11:44

针对新版本Config源码,因为用了很多scala的语法糖,不是很好理解,我采用step方式一步一步分析,基本上只要看懂我下面的step分析,risc-v的参数配置就能一步到位:
1)implicit val params = new MyConfig
2)class MyConfig extends Config(f:(v1,v2,v3)=>{case BUSWIDTH=>...}
class Config(p:Parameters) extends Parameters{
3)        def this(f:(View,View,View)=>PartialFunction)=this(Parameters(f))       
}
object Parameters {
        //注意:本第4步返回的是一个PartialParameters,一直到第16步执行完,说明Config的主构造参数p是一个PartialParameters
        //因为将来用p(BUSWIDTH)搜索配置值的时候,第29步中会用到Config的主构造参数p.chain,这将会调PartialParameters.chain
4)        def apply(f:(View,View,View)=>PartialFunction):Parameters = new PartialParameters(f)
}
5)private class PartialParameters(f:(View,View,View)=>PartialFunction) 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(p: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(p:Parameters) extends Parameters
16)再回到3(因为从12开始到15,就是为了用Config的主构造器(参数为PartialParameters(f))进行初始化)
17)再回到2
18)再回到1
19)val mm = new MyModule
20) class MyModule(implicit p:Parameters){
21)                val buswidth:Int = p(BUSWIDTH)        //Parametrs中无这种带Field的apply,只有其父类View中有
}
abstract class View{ //其实总的目标就是当用户用p(BUSWIDTH)即调用p:Parameters的apply方法时就开始搜索Field
22)        final def apply(pname:Field):T=apply(pname,this) //此时this是MyConfig,pname是BUSWIDTH,T是Int
        final def apply(pname:Field,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 def chain(site:View,tail:View,pname:Field):Option
        //下句中chain本来应该调用本类的chain方法,但因本Parameters类中chain是抽象方法,
        //所以跳到子类Config中,当然因为有new TerminalView,所以先要去newTerminalView
24)        protected def find(pname:Field,site:View):Option=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(p:Parametrs) extends Parameters {
        //p.chain下步将如何调用呢?根据第4步中注释分析,p的实际类型是PartialParameters,可知会调用PartialParameters.chain
29)        protected def chain(site:View,tail:View,pname:Field):Option=p.chain(site,tail,pname)
}
private class PartialParameters(f:(View,View,View)=>PartialFunction) extends Parameters {
        //site是MyConfig,tail是TerminalView,pname是BUSWIDTH
        protected def chain(site:View,tail:View,pname:Field):Option = {
                //如何查找呢?先通过将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)
                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)
class MyConfig extends Config((v1,v2,v3)=>{
39)        case BUSWIDTH => 32 //本39步之后不会再象前面那样继续执行case CHIPNAME=>"RISC-V",因为此时不是isDefinedAt
})
40)再回到Some(g.apply(pname).asInstanceOf)
41)回到protected def chain(site:View,tail:View,pname:Field):Option
42)再回到class Config中的protected def chain(site:View,tail:View,pname:Field):Option
        = p.chain(site,tail,pname)即29步
43)再回到abstract class Parameters extends View中的def find(pname:Field,site:View):Option=
        p.chain(site,new TerminalView,pname)即24步
abstract class View {
47)        final def apply(pname:Field):T = apply(pname,this)
        final def apply(pname:Field,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 p:Parameters) {
48)        val buswidth:Int = p(BUSWIDTH)
49)        val chipname:String = p(CHIPNAME) //chipname参数配置分析和BUSWIDTH一样,省略       
        println(buswidth)
        println(chipname)
}

页: [1]
查看完整版本: rocketchip高级参数化机制--新版本Config调试实验(11)