Add longnail merge and schedule
This commit is contained in:
73
coreDatasheets/VexRiscv.yaml
Normal file
73
coreDatasheets/VexRiscv.yaml
Normal file
@@ -0,0 +1,73 @@
|
||||
# VexRiscv
|
||||
- operation: RdCustReg
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
- operation: WrCustReg.addr
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 1
|
||||
- operation: WrCustReg.data
|
||||
earliest: 1
|
||||
latency: 1
|
||||
costly: 2
|
||||
- operation: RdRS1
|
||||
earliest: 2
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: RdRS2
|
||||
earliest: 2
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: WrRD
|
||||
earliest: 2
|
||||
latency: 1
|
||||
costly: 3
|
||||
- operation: RdPC
|
||||
earliest: 1
|
||||
latency: 0
|
||||
costly: 4
|
||||
- operation: WrPC
|
||||
earliest: 0
|
||||
latency: 0
|
||||
costly: 1
|
||||
- operation: RdMem
|
||||
earliest: 2
|
||||
latency: 1
|
||||
costly: 3
|
||||
- operation: WrMem
|
||||
earliest: 2
|
||||
latency: 1
|
||||
costly: 3
|
||||
- operation: RdIValid
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: RdInstr
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: RdStall
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: WrStall
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: RdFlush
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
||||
- operation: WrFlush
|
||||
earliest: 1
|
||||
latency: 0
|
||||
latest: 3
|
||||
costly: 4
|
@@ -0,0 +1,11 @@
|
||||
package com.minres.tgc.hammer
|
||||
|
||||
import os.*
|
||||
|
||||
object FileUtils {
|
||||
def changeExtension(path: os.Path, newExt: String): os.Path = {
|
||||
val baseName = path.baseName
|
||||
val newName = s"$baseName.$newExt"
|
||||
path / os.up / newName
|
||||
}
|
||||
}
|
@@ -7,4 +7,7 @@ object Global {
|
||||
lazy val HAMMER: Path = pathFromEnv("TGC_HAMMER_HOME").get
|
||||
lazy val WORKDIR: Path = pathFromEnv("TGC_HAMMER_WORKDIR").get
|
||||
lazy val TREENAIL: Path = HAMMER / "deps" / "treenail"
|
||||
lazy val LONGNAIL: Path = HAMMER / "deps" / "longnail"
|
||||
lazy val BASE_DIR: Path = Path(Main.conf.baseDirectory(), os.pwd)
|
||||
lazy val CORE_DATASHEETS: Path = HAMMER / "coreDatasheets"
|
||||
}
|
||||
|
@@ -2,9 +2,13 @@ package com.minres.tgc.hammer
|
||||
|
||||
import com.minres.tgc.hammer.cli.{HammerConf, MySubcommand}
|
||||
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
object Main {
|
||||
var conf: HammerConf = uninitialized
|
||||
|
||||
def main(args: Array[String]): Unit = {
|
||||
val conf = new HammerConf(args.toIndexedSeq)
|
||||
conf = new HammerConf(args.toIndexedSeq)
|
||||
|
||||
conf.subcommand match {
|
||||
case Some(c: MySubcommand) =>
|
||||
|
@@ -0,0 +1,10 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
import com.minres.tgc.hammer.Global.CORE_DATASHEETS
|
||||
import org.rogach.scallop.*
|
||||
|
||||
trait CoreSelection { this: MySubcommand =>
|
||||
val core: ScallopOption[String] = opt[String](group = mainGroup)
|
||||
|
||||
def getCoreDatasheet: os.Path = CORE_DATASHEETS / s"$core.yaml"
|
||||
}
|
@@ -1,9 +1,25 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
import org.rogach.scallop.ScallopConf
|
||||
import com.minres.tgc.hammer.Global
|
||||
import org.rogach.scallop.{ScallopConf, ScallopOption, ValueConverter, fileConverter, listArgConverter, singleArgConverter}
|
||||
import os.Path
|
||||
|
||||
import java.io.File
|
||||
|
||||
class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) {
|
||||
val baseDirectory: ScallopOption[File] = opt[File](default = Some(os.pwd.toIO))
|
||||
addSubcommand(new TreenailCommand)
|
||||
addSubcommand(new LongnailSchedCommand)
|
||||
|
||||
validateFileIsDirectory(baseDirectory)
|
||||
|
||||
verify()
|
||||
}
|
||||
|
||||
implicit val osPathConverter: ValueConverter[os.Path] = {
|
||||
singleArgConverter[os.Path](os.Path(_, Global.BASE_DIR))
|
||||
}
|
||||
|
||||
implicit val osPathListConverter: ValueConverter[List[os.Path]] = {
|
||||
listArgConverter[os.Path](os.Path(_, Global.BASE_DIR))
|
||||
}
|
||||
|
@@ -0,0 +1,5 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
class LongnailHLSCommand {
|
||||
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
class LongnailMergeCommand {
|
||||
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
import com.minres.tgc.hammer.FileUtils.changeExtension
|
||||
import com.minres.tgc.hammer.tasks.longnail.{LongnailMergeTask, LongnailScheduleTask}
|
||||
import com.minres.tgc.hammer.tasks.{Task, TreenailTask}
|
||||
import com.minres.tgc.hammer.tasks.longnail.SchedulingParameters
|
||||
import org.rogach.scallop.ScallopOption
|
||||
import os.Path
|
||||
|
||||
class LongnailSchedCommand extends MySubcommand("scheduleISAX") with CoreSelection {
|
||||
val inputFiles: ScallopOption[List[Path]] = trailArg[List[Path]]("inputFiles", group = mainGroup)
|
||||
val outputDirectory: ScallopOption[Path] = opt[Path](group = mainGroup)
|
||||
val schedParams: SchedulingParameters = addOptionGroup(new SchedulingParameters)
|
||||
|
||||
validateOSPathIsDirectory(outputDirectory)
|
||||
|
||||
override def getRequiredTasks: Seq[Task] = {
|
||||
val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc")
|
||||
val treenailTasks = coreDSLFiles.map(i => TreenailTask(i, changeExtension(i, "mlir")))
|
||||
val allMlirFiles = mlirFiles ++ treenailTasks.map(_.output)
|
||||
if (allMlirFiles.size == 1) {
|
||||
treenailTasks :+ LongnailScheduleTask(allMlirFiles.head, getCoreDatasheet, schedParams)
|
||||
} else {
|
||||
val mergedInput = outputDirectory() / "merged.mlir"
|
||||
val concatInput = outputDirectory() / "concat.mlir"
|
||||
treenailTasks :+ LongnailMergeTask(allMlirFiles, concatInput, mergedInput) :+ LongnailScheduleTask(mergedInput, getCoreDatasheet, schedParams)
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,8 +1,30 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
import com.minres.tgc.hammer.options.{BaseOption, OptionGroup}
|
||||
import com.minres.tgc.hammer.tasks.Task
|
||||
import org.rogach.scallop.Subcommand
|
||||
import org.rogach.scallop.{ScallopOption, ScallopOptionGroup, Subcommand, Util}
|
||||
|
||||
import java.nio.file.{Files, Path}
|
||||
|
||||
abstract class MySubcommand(name: String) extends Subcommand(name) {
|
||||
protected val mainGroup: ScallopOptionGroup = group()
|
||||
|
||||
def getRequiredTasks: Seq[Task]
|
||||
|
||||
def addOptions(options: Seq[BaseOption[?]]): Unit = {
|
||||
options.foreach(_.init(this, null))
|
||||
}
|
||||
def addOptionGroup[T <: OptionGroup](group: T): T = {
|
||||
group.init(this)
|
||||
group
|
||||
}
|
||||
|
||||
def validateOSPathIsDirectory(pathOption: ScallopOption[os.Path]): Unit = addValidation {
|
||||
pathOption.toOption
|
||||
.map {
|
||||
case path if Files.isDirectory(path.toNIO) => Right(())
|
||||
case path => Left(Util.format("File '%s' is not a directory", path))
|
||||
}
|
||||
.getOrElse(Right(()))
|
||||
}
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
package com.minres.tgc.hammer.cli
|
||||
|
||||
import com.minres.tgc.hammer.Global
|
||||
import com.minres.tgc.hammer.tasks.{Task, TreenailTask}
|
||||
import org.rogach.scallop.*
|
||||
|
||||
@@ -8,12 +9,13 @@ import os.Path
|
||||
|
||||
class TreenailCommand extends MySubcommand("parseCoreDSL") {
|
||||
val coreDSL: ScallopOption[File] = trailArg[File]("coreDSL")
|
||||
val output: ScallopOption[File] = opt[File](short = 'o', default = Some(new File("isax.mlir")))
|
||||
val output: ScallopOption[Path] = opt[Path](short = 'o', default = Some(os.Path("isax.mlir", Global.BASE_DIR)))
|
||||
|
||||
validateFileExists(coreDSL)
|
||||
validateFileIsFile(coreDSL)
|
||||
|
||||
override def getRequiredTasks: Seq[Task] = Seq(
|
||||
override def getRequiredTasks: Seq[Task] = {
|
||||
Seq(
|
||||
new TreenailTask(Path(coreDSL(), os.pwd), Path(output(), os.pwd))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,20 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
import os.Shellable
|
||||
|
||||
import scala.compiletime.uninitialized
|
||||
|
||||
trait BaseOption[T](using conv: ValueConverter[T]) {
|
||||
protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[T]
|
||||
private var scallop: ScallopOption[T] = uninitialized
|
||||
def init(scallopConf: ScallopConf, group: ScallopOptionGroup): Unit = scallop = createScallop(scallopConf, group)
|
||||
|
||||
def get: T = scallop()
|
||||
def apply: T = get
|
||||
|
||||
def getToolParameters: Seq[Shellable] = Seq(s"--$toolName", getToolArg)
|
||||
|
||||
def toolName: String
|
||||
def getToolArg: String = get.toString
|
||||
}
|
@@ -0,0 +1,12 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
|
||||
enum Color:
|
||||
case Red, Green, Blue
|
||||
|
||||
class ChoiceOption(choices: Seq[String], cliName: String, val toolName: String, descr: String, default: => Option[String], required: Boolean, cliShort: Char) extends BaseOption[String] {
|
||||
override protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[String] = {
|
||||
conf.choice(choices, name = cliName, short = cliShort, descr = descr, default = default, required = required, group = group)
|
||||
}
|
||||
}
|
@@ -0,0 +1,38 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
|
||||
import org.rogach.scallop.{ScallopConf, ValueConverter}
|
||||
import os.Shellable
|
||||
|
||||
import scala.collection.mutable
|
||||
|
||||
export com.minres.tgc.hammer.cli.osPathConverter
|
||||
|
||||
trait OptionGroup {
|
||||
def name: String
|
||||
private val options = mutable.ListBuffer[BaseOption[?]]()
|
||||
protected def add[T <: BaseOption[?]](option: T): T = {
|
||||
options += option
|
||||
option
|
||||
}
|
||||
|
||||
def getToolParameters: Seq[Shellable] = options.toSeq.flatMap(_.getToolParameters)
|
||||
|
||||
def init(scallopConf: ScallopConf): Unit = {
|
||||
val group = scallopConf.group(name)
|
||||
options.foreach(_.init(scallopConf, group))
|
||||
}
|
||||
def value[T](cliName: String, toolName: String, descr: String = "", default: => Option[T] = None, required: Boolean = false, cliShort: Char = '\u0000')(using conv: ValueConverter[T]): ValueOption[T] = add(ValueOption(cliName, toolName, descr, default, required, cliShort))
|
||||
def valueS[T](name: String, descr: String = "", default: => Option[T] = None, required: Boolean = false, cliShort: Char = '\u0000')(using conv: ValueConverter[T]): ValueOption[T] = add(ValueOption(name, name, descr, default, required, cliShort))
|
||||
|
||||
def trail[T](toolName: String, descr: String = "", default: => Option[T] = None, required: Boolean = false)(using conv: ValueConverter[T]): TrailOption[T] = add(TrailOption(toolName, descr, default, required))
|
||||
|
||||
def choice(choices: Seq[String], cliName: String, toolName: String, descr: String = "", default: => Option[String] = None, required: Boolean = false, cliShort: Char = '\u0000'): ChoiceOption = add(ChoiceOption(choices, cliName, toolName, descr, default, required, cliShort))
|
||||
def choiceS(choices: Seq[String], name: String, descr: String = "", default: => Option[String] = None, required: Boolean = false, cliShort: Char = '\u0000'): ChoiceOption = add(ChoiceOption(choices, name, name, descr, default, required, cliShort))
|
||||
|
||||
def tally(cliName: String, toolName: String, descr: String = "", required: Boolean = false, cliShort: Char = '\u0000'): TallyOption = add(TallyOption(cliName, toolName, descr, required, cliShort))
|
||||
def tallyS(name: String, descr: String = "", required: Boolean = false, cliShort: Char = '\u0000'): TallyOption = add(TallyOption(name, name, descr, required, cliShort))
|
||||
|
||||
def toggle(cliName: String, toolName: String, descr: String = "", default: => Option[Boolean] = None, required: Boolean = false, cliShort: Char = '\u0000'): ToggleOption = add(ToggleOption(cliName, toolName, descr, default, required, cliShort))
|
||||
def toggleS(name: String, descr: String = "", default: => Option[Boolean] = None, required: Boolean = false, cliShort: Char = '\u0000'): ToggleOption = add(ToggleOption(name, name, descr, default, required, cliShort))
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
|
||||
class TallyOption(cliName: String, val toolName: String, descr: String, required: Boolean, cliShort: Char) extends BaseOption[Int] {
|
||||
override protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[Int] = {
|
||||
conf.tally(name = cliName, short = cliShort, descr = descr, group = group)
|
||||
}
|
||||
}
|
@@ -0,0 +1,10 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
|
||||
class ToggleOption(cliName: String, val toolName: String, descr: String, default: => Option[Boolean], required: Boolean, cliShort: Char) extends BaseOption[Boolean] {
|
||||
|
||||
override protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[Boolean] = {
|
||||
conf.toggle(name = cliName, short = cliShort, descrYes = descr, default = default, required = required, group = group)
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
|
||||
class TrailOption[T](val toolName: String, descr: String, default: => Option[T], required: Boolean)(using conv: ValueConverter[T]) extends BaseOption[T] {
|
||||
override protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[T] = {
|
||||
conf.trailArg[T](descr = descr, default = default, required = required, group = group)
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package com.minres.tgc.hammer.options
|
||||
|
||||
import org.rogach.scallop.*
|
||||
|
||||
class ValueOption[T](cliName: String, val toolName: String, descr: String, default: => Option[T], required: Boolean, cliShort: Char)(using conv: ValueConverter[T]) extends BaseOption[T] {
|
||||
override protected def createScallop(conf: ScallopConf, group: ScallopOptionGroup): ScallopOption[T] = {
|
||||
conf.opt[T](name = cliName, short = cliShort, descr = descr, default = default, required = required, group = group)
|
||||
}
|
||||
}
|
@@ -4,7 +4,7 @@ import com.minres.tgc.hammer.Global
|
||||
|
||||
import os.*
|
||||
|
||||
class TreenailTask(coreDSLInput: Path, output: Path) extends Task {
|
||||
case class TreenailTask(coreDSLInput: Path, output: Path) extends Task {
|
||||
private val EXECUTABLE = Global.TREENAIL / "app" / "build" / "install" / "app" / "bin" / "app"
|
||||
|
||||
override def validate(): Unit = {
|
||||
|
@@ -0,0 +1,14 @@
|
||||
package com.minres.tgc.hammer.tasks.longnail
|
||||
|
||||
import com.minres.tgc.hammer.Global
|
||||
import com.minres.tgc.hammer.options.*
|
||||
import com.minres.tgc.hammer.tasks.Task
|
||||
import os.{Path, isFile}
|
||||
|
||||
trait LongnailBaseTask extends Task {
|
||||
protected val EXECUTABLE: os.Path = Global.LONGNAIL / "build" / "bin" / "longnail-opt"
|
||||
|
||||
override def validate(): Unit = {
|
||||
assert(isFile(EXECUTABLE), "Treenail Executable is missing, build Treenail")
|
||||
}
|
||||
}
|
@@ -0,0 +1,29 @@
|
||||
package com.minres.tgc.hammer.tasks.longnail
|
||||
|
||||
import os.Path
|
||||
|
||||
class LongnailHLSTask(schedulingFile: Option[Path], outDirectory: Path) extends LongnailBaseTask {
|
||||
override def validate(): Unit = {
|
||||
super.validate()
|
||||
}
|
||||
|
||||
override def execute(): Unit = {
|
||||
runExecutable(EXECUTABLE,
|
||||
"--lower-lil-to-hw",
|
||||
schedulingFile match {
|
||||
case Some(value) => s"--solutionSelection $value"
|
||||
case None => "--forceUseMinIISolution=true"
|
||||
},
|
||||
"--simplify-structure",
|
||||
"--cse",
|
||||
"--canonicalize",
|
||||
"--print-stats",
|
||||
"--lower-seq-to-sv",
|
||||
"--hw-cleanup",
|
||||
"--prettify-verilog",
|
||||
"--hw-legalize-modules",
|
||||
"--export-split-verilog",
|
||||
"--dir-name", outDirectory
|
||||
)
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package com.minres.tgc.hammer.tasks.longnail
|
||||
|
||||
import os.Path
|
||||
|
||||
class LongnailMergeTask(mlirFiles: Seq[Path], concatMLIR: Path, mergedMLIR: Path) extends LongnailBaseTask {
|
||||
override def validate(): Unit = {
|
||||
super.validate()
|
||||
}
|
||||
|
||||
override def execute(): Unit = {
|
||||
// Concatenate Input files
|
||||
os.write(concatMLIR, mlirFiles.map(os.read))
|
||||
|
||||
// Run Longnail for merge
|
||||
runExecutable(EXECUTABLE,
|
||||
"--merge-multiple-isaxes", concatMLIR,
|
||||
"-o", mergedMLIR
|
||||
)
|
||||
}
|
||||
}
|
@@ -0,0 +1,41 @@
|
||||
package com.minres.tgc.hammer.tasks.longnail
|
||||
|
||||
import com.minres.tgc.hammer.options.*
|
||||
import com.minres.tgc.hammer.tasks.longnail.LongnailBaseTask
|
||||
import os.Path
|
||||
|
||||
class LongnailScheduleTask(isaxMLIR: Path, coreDatasheet: Path, params: SchedulingParameters) extends LongnailBaseTask {
|
||||
|
||||
override def validate(): Unit = {
|
||||
super.validate()
|
||||
}
|
||||
|
||||
override def execute(): Unit = {
|
||||
/*runExecutable(EXECUTABLE,
|
||||
"--lower-coredsl-to-lil",
|
||||
"--max-unroll-factor", params.maxLoopUnrollFactor,
|
||||
"--schedule-lil",
|
||||
"--datasheet", params.base.coreDatasheet,
|
||||
"--library", params.base.cellLibrary,
|
||||
"--opTyLibrary", params.base.opTyLibrary,
|
||||
"--clockTime", params.base.clockPeriod,
|
||||
"--schedulingAlgo", params.base.schedulingAlgo,
|
||||
"--solver", params.base.ilpSolver,
|
||||
"--schedulingTimeout", params.schedulingTimeout,
|
||||
"--schedRefineTimeout", params.schedulingRefineTimeout,
|
||||
"--solSelKconfPath", params.schedulingKconf,
|
||||
"--verbose", params.base.verbose.toString,
|
||||
"-o", params.schedulingMLIR,
|
||||
isaxMLIR
|
||||
)*/
|
||||
runExecutable(EXECUTABLE,
|
||||
"--lower-coredsl-to-lil",
|
||||
"--schedule-lil",
|
||||
"--datasheet", coreDatasheet,
|
||||
params.getToolParameters,
|
||||
isaxMLIR
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -0,0 +1,21 @@
|
||||
package com.minres.tgc.hammer.tasks.longnail
|
||||
|
||||
import com.minres.tgc.hammer.options.*
|
||||
import os.Path
|
||||
import org.rogach.scallop.*
|
||||
|
||||
class SchedulingParameters extends OptionGroup {
|
||||
override def name: String = "Longnail Scheduling Args"
|
||||
|
||||
value[Int](cliName = "maxLoopUnrollFactor", toolName = "max-unroll-factor")
|
||||
valueS[Int](name = "schedulingTimeout")
|
||||
value[Int](cliName = "schedulingRefineTimeout", toolName = "schedRefineTimeout")
|
||||
value[Path](cliName = "schedulingKconf", toolName = "solSelKconfPath")
|
||||
value[Path](cliName = "schedulingMLIR", toolName = "o")
|
||||
choiceS(Seq("LEGACY", "MS", "PAMS", "PARAMS", "MI_MS", "MI_PAMS", "MI_PARAMS"), name = "schedulingAlgo", default = Some("LEGACY"))
|
||||
choice(Seq("CBC", "GLPK", "SCIP", "HIGHS", "GUROBI", "CPLEX", "XPRESS", "COPT"), cliName = "ilpSolver", toolName = "solver", default = Some("CBC"))
|
||||
toggle(cliName = "verboseSched", toolName = "verbose")
|
||||
valueS[Path](name = "opTyLibrary")
|
||||
value[Int](cliName = "clockPeriod", toolName = "clockTime")
|
||||
value[Path](cliName = "cellLibrary", toolName = "library")
|
||||
}
|
Reference in New Issue
Block a user