Commit a7138abf authored by Jens Korinth's avatar Jens Korinth
Browse files

WIP: define optimization levels during evaluation

* evaluation results are too conservative w.r.t. f_max
* adding new --optimization flag for import task that defines gcc-like
  opt levels, which activate different synth + pnr options
* Tcl does not work yet
parent 9c3c788f
Pipeline #240 passed with stage
in 2 minutes and 56 seconds
...@@ -31,6 +31,10 @@ set_param general.maxThreads 1 ...@@ -31,6 +31,10 @@ set_param general.maxThreads 1
create_project -in_memory -part @@PART@@ create_project -in_memory -part @@PART@@
# set parameters
set opt @@OPTIMIZATION@@
set synth_options "@@SYNTH_OPTIONS@@"
# add files # add files
add_files @@SRC_FILES@@ add_files @@SRC_FILES@@
# Read ngc/edif files, e.g. for primitives # Read ngc/edif files, e.g. for primitives
...@@ -49,18 +53,20 @@ foreach script [list @@TCL_FILES@@] { source $script } ...@@ -49,18 +53,20 @@ foreach script [list @@TCL_FILES@@] { source $script }
set top [lindex [find_top] 0] set top [lindex [find_top] 0]
# synthesize and optimize netlist # synthesize and optimize netlist
synth_design \ if {$opt >= 1} {
set synth_options "$synth_options -retiming -fanout_limit 400 -shreg_min_size 5"
}
if {$opt >= 2} {
set synth_options "$synth_options -fsm_extraction one_hot"
}
if {$opt >= 3} {
set synth_options "$synth_options -keep_equivalent_registers -resource_sharing off -no_lc"
}
puts synth_design \
-part @@PART@@ \ -part @@PART@@ \
-top $top \ -top $top \
-mode out_of_context \ -mode out_of_context \
-directive AlternateRoutability \ $synth_options
-retiming \
-fanout_limit 400 \
-fsm_extraction one_hot \
-keep_equivalent_registers \
-resource_sharing off \
-no_lc \
-shreg_min_size 5
# read switching activity files (if any) # read switching activity files (if any)
foreach saif [glob -nocomplain *.saif] { foreach saif [glob -nocomplain *.saif] {
...@@ -77,11 +83,33 @@ create_clock -name clk -period @@PERIOD@@ $clock_ports ...@@ -77,11 +83,33 @@ create_clock -name clk -period @@PERIOD@@ $clock_ports
set_property HD.CLK_SRC BUFGCTRL_X0Y0 $clock_ports set_property HD.CLK_SRC BUFGCTRL_X0Y0 $clock_ports
# place and route # place and route
opt_design set opt_directive "RuntimeOptimized"
place_design if {$opt >= 1} { set opt_directive "Default" }
phys_opt_design if {$opt >= 2} { set opt_directive "Explore" }
opt_design -directive $opt_directive
set place_directive "RuntimeOptimized"
if {$opt >= 1} { set place_directive "Default" }
if {$opt >= 1} { set place_directive "Explore" }
place_design -directive $place_directive
set physopt1_directive "RuntimeOptimized"
if {$opt >= 1} { set physopt1_directive "Default" }
if {$opt >= 2} { set physopt1_directive "Explore" }
if {$opt >= 3} { set physopt1_directive "AggressiveExplore" }
phys_opt_design -directive $physopt1_directive
set route_directive "RuntimeOptimized"
if {$opt >= 1} { set route_directive "Default" }
if {$opt >= 2} { set route_directive "Explore" }
route_design route_design
set physopt2_directive "Explore"
if {$opt > 2} { set physopt2_directive "AggressiveExplore" }
if {$opt >= 2} {
phys_opt_design -directive $physopt2_directive
}
# write design checkpoint # write design checkpoint
write_checkpoint -force @@IMPL_CHECKPOINT@@ write_checkpoint -force @@IMPL_CHECKPOINT@@
......
...@@ -113,7 +113,13 @@ object EvaluateIP { ...@@ -113,7 +113,13 @@ object EvaluateIP {
/** Perform the evaluation. /** Perform the evaluation.
* @return true if successful **/ * @return true if successful **/
def apply(zipFile: Path, targetPeriod: Double, targetPart: String, reportFile: Path)(implicit cfg: Configuration): Boolean = { def apply(zipFile: Path,
targetPeriod: Double,
targetPart: String,
reportFile: Path,
optimization: Int,
synthOptions: Option[String] = None)
(implicit cfg: Configuration): Boolean = {
def deleteOnExit(f: java.io.File) = f.deleteOnExit def deleteOnExit(f: java.io.File) = f.deleteOnExit
//def deleteOnExit(f: java.io.File) = f // keep files? //def deleteOnExit(f: java.io.File) = f // keep files?
...@@ -123,7 +129,7 @@ object EvaluateIP { ...@@ -123,7 +129,7 @@ object EvaluateIP {
// define report filenames // define report filenames
Files.createDirectories(reportFile.getParent) Files.createDirectories(reportFile.getParent)
val files = new Files(zipFile, reportFile) val files = new Files(zipFile, reportFile)
writeTclScript(files, targetPart, targetPeriod) writeTclScript(files, targetPart, targetPeriod, optimization, synthOptions)
val lt = new LogTrackingFileWatcher(Some(logger)) val lt = new LogTrackingFileWatcher(Some(logger))
cfg.verbose foreach { _ => lt += files.logFile } cfg.verbose foreach { _ => lt += files.logFile }
...@@ -171,7 +177,11 @@ object EvaluateIP { ...@@ -171,7 +177,11 @@ object EvaluateIP {
* @param targetPart Part identifier of the target FPGA. * @param targetPart Part identifier of the target FPGA.
* @param targetPeriod Target operating period. * @param targetPeriod Target operating period.
**/ **/
private def writeTclScript(files: Files, targetPart: String, targetPeriod: Double): Unit = { private def writeTclScript(files: Files,
targetPart: String,
targetPeriod: Double,
optimization: Int,
synthOptions: Option[String]): Unit = {
val needles: scala.collection.mutable.Map[String, String] = scala.collection.mutable.Map( val needles: scala.collection.mutable.Map[String, String] = scala.collection.mutable.Map(
"SRC_FILES" -> (files.hdl_files map (_.toString) mkString " "), "SRC_FILES" -> (files.hdl_files map (_.toString) mkString " "),
"TCL_FILES" -> (files.tcl_files mkString " "), "TCL_FILES" -> (files.tcl_files mkString " "),
...@@ -184,7 +194,9 @@ object EvaluateIP { ...@@ -184,7 +194,9 @@ object EvaluateIP {
"REPORT_POWER" -> files.rpt_power.toString, "REPORT_POWER" -> files.rpt_power.toString,
"SYNTH_CHECKPOINT" -> files.s_dcp.toString, "SYNTH_CHECKPOINT" -> files.s_dcp.toString,
"IMPL_CHECKPOINT" -> files.i_dcp.toString, "IMPL_CHECKPOINT" -> files.i_dcp.toString,
"NETLIST" -> files.netlist.toString "NETLIST" -> files.netlist.toString,
"OPTIMIZATION" -> optimization.toString,
"SYNTH_OPTIONS" -> (synthOptions getOrElse "")
) )
// write Tcl script // write Tcl script
......
...@@ -52,7 +52,8 @@ object Import { ...@@ -52,7 +52,8 @@ object Import {
* @param skipEval Do not perform out-of-context synthesis for resource estimation (optional). * @param skipEval Do not perform out-of-context synthesis for resource estimation (optional).
* @param cfg Implicit [[base.Configuration]]. * @param cfg Implicit [[base.Configuration]].
**/ **/
def apply(zip: Path, id: Kernel.Id, t: Target, acc: Option[Int], skipEval: Option[Boolean]) def apply(zip: Path, id: Kernel.Id, t: Target, acc: Option[Int], skipEval: Option[Boolean],
optimization: Int, synthOptions: Option[String] = None)
(implicit cfg: Configuration): Boolean = { (implicit cfg: Configuration): Boolean = {
// get VLNV from the file // get VLNV from the file
val vlnv = VLNV.fromZip(zip) val vlnv = VLNV.fromZip(zip)
...@@ -70,7 +71,7 @@ object Import { ...@@ -70,7 +71,7 @@ object Import {
// write core.json to output directory (as per config) // write core.json to output directory (as per config)
val p = cfg.outputDir(c, t).resolve("ipcore").resolve("core.json") val p = cfg.outputDir(c, t).resolve("ipcore").resolve("core.json")
importCore(c, t, p, vlnv, skipEval) importCore(c, t, p, vlnv, skipEval, optimization, synthOptions)
} }
/** /**
...@@ -82,7 +83,8 @@ object Import { ...@@ -82,7 +83,8 @@ object Import {
* @param skipEval Skip out-of-context synthesis step (optional). * @param skipEval Skip out-of-context synthesis step (optional).
* @param cfg Implicit [[Configuration]]. * @param cfg Implicit [[Configuration]].
**/ **/
private def importCore(c: Core, t: Target, p: Path, vlnv: VLNV, skipEval: Option[Boolean]) private def importCore(c: Core, t: Target, p: Path, vlnv: VLNV, skipEval: Option[Boolean], optimization: Int,
synthOptions: Option[String])
(implicit cfg: Configuration): Boolean = { (implicit cfg: Configuration): Boolean = {
Files.createDirectories(p.getParent) Files.createDirectories(p.getParent)
logger.trace("created output directories: {}", p.getParent.toString) logger.trace("created output directories: {}", p.getParent.toString)
...@@ -107,7 +109,7 @@ object Import { ...@@ -107,7 +109,7 @@ object Import {
} }
// evaluate the ip core and store the report with the link // evaluate the ip core and store the report with the link
val res = skipEval.getOrElse(false) || evaluateCore(c, t) val res = skipEval.getOrElse(false) || evaluateCore(c, t, optimization = optimization, synthOptions = synthOptions)
// write core.json // write core.json
logger.debug("writing core description: {}", p.toString) logger.debug("writing core description: {}", p.toString)
...@@ -120,9 +122,12 @@ object Import { ...@@ -120,9 +122,12 @@ object Import {
* place-and-route to produce area and Fmax estimates and the netlist. * place-and-route to produce area and Fmax estimates and the netlist.
* @param c Core description. * @param c Core description.
* @param t Target Architecture + Platform combination. * @param t Target Architecture + Platform combination.
* @param optimization Positive integer optimization level.
* @param synthOptions Optional arguments for synth_design.
* @param cfg Implicit [[Configuration]]. * @param cfg Implicit [[Configuration]].
**/ **/
private def evaluateCore(c: Core, t: Target)(implicit cfg: Configuration): Boolean = { private def evaluateCore(c: Core, t: Target, optimization: Int, synthOptions: Option[String] = None)
(implicit cfg: Configuration): Boolean = {
logger.trace("looking for SynthesisReport ...") logger.trace("looking for SynthesisReport ...")
val period = 0.5 val period = 0.5
val report = cfg.outputDir(c, t).resolve("ipcore").resolve("%s_export.xml".format(c.name)) val report = cfg.outputDir(c, t).resolve("ipcore").resolve("%s_export.xml".format(c.name))
...@@ -134,7 +139,7 @@ object Import { ...@@ -134,7 +139,7 @@ object Import {
true true
} getOrElse { } getOrElse {
logger.info("SynthesisReport for {} not found, starting evaluation ...", c.name) logger.info("SynthesisReport for {} not found, starting evaluation ...", c.name)
EvaluateIP(c.zipPath, period, t.pd.part, report) EvaluateIP(c.zipPath, period, t.pd.part, report, optimization, synthOptions)
} }
} }
} }
...@@ -68,7 +68,7 @@ class CorePanelController extends { ...@@ -68,7 +68,7 @@ class CorePanelController extends {
val path = java.nio.file.Paths.get(ImportFileChooser.selectedFile.toString) val path = java.nio.file.Paths.get(ImportFileChooser.selectedFile.toString)
val tasks = for { val tasks = for {
t <- Job.job.targets t <- Job.job.targets
} yield new ImportTask(path, t, 1, b => cores.update())(Config.configuration) // FIXME missing ID, clock cycles, skip eval } yield new ImportTask(path, t, 1, b => cores.update(), None, None, None, 2)(Config.configuration) // FIXME missing ID, clock cycles, skip eval
tasks foreach (TaskScheduler.apply _) tasks foreach (TaskScheduler.apply _)
} }
} }
......
...@@ -64,8 +64,10 @@ object JobExamples { ...@@ -64,8 +64,10 @@ object JobExamples {
Some("Optional description of the core."), Some("Optional description of the core."),
Some(13124425), Some(13124425),
Some(true), Some(true),
Some("-retiming"),
Some(Seq("axi4mm")), Some(Seq("axi4mm")),
Some(Seq("zedboard", "zc706"))) Some(Seq("zedboard", "zc706")),
Some(3))
val jobs: Seq[Job] = Seq(bulkImportJob, composeJob, coreStatisticsJob, dseJob, hlsJob, importJob) val jobs: Seq[Job] = Seq(bulkImportJob, composeJob, coreStatisticsJob, dseJob, hlsJob, importJob)
......
...@@ -226,8 +226,10 @@ final case class HighLevelSynthesisJob( ...@@ -226,8 +226,10 @@ final case class HighLevelSynthesisJob(
* @param description Description of the core (optional). * @param description Description of the core (optional).
* @param averageClockCycles Clock cycles in an average job (optional). * @param averageClockCycles Clock cycles in an average job (optional).
* @param skipEvaluation Do not perform evaluation (optional). * @param skipEvaluation Do not perform evaluation (optional).
* @param synthOptions Optional parameters for synth_design.
* @param _architectures Name list of [[base.Architecture]] instances. * @param _architectures Name list of [[base.Architecture]] instances.
* @param _platforms Name list of [[base.Platform]] instances. * @param _platforms Name list of [[base.Platform]] instances.
* @param _optimization Positive integer optimization level.
**/ **/
final case class ImportJob( final case class ImportJob(
zipFile: Path, zipFile: Path,
...@@ -235,8 +237,10 @@ final case class ImportJob( ...@@ -235,8 +237,10 @@ final case class ImportJob(
description: Option[String] = None, description: Option[String] = None,
averageClockCycles: Option[Int] = None, averageClockCycles: Option[Int] = None,
skipEvaluation: Option[Boolean] = None, skipEvaluation: Option[Boolean] = None,
synthOptions: Option[String] = None,
private val _architectures: Option[Seq[String]] = None, private val _architectures: Option[Seq[String]] = None,
private val _platforms: Option[Seq[String]] = None) extends Job("import") { private val _platforms: Option[Seq[String]] = None,
private val _optimization: Option[Int] = None) extends Job("import") {
/** Returns the list of [[base.Architecture]] instances selected in this job. */ /** Returns the list of [[base.Architecture]] instances selected in this job. */
def architectures: Set[Architecture] = def architectures: Set[Architecture] =
FileAssetManager.entities.architectures filter (a => _architectures map (_.contains(a.name)) getOrElse true) FileAssetManager.entities.architectures filter (a => _architectures map (_.contains(a.name)) getOrElse true)
...@@ -244,6 +248,9 @@ final case class ImportJob( ...@@ -244,6 +248,9 @@ final case class ImportJob(
/** Returns the list of [[base.Platform]] instances selected in this job. */ /** Returns the list of [[base.Platform]] instances selected in this job. */
def platforms: Set[Platform] = def platforms: Set[Platform] =
FileAssetManager.entities.platforms filter (p => _platforms map (_.contains(p.name)) getOrElse true) FileAssetManager.entities.platforms filter (p => _platforms map (_.contains(p.name)) getOrElse true)
/** Returns the optimization level. */
def optimization: Int = _optimization getOrElse 0
} }
object BulkImportJob extends Builds[BulkImportJob] object BulkImportJob extends Builds[BulkImportJob]
......
...@@ -52,7 +52,7 @@ private object BulkImport extends Executor[BulkImportJob] { ...@@ -52,7 +52,7 @@ private object BulkImport extends Executor[BulkImportJob] {
a <- j.architectures a <- j.architectures
p <- j.platforms p <- j.platforms
t = Target(a, p) t = Target(a, p)
} yield new ImportTask(j.zipFile, t, j.id, _ => signal.release(), j.averageClockCycles)(cfg) } yield new ImportTask(j.zipFile, t, j.id, _ => signal.release(), j.averageClockCycles, None, None, 2)(cfg)
importTasks foreach { tsk.apply _ } importTasks foreach { tsk.apply _ }
......
...@@ -70,7 +70,7 @@ protected object HighLevelSynthesis extends Executor[HighLevelSynthesisJob] { ...@@ -70,7 +70,7 @@ protected object HighLevelSynthesis extends Executor[HighLevelSynthesisJob] {
if (avgCC.isEmpty && k.testbenchFiles.length > 0) { if (avgCC.isEmpty && k.testbenchFiles.length > 0) {
logger.warn("executed HLS with co-sim for {}, but no co-simulation report was found", k) logger.warn("executed HLS with co-sim for {}, but no co-simulation report was found", k)
} }
Some(new ImportTask(zip, t, k.id, _ => signal.release(), avgCC)(cfg)) Some(new ImportTask(zip, t, k.id, _ => signal.release(), avgCC, None, None, 2)(cfg))
} }
case _ => None case _ => None
} }
......
...@@ -51,7 +51,7 @@ object Import extends Executor[ImportJob] { ...@@ -51,7 +51,7 @@ object Import extends Executor[ImportJob] {
val tasks = jobs map { case (j, t) => val tasks = jobs map { case (j, t) =>
val avgCC = FileAssetManager.reports.cosimReport(VLNV.fromZip(j.zipFile).name, t) map (_.latency.avg) val avgCC = FileAssetManager.reports.cosimReport(VLNV.fromZip(j.zipFile).name, t) map (_.latency.avg)
new ImportTask(j.zipFile, t, j.id, _ => signal.release(), avgCC, j.skipEvaluation)(cfg) new ImportTask(j.zipFile, t, j.id, _ => signal.release(), avgCC, j.skipEvaluation, None, 2)(cfg)
} }
tasks foreach { tsk.apply _ } tasks foreach { tsk.apply _ }
......
...@@ -55,8 +55,10 @@ package object json { ...@@ -55,8 +55,10 @@ package object json {
(JsPath \ "Description").readNullable[String] ~ (JsPath \ "Description").readNullable[String] ~
(JsPath \ "Average Clock Cycles").readNullable[Int] (verifying[Int](_ > 0)) ~ (JsPath \ "Average Clock Cycles").readNullable[Int] (verifying[Int](_ > 0)) ~
(JsPath \ "Skip Evaluation").readNullable[Boolean] ~ (JsPath \ "Skip Evaluation").readNullable[Boolean] ~
(JsPath \ "Synth Options").readNullable[String] ~
(JsPath \ "Architectures").readNullable[Seq[String]] ~ (JsPath \ "Architectures").readNullable[Seq[String]] ~
(JsPath \ "Platforms").readNullable[Seq[String]] (JsPath \ "Platforms").readNullable[Seq[String]] ~
(JsPath \ "Optimization").readNullable[Int] (verifying[Int](_ >= 0))
) (ImportJob.apply _) ) (ImportJob.apply _)
implicit val importJobWrites: Writes[ImportJob] = ( implicit val importJobWrites: Writes[ImportJob] = (
...@@ -66,8 +68,10 @@ package object json { ...@@ -66,8 +68,10 @@ package object json {
(JsPath \ "Description").writeNullable[String] ~ (JsPath \ "Description").writeNullable[String] ~
(JsPath \ "Average Clock Cycles").writeNullable[Int] ~ (JsPath \ "Average Clock Cycles").writeNullable[Int] ~
(JsPath \ "Skip Evaluation").writeNullable[Boolean] ~ (JsPath \ "Skip Evaluation").writeNullable[Boolean] ~
(JsPath \ "Synth Options").writeNullable[String] ~
(JsPath \ "Architectures").writeNullable[Seq[String]] ~ (JsPath \ "Architectures").writeNullable[Seq[String]] ~
(JsPath \ "Platforms").writeNullable[Seq[String]] (JsPath \ "Platforms").writeNullable[Seq[String]] ~
(JsPath \ "Optimization").writeNullable[Int]
) (unlift(ImportJob.unapply _ andThen (_ map ("Import" +: _)))) ) (unlift(ImportJob.unapply _ andThen (_ map ("Import" +: _))))
/* ImportJob @} */ /* ImportJob @} */
......
...@@ -37,7 +37,7 @@ private object ImportParser { ...@@ -37,7 +37,7 @@ private object ImportParser {
private val jobid = identity[ImportJob] _ private val jobid = identity[ImportJob] _
private def options: Parser[ImportJob => ImportJob] = private def options: Parser[ImportJob => ImportJob] =
(description | avgClockCycles | skipEval | architectures | platforms).rep map (opts => (description | avgClockCycles | skipEval | architectures | platforms | synthOptions | optimization).rep map (opts =>
(opts map (applyOption _) fold jobid) (_ andThen _)) (opts map (applyOption _) fold jobid) (_ andThen _))
private def description: Parser[(String, String)] = private def description: Parser[(String, String)] =
...@@ -50,12 +50,20 @@ private object ImportParser { ...@@ -50,12 +50,20 @@ private object ImportParser {
private def skipEval: Parser[(String, Boolean)] = private def skipEval: Parser[(String, Boolean)] =
(longOption("skipEvaluation", "SkipEval") ~ ws) map { case s => (s, true) } (longOption("skipEvaluation", "SkipEval") ~ ws) map { case s => (s, true) }
private def synthOptions: Parser[(String, String)] =
longOption("synthOptions", "SynthOptions") ~ ws ~/ qstring.opaque("additional synth_design options as string") ~ ws
private def optimization: Parser[(String, Int)] =
longOption("optimization", "Optimization") ~ ws ~/ posint.opaque("positive integer optimization level") ~ ws
private def applyOption(opt: (String, _)): ImportJob => ImportJob = opt match { private def applyOption(opt: (String, _)): ImportJob => ImportJob = opt match {
case ("Description", d: String) => _.copy(description = Some(d)) case ("Description", d: String) => _.copy(description = Some(d))
case ("AvgCC", cc: Int) => _.copy(averageClockCycles = Some(cc)) case ("AvgCC", cc: Int) => _.copy(averageClockCycles = Some(cc))
case ("SkipEval", se: Boolean) => _.copy(skipEvaluation = Some(se)) case ("SkipEval", se: Boolean) => _.copy(skipEvaluation = Some(se))
case ("SynthOptions", so: String) => _.copy(synthOptions = Some(so))
case ("Architectures", as: Seq[String @unchecked]) => _.copy(_architectures = Some(as)) case ("Architectures", as: Seq[String @unchecked]) => _.copy(_architectures = Some(as))
case ("Platforms", ps: Seq[String @unchecked]) => _.copy(_platforms = Some(ps)) case ("Platforms", ps: Seq[String @unchecked]) => _.copy(_platforms = Some(ps))
case ("Optimization", lvl: Int) => _.copy(_optimization = Some(lvl))
case o => throw new Exception(s"parsed illegal option: $o") case o => throw new Exception(s"parsed illegal option: $o")
} }
} }
...@@ -46,7 +46,9 @@ class ImportTask(val zip: Path, ...@@ -46,7 +46,9 @@ class ImportTask(val zip: Path,
val id: Kernel.Id, val id: Kernel.Id,
val onComplete: Boolean => Unit, val onComplete: Boolean => Unit,
val averageClockCycles: Option[Int] = None, val averageClockCycles: Option[Int] = None,
val skipEvaluation: Option[Boolean] = None) val skipEvaluation: Option[Boolean] = None,
val synthOptions: Option[String] = None,
val optimization: Int)
(implicit val cfg: Configuration) extends Task with LogTracking { (implicit val cfg: Configuration) extends Task with LogTracking {
private implicit val logger = de.tu_darmstadt.cs.esa.tapasco.Logging.logger(getClass) private implicit val logger = de.tu_darmstadt.cs.esa.tapasco.Logging.logger(getClass)
private val name = try { Some(VLNV.fromZip(zip).name) } catch { case _: Throwable => None } private val name = try { Some(VLNV.fromZip(zip).name) } catch { case _: Throwable => None }
...@@ -59,7 +61,7 @@ class ImportTask(val zip: Path, ...@@ -59,7 +61,7 @@ class ImportTask(val zip: Path,
val appender = LogFileTracker.setupLogFileAppender(_logFile.toString) val appender = LogFileTracker.setupLogFileAppender(_logFile.toString)
logger.trace("current thread name: {}", Thread.currentThread.getName()) logger.trace("current thread name: {}", Thread.currentThread.getName())
logger.info(description) logger.info(description)
val result = activity.Import(zip, id, t, averageClockCycles, skipEvaluation) val result = activity.Import(zip, id, t, averageClockCycles, skipEvaluation, optimization, synthOptions)
LogFileTracker.stopLogFileAppender(appender) LogFileTracker.stopLogFileAppender(appender)
result result
} }
......
...@@ -46,11 +46,23 @@ private object ImportParserSpec { ...@@ -46,11 +46,23 @@ private object ImportParserSpec {
Gen.posNum[Int] map (_.toString) Gen.posNum[Int] map (_.toString)
)) ))
val synthOptionsGen: Gen[String] = join(Seq(
genLongOption("synthOptions"),
qstringGen
))
val optimizationGen: Gen[String] = join(Seq(
genLongOption("optimization"),
Gen.posNum[Int] map (_.toString)
))
val optionGen: Gen[String] = Gen.oneOf( val optionGen: Gen[String] = Gen.oneOf(
descriptionGen, descriptionGen,
avgClockCyclesGen, avgClockCyclesGen,
architecturesGen, architecturesGen,
platformsGen platformsGen,
synthOptionsGen,
optimizationGen
) )
val optionsGen: Gen[String] = for { val optionsGen: Gen[String] = for {
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment