Commit cfe59f6e authored by Lukas Sommer's avatar Lukas Sommer
Browse files

Adapt calculation of feasible compositions to consider slot occupancy;

parent e648f0ac
Pipeline #1241 passed with stages
in 155 minutes and 37 seconds
...@@ -37,11 +37,13 @@ ...@@ -37,11 +37,13 @@
* @authors J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de) * @authors J. Korinth, TU Darmstadt (jk@esa.cs.tu-darmstadt.de)
**/ **/
package de.tu_darmstadt.cs.esa.tapasco.dse package de.tu_darmstadt.cs.esa.tapasco.dse
import de.tu_darmstadt.cs.esa.tapasco.base._ import de.tu_darmstadt.cs.esa.tapasco.base._
import de.tu_darmstadt.cs.esa.tapasco.filemgmt.FileAssetManager import de.tu_darmstadt.cs.esa.tapasco.filemgmt.FileAssetManager
import de.tu_darmstadt.cs.esa.tapasco.util.LogFormatter._ import de.tu_darmstadt.cs.esa.tapasco.util.LogFormatter._
import java.nio.file.{Paths} import java.nio.file.Paths
import Heuristics._
import Heuristics._
import de.tu_darmstadt.cs.esa.tapasco.util.SlotOccupation
class DesignSpace( class DesignSpace(
bd: Composition, bd: Composition,
...@@ -80,34 +82,40 @@ class DesignSpace( ...@@ -80,34 +82,40 @@ class DesignSpace(
val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target)) val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target))
val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) } val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) }
val areaEstimates = srs flatMap (_.area) val areaEstimates = srs flatMap (_.area)
val slotOccupations = srs map (r => SlotOccupation(r.slaves.get, target.pd.slotCount))
val targetUtil = target.pd.targetUtilization.toDouble val targetUtil = target.pd.targetUtilization.toDouble
logger.trace("target util = " + targetUtil) logger.trace("target util = " + targetUtil)
def slotUtil(counts : Seq[Int]) : SlotOccupation = (slotOccupations zip counts).map(o => o._1 * o._2).reduce(_ + _)
// check if there is any feasible composition // check if there is any feasible composition
if (minCounts.reduce(_ + _) > target.pd.slotCount) { if (!slotUtil(minCounts).isFeasible) {
throw new Exception("Composition infeasible! Exceeds maximal slot count of " + target.pd.slotCount throw new Exception("Composition infeasible! Exceeds maximal slot count of " + target.pd.slotCount
+ " for " + target + "." + NL + bd) + " for " + target + "." + NL + bd)
} }
def areaUtil(counts: Seq[Int]) = (areaEstimates zip counts) map (a => a._1 * a._2) reduce (_ + _) def areaUtil(counts: Seq[Int]) = (areaEstimates zip counts) map (a => a._1 * a._2) reduce(_ + _)
val currUtil = areaUtil(minCounts).utilization
// compute number of steps // compute number of steps
val currUtil = areaUtil(minCounts).utilization
val df: Int = Seq(java.lang.Math.round((targetUtil - currUtil) / currUtil).toInt, 1).max val df: Int = Seq(java.lang.Math.round((targetUtil - currUtil) / currUtil).toInt, 1).max
val currSlots = slotUtil(minCounts).slots
val targetSlots = target.pd.slotCount
val sf : Int = Math.max(Math.round(targetSlots.toDouble/currSlots.toDouble), 1).toInt
val steps = Math.min(sf, df)
logger.trace("minCounts = " + minCounts + " currUtil = " + currUtil) logger.trace("minCounts = " + minCounts + " currUtil = " + currUtil)
// compute feasible sequences as multiples of minCounts // compute feasible sequences as multiples of minCounts
val seqs = (for (i <- df to 1 by -1) val seqs = (for (i <- steps to 1 by -1)
yield minCounts map (n => i * n)) filter (c => areaUtil(c).isFeasible) yield minCounts map (n => i * n)) filter (c => areaUtil(c).isFeasible && slotUtil(c).isFeasible)
logger.trace("number of feasible counts: " + seqs.length) logger.trace("number of feasible counts: " + seqs.length)
if (seqs.length == 0) { if (seqs.isEmpty) {
logger.warn("No feasible composition found; please check starting composition ratios: " + NL + bd) logger.warn("No feasible composition found; please check starting composition ratios: " + NL + bd)
} }
// make sequence of CompositionEntries // make sequence of CompositionEntries
val ces = for { val ces = for {
s <- seqs filter (_.reduce(_ + _) <= target.pd.slotCount) s <- seqs filter (_.sum <= target.pd.slotCount)
} yield bd.composition.map(_.kernel) zip s map (x => Composition.Entry(x._1, x._2)) } yield bd.composition.map(_.kernel) zip s map (x => Composition.Entry(x._1, x._2))
// make full composition // make full composition
...@@ -123,7 +131,7 @@ class DesignSpace( ...@@ -123,7 +131,7 @@ class DesignSpace(
feasibleAlternatives(bd) map (feasibleCompositions(_)) reduce (_++_) feasibleAlternatives(bd) map (feasibleCompositions(_)) reduce (_++_)
lazy val enumerate: Seq[DesignSpace.Element] = (for { lazy val enumerate: Seq[DesignSpace.Element] = (for {
bd <- compositions(bd); bd <- compositions(bd)
f <- feasibleFreqs(bd) f <- feasibleFreqs(bd)
} yield DesignSpace.Element(bd, f, heuristic(bd, f, target)(cfg))) sortBy (_.h) reverse } yield DesignSpace.Element(bd, f, heuristic(bd, f, target)(cfg))) sortBy (_.h) reverse
...@@ -162,7 +170,7 @@ object DesignSpace { ...@@ -162,7 +170,7 @@ object DesignSpace {
val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target)) val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target))
val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) } val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) }
val cps = srs flatMap (_.timing) map (_.clockPeriod) val cps = srs flatMap (_.timing) map (_.clockPeriod)
val fmax = if (cps.length > 0) 1000.0 / cps.max else Double.PositiveInfinity val fmax = if (cps.nonEmpty) 1000.0 / cps.max else Double.PositiveInfinity
target.pd.supportedFrequencies map (_.toDouble) filter (_ <= fmax) sortWith (_>_) target.pd.supportedFrequencies map (_.toDouble) filter (_ <= fmax) sortWith (_>_)
} }
...@@ -172,39 +180,45 @@ object DesignSpace { ...@@ -172,39 +180,45 @@ object DesignSpace {
val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target)) val cores = bd.composition flatMap (ce => FileAssetManager.entities.core(ce.kernel, target))
val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) } val srs = cores flatMap { c: Core => FileAssetManager.reports.synthReport(c.name, target) }
val areaEstimates = srs flatMap (_.area) val areaEstimates = srs flatMap (_.area)
val slotOccupations = srs map (r => SlotOccupation(r.slaves.get, target.pd.slotCount))
val targetUtil = target.pd.targetUtilization.toDouble val targetUtil = target.pd.targetUtilization.toDouble
logger.trace("target util = " + targetUtil) logger.trace("target util = " + targetUtil)
def slotUtil(counts : Seq[Int]) : SlotOccupation = (slotOccupations zip counts).map(o => o._1 * o._2).reduce(_ + _)
// check if there is any feasible composition // check if there is any feasible composition
if ((minCounts fold 0) (_ + _) > target.pd.slotCount) { if (!slotUtil(minCounts).isFeasible) {
throw new Exception("Composition infeasible! Exceeds maximal slot count of " + target.pd.slotCount throw new Exception("Composition infeasible! Exceeds maximal slot count of " + target.pd.slotCount
+ " for " + target + "." + NL + bd) + " for " + target + "." + NL + bd)
} }
def areaUtil(counts: Seq[Int]) = (areaEstimates zip counts) map (a => a._1 * a._2) reduce (_ + _) def areaUtil(counts: Seq[Int]) = (areaEstimates zip counts) map (a => a._1 * a._2) reduce(_ + _)
val currUtil = areaUtil(minCounts).utilization
// compute number of steps // compute number of steps
val currUtil = areaUtil(minCounts).utilization
val df: Int = Seq(java.lang.Math.round((targetUtil - currUtil) / currUtil).toInt, 1).max val df: Int = Seq(java.lang.Math.round((targetUtil - currUtil) / currUtil).toInt, 1).max
val currSlots = slotUtil(minCounts).slots
val targetSlots = target.pd.slotCount
val sf : Int = Math.max(Math.round(targetSlots.toDouble/currSlots.toDouble), 1).toInt
val steps = Math.min(sf, df)
logger.trace("minCounts = " + minCounts + " currUtil = " + currUtil) logger.trace("minCounts = " + minCounts + " currUtil = " + currUtil)
// compute feasible sequences as multiples of minCounts // compute feasible sequences as multiples of minCounts
val seqs = (for (i <- df to 1 by -1) val seqs = (for (i <- steps to 1 by -1)
yield minCounts map (n => i * n)) filter (c => areaUtil(c).isFeasible) yield minCounts map (n => i * n)) filter (c => areaUtil(c).isFeasible && slotUtil(c).isFeasible)
logger.trace("number of feasible counts: " + seqs.length) logger.trace("number of feasible counts: " + seqs.length)
if (seqs.length == 0) { if (seqs.isEmpty) {
logger.warn("No feasible composition found; please check starting composition ratios: " + NL + bd) logger.warn("No feasible composition found; please check starting composition ratios: " + NL + bd)
} }
// make sequence of CompositionEntries // make sequence of CompositionEntries
val ces = for { val ces = for {
s <- seqs filter (_.reduce(_ + _) <= target.pd.slotCount) s <- seqs filter (_.sum <= target.pd.slotCount)
} yield bd.composition.map(_.kernel) zip s map (x => Composition.Entry(x._1, x._2)) } yield bd.composition.map(_.kernel) zip s map (x => Composition.Entry(x._1, x._2))
// make full composition // make full composition
ces map (Composition(Paths.get("N/A"), Some("Generated composition."), _)) ces map (Composition(Paths.get("N/A"), Some("Generated composition."), _))
} else { } else {
Seq() Seq.empty
} }
} }
...@@ -90,3 +90,17 @@ final case class AreaEstimate( ...@@ -90,3 +90,17 @@ final case class AreaEstimate(
def isFeasible: Boolean = List(slice, lut, ff, dsp, bram).map(x => x <= 100.0).reduce(_&&_) def isFeasible: Boolean = List(slice, lut, ff, dsp, bram).map(x => x <= 100.0).reduce(_&&_)
def compare(that: AreaEstimate): Int = this.resources compare that.resources def compare(that: AreaEstimate): Int = this.resources compare that.resources
} }
/**
* Occupation of slots of a hardware design
* @param slots Number of occupied slots
* @param available Number of available slots
*/
final case class SlotOccupation(slots : Int, available : Int) extends Ordered[SlotOccupation] {
override def toString: String = "SlotOccupation: %d/%d\n".format(slots, available)
def *(n : Int) : SlotOccupation = SlotOccupation(slots * n, available)
def +(s : SlotOccupation) : SlotOccupation = SlotOccupation(slots + s.slots, available)
def isFeasible : Boolean = slots <= available
override def compare(that: SlotOccupation): Int = this.slots compare that.slots
}
Markdown is supported
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