Commit 1f0855b5 authored by Jens Korinth's avatar Jens Korinth
Browse files

Remove distinction between Platform and Arch Features

* no real difference, distinction is arbitrary
* removed completely, instead there are only features now
* renamed/purged methods in common.tcl
* removed notion from Composer and subclasses
* per default, Tcl dict is now simply called "features"
* fixed case-sensitivity bug: by default all keys are now lowercased
* fixed all existing plugins and Tcl scripts
* fixed scalastyle warnings
parent 24297971
......@@ -546,28 +546,24 @@ namespace eval tapasco {
return $kernels
}
# Returns a list of configured features for the Platform.
proc get_platform_features {} {
global platformfeatures
if {[info exists platformfeatures]} { return [dict keys $platformfeatures] } { return [dict] }
# Returns a list of configured features.
proc get_features {} {
global features
if {[info exists features]} { return [dict keys $features] } { return [dict create] }
}
# Returns a dictionary with the configuration of given Platform feature.
proc get_platform_feature {feature} {
global platformfeatures
if {[info exists platformfeatures] && [dict exists $platformfeatures $feature]} {
return [dict get $platformfeatures $feature]
} else {
return [dict create]
}
# Returns a dictionary with the configuration of given feature (if it exists).
proc get_feature {feature} {
global features
if {[info exists features]} { return [dict get $features $feature] } { return [dict] }
}
# Returns true, if given feature is configured and enabled.
proc is_platform_feature_enabled {feature} {
global platformfeatures
if {[info exists platformfeatures]} {
if {[dict exists $platformfeatures $feature]} {
if {[dict get $platformfeatures $feature "enabled"] == "true"} {
proc is_feature_enabled {feature} {
global features
if {[info exists features]} {
if {[dict exists $features $feature]} {
if {[dict get $features $feature "enabled"] == "true"} {
return true
}
}
......@@ -575,31 +571,6 @@ namespace eval tapasco {
return false
}
# Returns a list of configured features for the Architecture.
proc get_architecture_features {} {
global architecturefeatures
if {[info exists architecturefeatures]} { return [dict keys $architectureFeatures] } { return [dict create] }
}
# Returns a dictionary with the configuration of given Architecture feature.
proc get_architecture_feature {feature} {
global architecturefeatures
if {[info exists architecturefeatures]} { return [dict get $architecturefeatures $feature] } { return [dict] }
}
# Returns true, if given feature is configured and enabled.
proc is_architecture_feature_enabled {feature} {
global architecturefeatures
if {[info exists architecturefeatures]} {
if {[dict exists $architecturefeatures $feature]} {
if {[dict get $architecturefeatures $feature "enabled"] == "true"} {
return true
}
}
}
return false
}
proc create_debug_core {clk nets {depth 4096} {stages 0} {name "u_ila_0"}} {
puts "Creating an ILA debug core ..."
puts " data depth : $depth"
......
......@@ -6,14 +6,14 @@ namespace eval blue_dma {
proc blue_dma {{args {}}} {
variable vlnv
if {[tapasco::is_platform_feature_enabled "BlueDMA"]} {
if {[tapasco::is_feature_enabled "BlueDMA"]} {
# blue_dma is drop-in replacement for dual_dma: replace original VLNV
dict set tapasco::stdcomps dualdma vlnv $vlnv
}
}
proc set_constraints {{args {}}} {
if {[tapasco::is_platform_feature_enabled "BlueDMA"]} {
if {[tapasco::is_feature_enabled "BlueDMA"]} {
puts "Adding false path constraints for BlueDMA"
set constraints_fn "[get_property DIRECTORY [current_project]]/bluedma.xdc"
set constraints_file [open $constraints_fn w+]
......
......@@ -78,11 +78,11 @@ namespace eval leds {
proc create_leds {{name "gp_leds"}} {
variable vlnv
if {[tapasco::is_platform_feature_enabled "LED"]} {
if {[tapasco::is_feature_enabled "LED"]} {
puts "Implementing Platform feature LED ..."
# create and connect LED core
set const_one [tapasco::createConstant "const_one" 1 1]
set gp_led [create_led_core "gp_led" [dict get [tapasco::get_platform_feature "LED"] "inputs"]]
set gp_led [create_led_core "gp_led" [dict get [tapasco::get_feature "LED"] "inputs"]]
set pcie_aclk [get_bd_pins "/PCIe/pcie_aclk"]
set pcie_aresetn [get_bd_pins "/PCIe/pcie_aresetn"]
set pcie_aclk_net [get_bd_net -of_objects $pcie_aclk]
......
......@@ -160,13 +160,13 @@ namespace eval platform {
CONFIG.S01_HAS_DATA_FIFO {2}
] $mig_ic
set cf [tapasco::get_platform_feature "Cache"]
set cache_en [tapasco::is_platform_feature_enabled "Cache"]
set cf [tapasco::get_feature "Cache"]
set cache_en [tapasco::is_feature_enabled "Cache"]
if {$cache_en} {
puts "Platform configured w/L2 Cache, implementing ..."
set cache [tapasco::createSystemCache "cache_l2" 1 \
[dict get [tapasco::get_platform_feature "Cache"] "size"] \
[dict get [tapasco::get_platform_feature "Cache"] "associativity"]]
[dict get [tapasco::get_feature "Cache"] "size"] \
[dict get [tapasco::get_feature "Cache"] "associativity"]]
# connect mig_ic master to cache_l2
connect_bd_intf_net [get_bd_intf_pins mig_ic/M00_AXI] [get_bd_intf_pins $cache/S0_AXI_GEN]
......@@ -405,7 +405,7 @@ namespace eval platform {
]
# enable ATS/PRI (if platform feature is set)
if {[tapasco::is_platform_feature_enabled "ATS-PRI"]} {
if {[tapasco::is_feature_enabled "ATS-PRI"]} {
puts " ATS/PRI support is enabled"
lappend pcie_properties \
CONFIG.c_ats_enable {true} \
......
......@@ -23,7 +23,7 @@
#
namespace eval fancontrol {
proc fancontrol_feature {{args {}}} {
if {![dict exists [tapasco::get_architecture_features] "FanControl"] || [tapasco::is_platform_feature_enabled "FanControl"]} {
if {[tapasco::is_feature_enabled "FanControl"]} {
put "Building primitive PWM module to subdue the noisy ZC706 fan ..."
set ps [get_bd_cell -hierarchical -filter {VLNV =~ "xilinx.com:ip:processing_system*"}]
set cnt [tapasco::createBinaryCounter "pwmcounter" 4]
......
......@@ -63,7 +63,7 @@ namespace eval oled {
}
proc oled_feature {{args {}}} {
if {[tapasco::is_platform_feature_enabled "OLED"]} {
if {[tapasco::is_feature_enabled "OLED"]} {
set oled [create_subsystem_oled "OLED" [arch::get_irqs]]
set ps [get_bd_cell -hierarchical -filter {VLNV =~ "xilinx.com:ip:processing_system*"}]
set ps_rst [get_bd_pin "/Host/ps_resetn"]
......
......@@ -68,10 +68,10 @@ namespace eval debug {
}
proc debug_feature {} {
if {[tapasco::is_platform_feature_enabled "Debug"]} {
if {[tapasco::is_feature_enabled "Debug"]} {
puts "Creating ILA debug core, will require re-run of synthesis."
# get config
set debug [tapasco::get_platform_feature "Debug"]
set debug [tapasco::get_feature "Debug"]
puts " Debug = $debug"
# default values
set depth 4096
......@@ -100,7 +100,7 @@ namespace eval debug {
proc write_ltx {} {
global bitstreamname
if {[tapasco::is_platform_feature_enabled "Debug"]} {
if {[tapasco::is_feature_enabled "Debug"]} {
puts "Writing debug probes into file ${bitstreamname}.ltx ..."
write_debug_probes -force -verbose "${bitstreamname}.ltx"
}
......
......@@ -39,13 +39,12 @@ trait Composer {
* @param bd Composition to synthesize
* @param target Platform and Architecture combination to synthesize for
* @param f target design frequency (PE speed)
* @param archFeatures ArchitectureFeatures (optional).
* @param platformFeatures Platform features (optional).
* @param features Features (optional)
* @param cfg implicit Configuration instance
* @return Composer.Result with error code / additional data
**/
def compose(bd: Composition, target: Target, f: Double = 0, archFeatures: Seq[Feature] = Seq(),
platformFeatures: Seq[Feature] = Seq())(implicit cfg: Configuration): Result
def compose(bd: Composition, target: Target, f: Double = 0, features: Seq[Feature] = Seq())
(implicit cfg: Configuration): Result
/** Removes all intermediate files for the run, leaving results.
* @param bd Composition to synthesize
......
......@@ -46,11 +46,11 @@ class VivadoComposer()(implicit cfg: Configuration) extends Composer {
def maxMemoryUsagePerProcess: Int = VIVADO_PROCESS_PEAK_MEM
/** @inheritdoc */
def compose(bd: Composition, target: Target, f: Heuristics.Frequency = 0, archFeatures: Seq[Feature] = Seq(),
platformFeatures: Seq[Feature] = Seq()) (implicit cfg: Configuration): Composer.Result = {
def compose(bd: Composition, target: Target, f: Heuristics.Frequency = 0, features: Seq[Feature] = Seq())
(implicit cfg: Configuration): Composer.Result = {
logger.debug("VivadoComposer uses at most {} threads", cfg.maxThreads getOrElse "unlimited")
// create output struct
val files = VivadoComposer.Files(bd, target, f, archFeatures ++ platformFeatures)
val files = VivadoComposer.Files(bd, target, f, features)
// create log tracker
val lt = new LogTrackingFileWatcher(Some(logger))
// create output directory
......@@ -61,7 +61,7 @@ class VivadoComposer()(implicit cfg: Configuration) extends Composer {
mkTclScript(fromTemplate = Common.commonDir.resolve("design.master.tcl.template"),
to = files.tclFile,
projectName = Composer.mkProjectName(bd, target, f),
header = makeHeader(bd, target, f, archFeatures, platformFeatures),
header = makeHeader(bd, target, f, features),
target = target,
composition = composition(bd, target))
......@@ -192,16 +192,14 @@ class VivadoComposer()(implicit cfg: Configuration) extends Composer {
}
/** Produces the header section of the main Tcl file, containing several global vars. **/
private def makeHeader(bd: Composition, target: Target, f: Heuristics.Frequency, archFeatures: Seq[Feature],
platformFeatures: Seq[Feature]): String =
private def makeHeader(bd: Composition, target: Target, f: Heuristics.Frequency, features: Seq[Feature]): String =
"set tapasco_freq %3.0f%s".format(f, NL) +
(target.pd.hostFrequency map (f => "set tapasco_host_freq %3.0f%s".format(f, NL)) getOrElse "") +
(target.pd.memFrequency map (f => "set tapasco_mem_freq %3.0f%s".format(f, NL)) getOrElse "") +
(target.pd.boardPreset map (bp => "set tapasco_board_preset %s%s".format(bp, NL)) getOrElse "") +
(cfg.maxThreads map (mt => "set tapasco_jobs %d%s".format(mt, NL)) getOrElse "") +
(cfg.maxThreads map (mt => "set_param general.maxThreads %d%s".format(mt, NL)) getOrElse "") +
(platformFeatures.map { f => new FeatureTclPrinter("platform").toTcl(f) } mkString NL) +
(archFeatures.map { f => new FeatureTclPrinter("architecture").toTcl(f) } mkString NL) + NL
(features.map { f => new FeatureTclPrinter().toTcl(f) } mkString NL)
}
/** Companion object of [[VivadoComposer]]. */
......
......@@ -23,19 +23,18 @@
**/
package de.tu_darmstadt.cs.esa.tapasco.base
sealed class Feature(val name: String, val props: Map[String, String]) {
sealed case class Feature(val name: String, val props: Map[String, String]) {
def unapply: Option[(String, Map[String, String])] = Some((name, props))
override def equals(o: Any): Boolean = o match {
case Feature(n, p) => name.equals(n) && props.equals(p)
case _ => false
}
}
object Feature {
def apply(name: String, props: Map[String, String]): Feature = new Feature(
name,
if (props.get("Enabled").nonEmpty) props else props + ("Enabled" -> "true")
)
def apply(name: String, props: Map[String, String]): Feature = {
val lp = props map { case (k, v) => k.toLowerCase -> v }
new Feature(
name,
if (lp.get("enabled").nonEmpty) lp else lp + ("enabled" -> "true")
)
}
def unapply(f: Feature): Option[(String, Map[String, String])] = f.unapply
}
......@@ -25,7 +25,7 @@ package de.tu_darmstadt.cs.esa.tapasco.base.tcl
import de.tu_darmstadt.cs.esa.tapasco.base.Feature
import scala.util.Properties.{lineSeparator => NL}
class FeatureTclPrinter(prefix: String) {
class FeatureTclPrinter(prefix: String = "") {
private val pre = s"dict set ${prefix}features"
/** GenerateTcl commands to add feature to a Tcl dict.
......
......@@ -6,10 +6,10 @@ import scala.language.implicitConversions
private object BasicParsers {
def longOption(name: String): Parser[String] = longOption(name, name)
def longOption(name: String, retVal: String, alternatives: String*) =
def longOption(name: String, retVal: String, alternatives: String*): Parser[String] =
(name +: alternatives) map (n => IgnoreCase("--%s".format(n)).!.map(_ => retVal)) reduce (_|_)
def longShortOption(shortName: String, longName: String, retVal: Option[String] = None) =
def longShortOption(shortName: String, longName: String, retVal: Option[String] = None): Parser[String] =
IgnoreCase("-%s".format(shortName)).! | IgnoreCase("--%s".format(longName)).! map (retVal getOrElse _)
val argChars = "-"
......
......@@ -26,19 +26,20 @@ object CommandLineParser {
}
object ParserException {
private final val SLICE_WINDOW = (-100, 40)
private final val SLICE_LEFT = -100
private final val SLICE_RIGHT = 40
def apply(f: Parsed.Failure): ParserException =
ParserException(f.lastParser.toString,
f.index,
f.extra.input.slice(f.index + SLICE_WINDOW._1, f.index + SLICE_WINDOW._2)
f.extra.input.slice(f.index + SLICE_LEFT, f.index + SLICE_RIGHT)
.replace ("\t", " ")
.replace ("\n", " "),
("~" * f.index + "^").slice(f.index + SLICE_WINDOW._1,
f.index + SLICE_WINDOW._2))
("~" * f.index + "^").slice(f.index + SLICE_LEFT,
f.index + SLICE_RIGHT))
}
def check[A](x: Parsed[A]) = x match {
def check[A](x: Parsed[A]): Either[ParserException, A] = x match {
case f: Parsed.Failure => Left(ParserException(f))
case Parsed.Success(cfg, _) => Right(cfg)
}
......
......@@ -27,8 +27,8 @@ private object CommonArgParsers {
(BasicParsers.seqOne(compositionEntry) ~ ws)
.opaque("list of composition entries of form <KERNEL NAME> 'x' <COUNT>")
def compositionBegin = "[" ~ ws opaque("start of composition: '['")
def compositionEnd = "]" ~ ws opaque("end of composition: ']'")
def compositionBegin: Parser[Unit] = "[" ~ ws opaque("start of composition: '['")
def compositionEnd: Parser[Unit] = "]" ~ ws opaque("end of composition: ']'")
def compositionFile: Parser[Composition] =
path.opaque("path to composition Json file") map loadCompositionFromFile _
......
......@@ -19,9 +19,11 @@ private object FeatureParsers {
val featureMarks = (featureBeginChars ++ featureEndChars) map (_.toString)
val featureAssigns = Seq("->", "=", ":=", ":")
def featureBegin = CharIn(featureBeginChars).opaque(s"begin of feature mark, one of '$featureBeginChars'")
def featureEnd = CharIn(featureEndChars).opaque(s"end of feature mark, one of '$featureEndChars'")
def featureAssign = "->" | "=" | ":=" | ":"
def featureBegin: Parser[Unit] =
CharIn(featureBeginChars).opaque(s"begin of feature mark, one of '$featureBeginChars'")
def featureEnd: Parser[Unit] =
CharIn(featureEndChars).opaque(s"end of feature mark, one of '$featureEndChars'")
def featureAssign: Parser[Unit] = "->" | "=" | ":=" | ":"
def featureKey: Parser[String] =
(quotedString | string(featureAssigns ++ featureMarks))
......
package de.tu_darmstadt.cs.esa.tapasco.parser
import FormatObject._
import scala.language.implicitConversions
sealed trait FormatObject {
def /(other: FormatObject) = Concat(this, other)
def concat(other: FormatObject) = Concat(this, other)
def ~(other: FormatObject) = Join(this, other)
def join(other: FormatObject) = Join(this, other)
def &(other: FormatObject) = Break(this, other)
def break(other: FormatObject) = Break(this, other)
def /(other: FormatObject): FormatObject = Concat(this, other)
def concat(other: FormatObject): FormatObject = Concat(this, other)
def ~(other: FormatObject): FormatObject = Join(this, other)
def join(other: FormatObject): FormatObject = Join(this, other)
def &(other: FormatObject): FormatObject = Break(this, other)
def break(other: FormatObject): FormatObject = Break(this, other)
}
final case class Header(title: String, section: ManSection, date: String, source: String) extends FormatObject
sealed class Section(val name: String, val content: FormatObject) extends FormatObject
......@@ -27,8 +28,8 @@ final case class RI(fo: FormatObject) extends FormatObject
final case class SB(fo: FormatObject) extends FormatObject
final case class SM(fo: FormatObject) extends FormatObject
final case class Block(fo: FormatObject, width: Int = 80) extends FormatObject
final case class Indent(fo: FormatObject, depth: Int = 2) extends FormatObject
final case class Block(fo: FormatObject, width: Int = DEFAULT_BLOCK_WIDTH) extends FormatObject
final case class Indent(fo: FormatObject, depth: Int = DEFAULT_INDENT_WIDTH) extends FormatObject
final case class Concat(fo1: FormatObject, fo2: FormatObject) extends FormatObject
final case class Join(fo1: FormatObject, fo2: FormatObject) extends FormatObject
final case class Break(fo1: FormatObject, fo2: FormatObject) extends FormatObject
......@@ -37,6 +38,8 @@ final case class Name(program: String, onelineDesc: String) extends Section("Nam
final case class Synopsis(shortUsage: FormatObject) extends Section("Synopsis", shortUsage)
object FormatObject {
final val DEFAULT_BLOCK_WIDTH: Int = 80
final val DEFAULT_INDENT_WIDTH: Int = 2
implicit def toFormatObject(s: String): FormatObject = T(s)
implicit def toString(fo: FormatObject)(implicit formatter: Formatter[String]): String =
formatter(fo)
......
......@@ -24,6 +24,7 @@ trait Formatter[A] extends Function[FormatObject, A] {
def format(p: Join): A
def format(p: Break): A
// scalastyle:off cyclomatic.complexity
def apply(fo: FormatObject): A = fo match {
case x: Header => format(x)
case x: Section => format(x)
......@@ -46,6 +47,7 @@ trait Formatter[A] extends Function[FormatObject, A] {
case x: Join => format(x)
case x: Break => format(x)
}
// scalastyle:on cyclomatic.complexity
}
/** Formatter producing strings; used for CLI output. */
......@@ -104,7 +106,7 @@ class StringFormatter extends Formatter[String] {
/** Formatter producing man page format. */
class ManPageFormatter extends StringFormatter {
override def format(header: Header) =
override def format(header: Header): String =
s".TH ${header.title} ${header.section: Int} ${header.source} ${header.section.manual}"
override def format(section: Section): String =
......
......@@ -25,7 +25,7 @@ private object GlobalOptions {
longOption("logFile") |
longOption("parallel") |
longOption("slurm") |
longOption("maxThreads")
longOption("maxThreads")
).opaque("a global option")
def help: Parser[(String, String)] =
......@@ -81,6 +81,7 @@ private object GlobalOptions {
def globalOptions: Parser[Configuration] =
globalOptionsSeq map (as => mkConfig(as))
// scalastyle:off cyclomatic.complexity
private def mkConfig[A <: Seq[Tuple2[String, _]]](pa: A, c: Option[Configuration] = None): Configuration =
pa match {
case a +: as => a match {
......@@ -101,6 +102,7 @@ private object GlobalOptions {
}
case x => c getOrElse Configuration()
}
// scalastyle:on cyclomatic.complexity
private def readJobsFile(p: Path): Seq[Job] =
Json.fromJson[Seq[Job]](Json.parse(Source.fromFile(p.toString).getLines mkString "")) match {
......
......@@ -6,6 +6,7 @@ sealed abstract class ManSection(private val n: Int, _manual: Option[String] = N
lazy val manual: String = _manual getOrElse "MAN(%d)".format(n)
}
// scalastyle:off magic.number
final case object GeneralCommands extends ManSection(1)
final case object SystemCalls extends ManSection(2)
final case object LibraryFunctions extends ManSection(3)
......@@ -14,6 +15,7 @@ final case object FileFormatsConventions extends ManSection(5)
final case object GamesAndScreensavers extends ManSection(6)
final case object Miscellanea extends ManSection(7)
final case object SysAdminCommands extends ManSection(8)
// scalastyle:on magic.number
object ManSection {
private lazy val numMap: Map[Int, ManSection] = all map (s => (s: Int) -> s) toMap
......@@ -29,7 +31,7 @@ object ManSection {
SysAdminCommands
)
def apply(n: Int) = numMap(n)
def apply(n: Int): ManSection = numMap(n)
implicit def toManSection(n: Int): ManSection = apply(n)
implicit def toInt(s: ManSection): Int = s.n
......
......@@ -4,6 +4,7 @@ import scala.util.Properties.{lineSeparator => NL}
object Usage {
private final val logger = de.tu_darmstadt.cs.esa.tapasco.Logging.logger(getClass)
private final val BINDENT = 74
def apply()(implicit fmt: Formatter[String] = StringFormatter): String = fmt(usage)
......@@ -226,8 +227,9 @@ configuration via `tapasco -n config.json`.
Block("All HLS kernels are located in the directories below the currently" ~
"configured Kernel directory (see `tapasco -h globals`). Each kernel" ~
"requires a description in a simple Json format, examples can be found" ~
"in $TAPASCO_HOME/kernel.", 74)))
"in $TAPASCO_HOME/kernel.", BINDENT)))
// scalastyle:off method.length
private def explore() = Section("Design Space Exploration Job",
Block("Even simple hardware designs often require a surprisingly high number of" ~
"design choices. It is difficult to estimate the impact of each choice on" ~
......@@ -304,7 +306,8 @@ configuration via `tapasco -n config.json`.
Block("All HLS kernels are located in the directories below the currently" ~
"configured Kernel directory (see `tapasco -h globals`). Each kernel" ~
"requires a description in a simple Json format, examples can be found" ~
"in $TAPASCO_HOME/kernel.", 74)))
"in $TAPASCO_HOME/kernel.", BINDENT)))
// scalastyle:on method.length
private def shortJobs() = Section("Jobs",
Arg("", "(see `tapasco -h <job>` for details)") &
......
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