diff options
Diffstat (limited to 'src/main/scala/firrtl/constraint/IsMax.scala')
| -rw-r--r-- | src/main/scala/firrtl/constraint/IsMax.scala | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/constraint/IsMax.scala b/src/main/scala/firrtl/constraint/IsMax.scala new file mode 100644 index 00000000..3f24b7c0 --- /dev/null +++ b/src/main/scala/firrtl/constraint/IsMax.scala @@ -0,0 +1,59 @@ +// See LICENSE for license details. + +package firrtl.constraint + +object IsMax { + def apply(left: Constraint, right: Constraint): Constraint = (left, right) match { + case (l: IsKnown, r: IsKnown) => l max r + case _ => apply(Seq(left, right)) + } + def apply(children: Seq[Constraint]): Constraint = { + val x = children.foldLeft(new IsMax(None, Vector(), Vector())) { (add, c) => + add.addChild(c) + } + x.reduce() + } +} + +case class IsMax private[constraint](known: Option[IsKnown], + mins: Vector[IsMin], + others: Vector[Constraint] + ) extends MultiAry { + + def op(b1: IsKnown, b2: IsKnown): IsKnown = b1 max b2 + + override def serialize: String = "max(" + children.map(_.serialize).mkString(", ") + ")" + + override def map(f: Constraint=>Constraint): Constraint = IsMax(children.map(f)) + + lazy val children: Vector[Constraint] = { + if(known.nonEmpty) known.get +: (mins ++ others) else mins ++ others + } + + def reduce(): Constraint = { + if(children.size == 1) children.head else { + (known, mins, others) match { + case (Some(IsKnown(a)), _, _) => + // Eliminate minimums who have a known minimum value which is smaller than known maximum value + val filteredMins = mins.filter { + case IsMin(Some(IsKnown(i)), _, _) if i <= a => false + case other => true + } + // If a successful filter, rerun reduce + val newMax = new IsMax(known, filteredMins, others) + if(filteredMins.size != mins.size) { + newMax.reduce() + } else newMax + case _ => this + } + } + } + + def addChild(x: Constraint): IsMax = x match { + case k: IsKnown => new IsMax(known = merge(Some(k), known), mins, others) + case max: IsMax => new IsMax(known = merge(known, max.known), max.mins ++ mins, others ++ max.others) + case min: IsMin => new IsMax(known, mins :+ min, others) + case other => new IsMax(known, mins, others :+ other) + } +} + |
