Skip to content

Commit

Permalink
UPF Generation [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
Sriram Sridhar authored and Sriram Sridhar committed Apr 26, 2023
1 parent 6d8680b commit ea2f093
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 1 deletion.
3 changes: 2 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,8 @@ lazy val rocketchip = freshProject("rocketchip", rocketChipDir)
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-reflect" % scalaVersion.value,
"org.json4s" %% "json4s-jackson" % "3.6.6",
"org.scalatest" %% "scalatest" % "3.2.0" % "test"
"org.scalatest" %% "scalatest" % "3.2.0" % "test",
"org.scala-graph" %% "graph-core" % "1.13.5"
)
)
.settings( // Settings for scalafix
Expand Down
1 change: 1 addition & 0 deletions common.mk
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ $(FIRRTL_FILE) $(ANNO_FILE) $(CHISEL_LOG_FILE) &: $(SCALA_SOURCES) $(SCALA_BUILD
--name $(long_name) \
--top-module $(MODEL_PACKAGE).$(MODEL) \
--legacy-configs $(CONFIG_PACKAGE):$(CONFIG) \
$(UPF_ASPECT) \
$(EXTRA_CHISEL_OPTIONS)) | tee $(CHISEL_LOG_FILE))

define mfc_extra_anno_contents
Expand Down
91 changes: 91 additions & 0 deletions generators/chipyard/src/main/scala/upf/ChipTopUPF.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// See LICENSE for license details
package chipyard.upf

import chipyard.TestHarness
import freechips.rocketchip.diplomacy.LazyModule

import scala.collection.mutable.ListBuffer

import scalax.collection.mutable.Graph
import scalax.collection.GraphPredef._, scalax.collection.GraphEdge._

object ChipTopUPF {

def default: UPFFunc.UPFFunction = {
case top: LazyModule => {
val modulesList = getLazyModules(top)
val pdList = createPowerDomains(modulesList)
val g = connectPDHierarchy(pdList)
traverseGraph(g, UPFGenerator.generateUPF)
}
}

def getLazyModules(top: LazyModule): ListBuffer[LazyModule] = {
var i = 0
var result = new ListBuffer[LazyModule]()
result.append(top)
while (i < result.length) {
val lazyMod = result(i)
for (child <- lazyMod.getChildren) {
result.append(child)
}
i += 1
}
return result
}

def createPowerDomains(modulesList: ListBuffer[LazyModule]): ListBuffer[PowerDomain] = {
var pdList = ListBuffer[PowerDomain]()
for (pdInput <- UPFInputs.upfInfo) {
val pd = new PowerDomain(name=pdInput.name, modules=getPDModules(pdInput, modulesList),
isTop=pdInput.isTop, isGated=pdInput.isGated,
highVoltage=pdInput.highVoltage, lowVoltage=pdInput.lowVoltage)
pdList.append(pd)
}
return pdList
}

def getPDModules(pdInput: PowerDomainInput, modulesList: ListBuffer[LazyModule]): ListBuffer[LazyModule] = {
var pdModules = ListBuffer[LazyModule]()
for (moduleName <- pdInput.moduleList) {
var module = modulesList.filter(_.module.name == moduleName)
if (module.length == 1) { // filter returns a collection
pdModules.append(module(0))
} else {
module = modulesList.filter(_.module.instanceName == moduleName)
if (module.length == 1) {
pdModules.append(module(0))
} else {
module = modulesList.filter(_.module.pathName == moduleName)
if (module.length == 1) {
pdModules.append(module(0))
} else {
throw new Exception(s"PowerDomainInput module list doesn't exist in design.")
}
}
}
}
return pdModules
}

def connectPDHierarchy(pdList: ListBuffer[PowerDomain]): Graph[PowerDomain, DiEdge] = {
var g = Graph[PowerDomain, DiEdge]()
for (pd <- pdList) {
val pdInput = UPFInputs.upfInfo.filter(_.name == pd.name)(0)
val childPDs = pdList.filter(x => pdInput.childrenPDs.contains(x.name))
for (childPD <- childPDs) {
g += (pd ~> childPD) // directed edge from pd to childPD
}
}
return g
}

def traverseGraph(g: Graph[PowerDomain, DiEdge], action: (PowerDomain, Graph[PowerDomain, DiEdge]) => Unit): Unit = {
for (node <- g.nodes.filter(_.diPredecessors.isEmpty)) { // all nodes without parents
g.outerNodeTraverser(node).foreach(pd => action(pd, g))
}
}

}

case object ChipTopUPFAspect extends UPFAspect[chipyard.TestHarness](ChipTopUPF.default)
24 changes: 24 additions & 0 deletions generators/chipyard/src/main/scala/upf/UPFAspect.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// See LICENSE for license details
package chipyard.upf

import chisel3.aop.Aspect
import firrtl.{AnnotationSeq}
import chipyard.TestHarness
import freechips.rocketchip.stage.phases.TargetDirKey

import freechips.rocketchip.diplomacy.LazyModule

abstract class UPFAspect[T <: TestHarness](upf: UPFFunc.UPFFunction) extends Aspect[T] {

final override def toAnnotation(top: T): AnnotationSeq = {
UPFFunc.UPFPath = top.p(TargetDirKey) + "/upf"
upf(top.lazyDut)
AnnotationSeq(Seq()) // noop
}

}

object UPFFunc {
type UPFFunction = PartialFunction[LazyModule, Unit]
var UPFPath = "" // output dir path
}
Loading

0 comments on commit ea2f093

Please sign in to comment.