Add Longnail complete command

This commit is contained in:
2025-10-02 18:23:31 +02:00
parent 69b63d93da
commit 47614ad47f
10 changed files with 97 additions and 18 deletions

View File

@@ -11,5 +11,6 @@ object Global {
lazy val LONGNAIL: Path = HAMMER / "deps" / "longnail" lazy val LONGNAIL: Path = HAMMER / "deps" / "longnail"
lazy val BASE_DIR: Path = os.pwd lazy val BASE_DIR: Path = os.pwd
lazy val OUT_DIR: Path = Main.conf.outputDirectory() lazy val OUT_DIR: Path = Main.conf.outputDirectory()
lazy val TMP_DIR: Path = OUT_DIR / "tmp"
lazy val CORE_DATASHEETS: Path = HAMMER / "coreDatasheets" lazy val CORE_DATASHEETS: Path = HAMMER / "coreDatasheets"
} }

View File

@@ -6,6 +6,7 @@ import com.minres.tgc.hammer.FileUtils.*
class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) { class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) {
val outputDirectory: ScallopOption[Path] = opt[Path](default = Some("output".path()), descr = "The base output directory") val outputDirectory: ScallopOption[Path] = opt[Path](default = Some("output".path()), descr = "The base output directory")
addSubcommand(new LongnailCommand)
addSubcommand(new TreenailCommand) addSubcommand(new TreenailCommand)
addSubcommand(new LongnailSchedCommand) addSubcommand(new LongnailSchedCommand)

View File

@@ -0,0 +1,44 @@
package com.minres.tgc.hammer.cli
import com.minres.tgc.hammer.FileUtils.*
import com.minres.tgc.hammer.Global.*
import com.minres.tgc.hammer.tasks.{Task, TreenailTask}
import com.minres.tgc.hammer.tasks.longnail.{LongnailHLSTask, LongnailMergeTask, LongnailScheduleTask, SchedulingParameters}
import org.rogach.scallop.*
import os.Path
import scala.collection.mutable
class LongnailCommand extends MySubcommand("isaxHLS") with CoreSelection {
val inputFiles: ScallopOption[List[Path]] = trailArg[List[Path]]("inputFiles", group = mainGroup, descr = "One or multiple input files; Both .core_desc as well as .mlir are supported (also mixed)")
val useMinIISolution: ScallopOption[Boolean] = toggle(name = "useMinIISolution", group = mainGroup, default = Some(false), descrYes = "Whether to automatically choose the scheduling solution with the lowest II. If not activated, a manual selection during execution will be required!")
val schedParams: SchedulingParameters = addConfigElement(new SchedulingParameters)
banner(
"""Run the complete longnail flow from CoreDSL/MLIR to receive a SystemVerilog representation of the ISAXes
|Usage: tgc-hammer isaxHLS -c VexRiscv --useMinIISolution isax.core_desc
|""".stripMargin)
override def getRequiredTasks: Seq[Task] = {
val tasks = mutable.ListBuffer[Task]()
val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc")
val treenailTasks = coreDSLFiles.map(i => TreenailTask(i, TMP_DIR / s"${i.baseName}.mlir"))
tasks ++= treenailTasks
val allMlirFiles = mlirFiles ++ treenailTasks.map(_.output)
if (allMlirFiles.size == 1) {
tasks += LongnailScheduleTask(allMlirFiles.head, getCoreDatasheet, schedParams)
} else {
val mergedInput = TMP_DIR / "merged.mlir"
val concatInput = TMP_DIR / "concat.mlir"
tasks += LongnailMergeTask(allMlirFiles, concatInput, mergedInput)
tasks += LongnailScheduleTask(mergedInput, getCoreDatasheet, schedParams)
}
if (useMinIISolution()) {
tasks += LongnailHLSTask(schedParams.schedulingSolutionFile(), None, OUT_DIR)
} else {
???
}
tasks.toSeq
}
}

View File

@@ -1,5 +0,0 @@
package com.minres.tgc.hammer.cli
class LongnailHLSCommand {
}

View File

@@ -1,5 +1,31 @@
package com.minres.tgc.hammer.cli package com.minres.tgc.hammer.cli
class LongnailMergeCommand { import com.minres.tgc.hammer.tasks.{CopyTask, Task, TreenailTask}
import org.rogach.scallop.*
import os.Path
import com.minres.tgc.hammer.FileUtils.*
import com.minres.tgc.hammer.Global.*
import com.minres.tgc.hammer.tasks.longnail.LongnailMergeTask
class LongnailMergeCommand extends MySubcommand("mergeISAX") {
val inputFiles: ScallopOption[List[Path]] = trailArg[List[Path]]("inputFiles", group = mainGroup, descr = "One or multiple input files; Both .core_desc as well as .mlir are supported (also mixed)")
val output: ScallopOption[Path] = opt[Path](short = 'o', default = Some("merged.mlir".path()), descr = "The .mlir file containing the merged ISAXes")
override def getRequiredTasks: Seq[Task] = {
val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc")
if (inputFiles().size == 1) {
if (coreDSLFiles.size == 1) {
Seq(TreenailTask(coreDSLFiles.head, output()))
} else {
Seq(CopyTask(mlirFiles.head, output()))
}
} else {
val treenailTasks = coreDSLFiles.map(i => TreenailTask(i, TMP_DIR / s"${i.baseName}.mlir"))
val allMlirFiles = mlirFiles ++ treenailTasks.map(_.output)
val concatInput = TMP_DIR / "concat.mlir"
treenailTasks :+ LongnailMergeTask(allMlirFiles, concatInput, output())
}
}
} }

View File

@@ -20,13 +20,13 @@ class LongnailSchedCommand extends MySubcommand("scheduleISAX") with CoreSelecti
override def getRequiredTasks: Seq[Task] = { override def getRequiredTasks: Seq[Task] = {
val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc") val (coreDSLFiles, mlirFiles) = inputFiles().partition(_.ext == "core_desc")
val treenailTasks = coreDSLFiles.map(i => TreenailTask(i, changeExtension(i, "mlir"))) val treenailTasks = coreDSLFiles.map(i => TreenailTask(i, TMP_DIR / s"${i.baseName}.mlir"))
val allMlirFiles = mlirFiles ++ treenailTasks.map(_.output) val allMlirFiles = mlirFiles ++ treenailTasks.map(_.output)
if (allMlirFiles.size == 1) { if (allMlirFiles.size == 1) {
treenailTasks :+ LongnailScheduleTask(allMlirFiles.head, getCoreDatasheet, schedParams) treenailTasks :+ LongnailScheduleTask(allMlirFiles.head, getCoreDatasheet, schedParams)
} else { } else {
val mergedInput = OUT_DIR / "merged.mlir" val mergedInput = TMP_DIR / "merged.mlir"
val concatInput = OUT_DIR / "concat.mlir" val concatInput = TMP_DIR / "concat.mlir"
treenailTasks :+ LongnailMergeTask(allMlirFiles, concatInput, mergedInput) :+ LongnailScheduleTask(mergedInput, getCoreDatasheet, schedParams) treenailTasks :+ LongnailMergeTask(allMlirFiles, concatInput, mergedInput) :+ LongnailScheduleTask(mergedInput, getCoreDatasheet, schedParams)
} }
} }

View File

@@ -13,7 +13,7 @@ trait BaseOption[T](using conv: ValueConverter[T]) extends ConfigElement {
} }
def get: T = scallop() def get: T = scallop()
def apply: T = get def apply(): T = get
def getToolParameters: Seq[Shellable] = if (scallop.isDefined) Seq(s"$toolName", getToolArg) else Seq() def getToolParameters: Seq[Shellable] = if (scallop.isDefined) Seq(s"$toolName", getToolArg) else Seq()

View File

@@ -0,0 +1,13 @@
package com.minres.tgc.hammer.tasks
import os.*
case class CopyTask(from: Path, to: Path) extends Task {
override def validate(): Unit = {
}
override def execute(): Unit = {
copy(from, to)
}
}

View File

@@ -2,17 +2,16 @@ package com.minres.tgc.hammer.tasks.longnail
import os.Path import os.Path
class LongnailHLSTask(schedulingFile: Option[Path], outDirectory: Path) extends LongnailBaseTask { class LongnailHLSTask(schedulingSolutionFile: Path, schedulingSelectionFile: Option[Path], outDirectory: Path) extends LongnailBaseTask {
override def validate(): Unit = { override def validate(): Unit = {
super.validate() super.validate()
} }
override def execute(): Unit = { override def execute(): Unit = {
runExecutable(EXECUTABLE, runExecutable(EXECUTABLE,
"--lower-lil-to-hw", schedulingSelectionFile match {
schedulingFile match { case Some(value) => s"--lower-lil-to-hw=solutionSelection=$value"
case Some(value) => s"--solutionSelection $value" case None => "--lower-lil-to-hw=forceUseMinIISolution=true"
case None => "--forceUseMinIISolution=true"
}, },
"--simplify-structure", "--simplify-structure",
"--cse", "--cse",
@@ -22,8 +21,8 @@ class LongnailHLSTask(schedulingFile: Option[Path], outDirectory: Path) extends
"--hw-cleanup", "--hw-cleanup",
"--prettify-verilog", "--prettify-verilog",
"--hw-legalize-modules", "--hw-legalize-modules",
"--export-split-verilog", s"--export-split-verilog=dir-name=$outDirectory",
"--dir-name", outDirectory schedulingSolutionFile
) )
} }
} }

View File

@@ -26,5 +26,5 @@ class SchedulingParameters extends OptionGroup {
}) })
value[Int](cliName = "--maxLoopUnrollFactor", toolName = "max-unroll-factor", default = Some(16), descr = "Longnail max loop unroll factor") value[Int](cliName = "--maxLoopUnrollFactor", toolName = "max-unroll-factor", default = Some(16), descr = "Longnail max loop unroll factor")
value[Path](cliName = "--schedulingMLIR", toolName = "o", default = Some(OUT_DIR / "scheduling_solutions.mlir"), descr = "Output file with different scheduling solutions") val schedulingSolutionFile: ValueOption[Path] = value[Path](cliName = "--schedulingMLIR", toolName = "o", default = Some(OUT_DIR / "scheduling_solutions.mlir"), descr = "Output file with different scheduling solutions")
} }