1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
// SPDX-License-Identifier: Apache-2.0
package firrtl.constraint
object IsMin {
def apply(left: Constraint, right: Constraint): Constraint = (left, right) match {
case (l: IsKnown, r: IsKnown) => l.min(r)
case _ => apply(Seq(left, right))
}
def apply(children: Seq[Constraint]): Constraint = {
children
.foldLeft(new IsMin(None, Vector(), Vector())) { (add, c) =>
add.addChild(c)
}
.reduce()
}
}
case class IsMin private[constraint] (known: Option[IsKnown], maxs: Vector[IsMax], others: Vector[Constraint])
extends MultiAry {
def op(b1: IsKnown, b2: IsKnown): IsKnown = b1.min(b2)
override def serialize: String = "min(" + children.map(_.serialize).mkString(", ") + ")"
override def map(f: Constraint => Constraint): Constraint = IsMin(children.map(f))
lazy val children: Vector[Constraint] = {
if (known.nonEmpty) known.get +: (maxs ++ others) else maxs ++ others
}
def reduce(): Constraint = {
if (children.size == 1) children.head
else {
(known, maxs, others) match {
case (Some(IsKnown(i)), _, _) =>
// Eliminate maximums who have a known maximum value which is larger than known minimum value
val filteredMaxs = maxs.filter {
case IsMax(Some(IsKnown(a)), _, _) if a >= i => false
case other => true
}
// If a successful filter, rerun reduce
val newMin = new IsMin(known, filteredMaxs, others)
if (filteredMaxs.size != maxs.size) {
newMin.reduce()
} else newMin
case _ => this
}
}
}
def addChild(x: Constraint): IsMin = x match {
case k: IsKnown => new IsMin(merge(Some(k), known), maxs, others)
case max: IsMax => new IsMin(known, maxs :+ max, others)
case min: IsMin => new IsMin(merge(min.known, known), maxs ++ min.maxs, others ++ min.others)
case other => new IsMin(known, maxs, others :+ other)
}
}
|