diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala index 1e72418..bfaa8fa 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/Global.scala @@ -11,5 +11,6 @@ object Global { lazy val LONGNAIL: Path = HAMMER / "deps" / "longnail" lazy val BASE_DIR: Path = os.pwd lazy val OUT_DIR: Path = Main.conf.outputDirectory() + lazy val TMP_DIR: Path = OUT_DIR / "tmp" lazy val CORE_DATASHEETS: Path = HAMMER / "coreDatasheets" } diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala index 7010035..7d99bd7 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/HammerConf.scala @@ -6,6 +6,7 @@ import com.minres.tgc.hammer.FileUtils.* class HammerConf(arguments: Seq[String]) extends ScallopConf(arguments) { val outputDirectory: ScallopOption[Path] = opt[Path](default = Some("output".path()), descr = "The base output directory") + addSubcommand(new LongnailCommand) addSubcommand(new TreenailCommand) addSubcommand(new LongnailSchedCommand) diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailCommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailCommand.scala new file mode 100644 index 0000000..67f1e5a --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailCommand.scala @@ -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 + } +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailHLSCommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailHLSCommand.scala deleted file mode 100644 index 71436ce..0000000 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailHLSCommand.scala +++ /dev/null @@ -1,5 +0,0 @@ -package com.minres.tgc.hammer.cli - -class LongnailHLSCommand { - -} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailMergeCommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailMergeCommand.scala index 39fb846..9ba9498 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailMergeCommand.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailMergeCommand.scala @@ -1,5 +1,31 @@ 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()) + } + } } diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailSchedCommand.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailSchedCommand.scala index 2ca2f2e..938875a 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailSchedCommand.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/cli/LongnailSchedCommand.scala @@ -20,13 +20,13 @@ class LongnailSchedCommand extends MySubcommand("scheduleISAX") with CoreSelecti override def getRequiredTasks: Seq[Task] = { 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) if (allMlirFiles.size == 1) { treenailTasks :+ LongnailScheduleTask(allMlirFiles.head, getCoreDatasheet, schedParams) } else { - val mergedInput = OUT_DIR / "merged.mlir" - val concatInput = OUT_DIR / "concat.mlir" + val mergedInput = TMP_DIR / "merged.mlir" + val concatInput = TMP_DIR / "concat.mlir" treenailTasks :+ LongnailMergeTask(allMlirFiles, concatInput, mergedInput) :+ LongnailScheduleTask(mergedInput, getCoreDatasheet, schedParams) } } diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/options/BaseOption.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/options/BaseOption.scala index 52fc601..25c4f01 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/options/BaseOption.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/options/BaseOption.scala @@ -13,7 +13,7 @@ trait BaseOption[T](using conv: ValueConverter[T]) extends ConfigElement { } 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() diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/CopyTask.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/CopyTask.scala new file mode 100644 index 0000000..1b6cc48 --- /dev/null +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/CopyTask.scala @@ -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) + } +} diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/LongnailHLSTask.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/LongnailHLSTask.scala index 6983b9c..065c3c1 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/LongnailHLSTask.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/LongnailHLSTask.scala @@ -2,17 +2,16 @@ package com.minres.tgc.hammer.tasks.longnail 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 = { super.validate() } override def execute(): Unit = { runExecutable(EXECUTABLE, - "--lower-lil-to-hw", - schedulingFile match { - case Some(value) => s"--solutionSelection $value" - case None => "--forceUseMinIISolution=true" + schedulingSelectionFile match { + case Some(value) => s"--lower-lil-to-hw=solutionSelection=$value" + case None => "--lower-lil-to-hw=forceUseMinIISolution=true" }, "--simplify-structure", "--cse", @@ -22,8 +21,8 @@ class LongnailHLSTask(schedulingFile: Option[Path], outDirectory: Path) extends "--hw-cleanup", "--prettify-verilog", "--hw-legalize-modules", - "--export-split-verilog", - "--dir-name", outDirectory + s"--export-split-verilog=dir-name=$outDirectory", + schedulingSolutionFile ) } } diff --git a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/SchedulingParameters.scala b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/SchedulingParameters.scala index 4133a36..74106f4 100644 --- a/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/SchedulingParameters.scala +++ b/toolflow/src/main/scala/com/minres/tgc/hammer/tasks/longnail/SchedulingParameters.scala @@ -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[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") }