Skip to content

Commit 5bddd33

Browse files
author
Oron Port
committed
<> connection and port/variable construction operation is working under the new single transparent inline method mechanism
1 parent 8f000bf commit 5bddd33

File tree

8 files changed

+39
-79
lines changed

8 files changed

+39
-79
lines changed

core/src/main/scala/dfhdl/core/Container.scala

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,3 @@ abstract class RTDomainContainer(cfg: RTDomainCfg) extends DomainContainer(Domai
5252
DFOpaque(Rst())
5353
end Rst
5454
end RTDomainContainer
55-
56-
object RTDomainContainer:
57-
object Ops:
58-
extension [D <: RTDomainContainer](domain: D)
59-
def <>[R <: Resource](resource: R)(using dfc: DFC, cc: Resource.CanConnect[R, D]): Unit =
60-
cc.connect(resource, domain)

core/src/main/scala/dfhdl/core/DFType.scala

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,6 @@ object DFType:
101101
type Supported = DFTypeAny | FieldsOrTuple | DFEncoding | DFOpaqueA | Byte | Int | Long |
102102
Boolean | Double | String | Object | Unit
103103

104-
object Ops:
105-
extension [T <: Supported](t: T)
106-
infix def <>[A, C, I, P](modifier: Modifier[A, C, I, P])(using
107-
@implicitNotFound("Port/Variable declarations cannot be global") dfc: DFC,
108-
tc: DFType.TC[T],
109-
ck: DFC.Scope.Local,
110-
dt: DomainType
111-
): DFVal[tc.Type, Modifier[A & ck.type & dt.type, C, I, P]] =
112-
trydf:
113-
if (modifier.value.isPort)
114-
dfc.owner.asIR match
115-
case _: ir.DFDomainOwner =>
116-
case _ =>
117-
throw new IllegalArgumentException(
118-
"Ports can only be directly owned by a design, a domain or an interface."
119-
)
120-
DFVal.Dcl(tc(t), modifier.asInstanceOf[Modifier[A & ck.type & dt.type, C, I, P]])
121-
end extension
122-
end Ops
123-
124104
trait TC[T]:
125105
type Type <: DFTypeAny
126106
def apply(t: T)(using DFC): Type

core/src/main/scala/dfhdl/core/DFVal.scala

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1236,25 +1236,30 @@ object DFVal extends DFValLP:
12361236
exactOp2["as", DFC, DFValAny](lhs, aliasType)
12371237
end extension
12381238
extension [L](inline lhs: L)
1239-
transparent inline def <~>[R](inline rhs: R)(using DFC): Any =
1239+
transparent inline def <>[R](inline rhs: R)(using DFC): Any =
12401240
// operator `<>` as a constructor is unidirectional
12411241
// operator `<>` as a connection is bidirectional and commutative
1242-
// TODO: possibly use match on lhs and rhs together fixing scalac issue
1243-
// https://github.com/scala/scala3/issues/24076
1244-
inline lhs match
1245-
case lhs: DFValAny => inline rhs match
1246-
// if both LHS and RHS are DFVals, we call `specialConnect` to handle possible
1247-
// connection in either direction where both implicit directions are available
1248-
// case rhs: DFValAny => ConnectOps.specialConnect(lhs, rhs)
1249-
// otherwise, we invoke the implicit given operation in both directions by turning
1250-
// on the bothWays flag for all other cases
1251-
case _ => exactOp2["<>", DFC, Any](lhs, rhs)
1252-
case _ => inline rhs match
1253-
// if the RHS is a modifier, this is a port/variable constructor,
1254-
// so we invoke the the implicit given operation only in one way
1255-
case _: ModifierAny => exactOp2["<>", DFC, Any](lhs, rhs)
1256-
case _ => exactOp2["<>", DFC, Any](lhs, rhs, bothWays = true)
1257-
end match
1242+
inline val lhsIsDFVal = inline compiletime.erasedValue[L] match
1243+
case _: DFValAny => true
1244+
case _ => false
1245+
inline val rhsIsDFVal = inline compiletime.erasedValue[R] match
1246+
case _: DFValAny => true
1247+
case _ => false
1248+
inline val rhsIsModifier = inline compiletime.erasedValue[R] match
1249+
case _: ModifierAny => true
1250+
case _ => false
1251+
// if both LHS and RHS are DFVals, we call `specialConnect` to handle possible
1252+
// connection in either direction where both implicit directions are available
1253+
inline if (lhsIsDFVal && rhsIsDFVal)
1254+
inline lhs match
1255+
case lhs: DFValAny => inline rhs match
1256+
case rhs: DFValAny => ConnectOps.specialConnect(lhs, rhs)
1257+
// if the RHS is a modifier, this is a port/variable constructor,
1258+
// so we invoke the the implicit given operation only in one way
1259+
else if (rhsIsModifier) exactOp2["<>", DFC, Any](lhs, rhs)
1260+
// otherwise, we invoke the implicit given operation in both directions by turning
1261+
// on the bothWays flag for all other cases
1262+
else exactOp2["<>", DFC, Any](lhs, rhs, bothWays = true)
12581263
end extension
12591264

12601265
extension [T <: DFTypeAny, A, C, I, S <: Int, V](dfVal: DFVal[T, Modifier[A, C, I, Any]])
@@ -1557,21 +1562,22 @@ object ConnectOps:
15571562
inline lhs: L,
15581563
inline rhs: R
15591564
)(using DFC): Unit =
1560-
inline val connectableL = inline lhs match
1565+
inline val connectableL = inline compiletime.erasedValue[L] match
15611566
case _: DFVal[DFTypeAny, Modifier[Any, Modifier.Connectable, Any, Any]] => true
15621567
case _ => false
1563-
inline val connectableR = inline rhs match
1568+
inline val connectableR = inline compiletime.erasedValue[R] match
15641569
case _: DFVal[DFTypeAny, Modifier[Any, Modifier.Connectable, Any, Any]] => true
15651570
case _ => false
15661571
inline if (connectableL || connectableR)
15671572
inline if (IsGiven[TC_Connect[L, R]])
15681573
val tcL = compiletime.summonInline[TC_Connect[L, R]]
15691574
inline if (IsGiven[TC_Connect[R, L]])
15701575
val tcR = compiletime.summonInline[TC_Connect[R, L]]
1571-
// since we have both candidates, we try the RHS first, so if both fail at runtime,
1572-
// the error message will be from the LHS as fallback.
1573-
try tcR.connect(rhs, lhs)
1574-
catch case e: Throwable => tcL.connect(lhs, rhs)
1576+
try tcL.connect(lhs, rhs)
1577+
catch
1578+
case eL: Throwable =>
1579+
try tcR.connect(rhs, lhs)
1580+
catch case eR: Throwable => throw eL
15751581
else tcL.connect(lhs, rhs)
15761582
else if (IsGiven[TC_Connect[R, L]])
15771583
compiletime.summonInline[TC_Connect[R, L]].connect(rhs, lhs)
@@ -1599,17 +1605,6 @@ object ConnectOps:
15991605
def apply(lhs: L, rhs: R)(using DFC): Out = trydf {
16001606
lhs.connect(tc(lhs.dfType, rhs))
16011607
}(using dfc, CTName("<>"))
1602-
extension [T <: DFTypeAny, C](dfPort: DFVal[T, Modifier[Any, C, Any, Any]])
1603-
def <>(rhs: DFVal.TC_Or_OPEN_Or_Resource.Exact[T])(using
1604-
DFC
1605-
)(using
1606-
connectableOnly: ConnectableOnly[C, rhs.ExactFrom]
1607-
): Unit =
1608-
given CTName = CTName("<>")
1609-
trydf {
1610-
rhs.tc.connect(dfPort, rhs.exactFrom)
1611-
}
1612-
end extension
16131608
end ConnectOps
16141609

16151610
extension (dfVal: ir.DFVal)

core/src/main/scala/dfhdl/hdl.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package dfhdl
22
protected object hdl:
33
class dsn extends scala.annotation.StaticAnnotation
44
import core.IntP
5-
export core.DFType.Ops.*
65
export core.DFBoolOrBit.Val.Ops.*
76
export core.DFBits.StrInterpOps.{h, b}
87
export core.DFBits.Val.Ops.*
@@ -25,7 +24,6 @@ protected object hdl:
2524
export internals.CommonOps.*
2625
export core.{dfType}
2726
export core.DFPhysical.Val.Ops.*
28-
export platforms.resources.Resource.Ops.*
2927
export core.COMB_LOOP
3028
type Time = core.DFTime
3129
val Time = core.DFTime
@@ -34,7 +32,6 @@ protected object hdl:
3432
export core.DFRange.Ops.*
3533
export core.Step.Ops.*
3634
export core.Wait.Ops.*
37-
export core.RTDomainContainer.Ops.*
3835
type Step = core.Step
3936
type DFC = core.DFC
4037
val DFC = core.DFC

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

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,15 +81,5 @@ object Resource extends ResourceLP:
8181
def apply(resource1: R, resourceOrValue: T)(using DFC): Out =
8282
cc.connect(resource1, resourceOrValue)
8383
end given
84-
object Ops:
85-
extension [R <: Resource](resource: R)
86-
def <>[T <: Resource](that: T)(using dfc: DFC, cc: CanConnect[R, T]): Unit =
87-
cc.connect(resource, that)
88-
def <>[T <: DFValAny | RTDomainContainer](that: T)(using
89-
dfc: DFC,
90-
cc: CanConnect[R, T]
91-
): Unit = trydf {
92-
cc.connect(resource, that)
93-
}
94-
export Resource.Ops.*
84+
export dfhdl.hdl.<>
9585
end Resource

core/src/test/scala/CoreSpec/DFTypeSpec.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,14 @@ class DFTypeSpec extends DFSpec:
8989
"""z(3, 0).prev"""
9090
)
9191
assertCompileError(
92-
"The LHS of a connection must be a connectable DFHDL value (var/port)."
92+
"At least one of the connection arguments must be a connectable DFHDL value (var/port)."
9393
)(
9494
"""z(3, 0) <> all(0)"""
9595
)
9696
val tplx = tpl <> VAR
9797
tplx._1 := 1
9898
assertCompileError(
99-
"The LHS of a connection must be a connectable DFHDL value (var/port)."
99+
"At least one of the connection arguments must be a connectable DFHDL value (var/port)."
100100
)(
101101
"""tplx._1 <> 1"""
102102
)

core/src/test/scala/CoreSpec/GlobalsSpec.scala

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ import dfhdl.*
33

44
class GlobalsSpec extends NoDFCSpec:
55
test("Global errors") {
6-
assertCompileError("Port/Variable declarations cannot be global")(
6+
assertCompileError(
7+
"Missing local design context.\nEither this operation is not supported in global context or `using DFC` is missing."
8+
)(
79
"""val x = Bit <> VAR"""
810
)
9-
assertCompileError("Port/Variable declarations cannot be global")(
11+
assertCompileError(
12+
"Missing local design context.\nEither this operation is not supported in global context or `using DFC` is missing."
13+
)(
1014
"""val x = Bit <> IN"""
1115
)
1216
}

lib/src/test/scala/ElaborationChecksSpec.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ class ElaborationChecksSpec extends DesignSpec:
158158
|DFiant HDL elaboration error!
159159
|Position: ${currentFilePos}ElaborationChecksSpec.scala:154:19 - 154:28
160160
|Hierarchy: Top.y
161-
|Operation: ``
161+
|Operation: `Port/Variable constructor`
162162
|Message: Ports can only be directly owned by a design, a domain or an interface.
163163
|""".stripMargin
164164
)

0 commit comments

Comments
 (0)