risc-v中文社区

 找回密码
 立即注册
查看: 1418|回复: 1

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

[复制链接]

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
发表于 2021-10-18 16:40:59 | 显示全部楼层 |阅读模式
以前的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[config] 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[config] def chain[T](site: View, tail: View, pname: Field[T]): Option[T]
  protected[config] 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[config] 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[config] 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[config] 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 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
  }
}


回复

使用道具 举报

347

主题

564

帖子

2237

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2237
 楼主| 发表于 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)
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



Archiver|手机版|小黑屋|risc-v中文社区

GMT+8, 2024-4-24 03:17 , Processed in 0.018055 second(s), 17 queries .

risc-v中文社区论坛 官方网站

Copyright © 2018-2021, risc-v open source

快速回复 返回顶部 返回列表