Skip to content

Commit ca063be

Browse files
author
Oron Port
committed
merging constraints and fixing unconnected resource constraints
1 parent f54b94e commit ca063be

File tree

3 files changed

+46
-3
lines changed

3 files changed

+46
-3
lines changed

compiler/ir/src/main/scala/dfhdl/compiler/ir/annotation.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,8 @@ object constraints:
6262
sealed abstract class Constraint extends HWAnnotation derives ReadWriter
6363
sealed abstract class GlobalConstraint extends Constraint derives ReadWriter
6464
sealed abstract class SigConstraint extends Constraint derives ReadWriter:
65+
def merge(that: SigConstraint): Option[SigConstraint] =
66+
if (this == that) Some(this) else None
6567
val bitIdx: ConfigN[Int]
6668
final case class Device(name: String, properties: Map[String, String]) extends GlobalConstraint
6769
derives CanEqual, ReadWriter:
@@ -72,6 +74,31 @@ object constraints:
7274
val props = properties.map { case (k, v) => s""""$k" -> "$v"""" }.mkString(", ")
7375
s"""@device("$name"${props.emptyOr(", " + _)})"""
7476

77+
extension [T](configN: ConfigN[T])
78+
def merge(that: ConfigN[T]): ConfigN[T] =
79+
(configN, that) match
80+
case (None, None) => None
81+
case (t: T @unchecked, None) => t
82+
case (None, t: T @unchecked) => t
83+
case (t1: T @unchecked, t2: T @unchecked) if t1 equals t2 => t1
84+
case x => throw new IllegalArgumentException("Constraint merge error: " + x)
85+
extension (list: List[SigConstraint])
86+
def merge: List[SigConstraint] =
87+
list.foldLeft(List.empty[SigConstraint]) { (acc, cs) =>
88+
var merged = false
89+
val newAcc = acc.map { next =>
90+
if (merged) next
91+
else cs.merge(next) match
92+
case Some(mergedCs) =>
93+
merged = true
94+
mergedCs
95+
case None => next
96+
}
97+
if (merged) newAcc
98+
else cs :: newAcc
99+
}.reverse
100+
end extension
101+
75102
private def csParam[T](name: String, value: ConfigN[T])(using printer: Printer): String =
76103
value match
77104
case None => ""
@@ -93,6 +120,20 @@ object constraints:
93120
protected def `prot_=~`(that: HWAnnotation)(using MemberGetSet): Boolean = this == that
94121
lazy val getRefs: List[DFRef.TwoWayAny] = Nil
95122
def copyWithNewRefs(using RefGen): this.type = this
123+
override def merge(that: SigConstraint): Option[SigConstraint] =
124+
that match
125+
case that: IO if bitIdx == that.bitIdx =>
126+
Some(
127+
IO(
128+
bitIdx = bitIdx,
129+
loc = loc.merge(that.loc),
130+
standard = standard.merge(that.standard),
131+
slewRate = slewRate.merge(that.slewRate),
132+
driveStrength = driveStrength.merge(that.driveStrength),
133+
pullMode = pullMode.merge(that.pullMode)
134+
)
135+
)
136+
case _ => None
96137
def codeString(using Printer): String =
97138
val params = List(
98139
csParam("bitIdx", bitIdx),

core/src/main/scala/dfhdl/platforms/resources/Resource.scala

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ trait Resource extends ResourceContext:
77
private val connections = mutable.ListBuffer[Resource]()
88
protected[resources] def connect(that: Resource): Unit =
99
connections += that
10+
// will always return at least this resource
1011
private lazy val allConnections: List[Resource] =
1112
val visited = mutable.Set[Resource]()
1213
val result = mutable.ListBuffer[Resource]()
@@ -17,10 +18,11 @@ trait Resource extends ResourceContext:
1718
result += conn
1819
dfs(conn)
1920
dfs(this)
20-
result.distinct.toList
21+
val res = result.distinct.toList
22+
if (res.isEmpty) List(this) else res
2123
end allConnections
2224
lazy val allSigConstraints: List[SigConstraint] =
23-
allConnections.flatMap(_.directAndOwnerSigConstraints).distinct
25+
allConnections.flatMap(_.directAndOwnerSigConstraints).merge
2426
owner.addResource(this)
2527
end Resource
2628

core/src/main/scala/dfhdl/platforms/resources/ResourceContext.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ trait ResourceContext extends OnCreateEvents, HasDFC, HasClsMetaArgs:
2222
val ownerConstraints = if (isTopResource) Nil else owner.directAndOwnerSigConstraints
2323
(ownerConstraints ++ getResourceConstraints.collect {
2424
case constraint: SigConstraint => constraint
25-
}).distinct
25+
}).merge
2626
protected def __dfc: DFC =
2727
println("Severe error: missing DFHDL context!\nMake sure you enable the DFHDL compiler plugin.")
2828
sys.exit(1)

0 commit comments

Comments
 (0)