Skip to content

Commit d164df0

Browse files
author
Oron Port
committed
refactor resources to introduce toggle IO inversion and explcit active state
1 parent 40ffaf4 commit d164df0

File tree

11 files changed

+73
-33
lines changed

11 files changed

+73
-33
lines changed

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

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,8 @@ object constraints:
186186
driveStrength: ConfigN[Int] = None,
187187
pullMode: ConfigN[IO.PullMode] = None,
188188
dualPurposeGroups: ConfigN[String] = None,
189-
unusedPullMode: ConfigN[IO.PullMode] = None
189+
unusedPullMode: ConfigN[IO.PullMode] = None,
190+
invertActiveState: ConfigN[Boolean] = None
190191
) extends SigConstraint derives CanEqual, ReadWriter:
191192
protected def `prot_=~`(that: HWAnnotation)(using MemberGetSet): Boolean = this == that
192193
lazy val getRefs: List[DFRef.TwoWayAny] = Nil
@@ -204,7 +205,8 @@ object constraints:
204205
driveStrength = driveStrength.merge(that.driveStrength),
205206
pullMode = pullMode.merge(that.pullMode),
206207
dualPurposeGroups = dualPurposeGroups.merge(that.dualPurposeGroups),
207-
unusedPullMode = unusedPullMode.merge(that.unusedPullMode)
208+
unusedPullMode = unusedPullMode.merge(that.unusedPullMode),
209+
invertActiveState = invertActiveState.merge(that.invertActiveState)
208210
)
209211
)
210212
case _ => None
@@ -220,7 +222,8 @@ object constraints:
220222
csParam("driveStrength", driveStrength),
221223
csParam("pullMode", pullMode),
222224
csParam("dualPurposeGroups", dualPurposeGroups),
223-
csParam("unusedPullMode", unusedPullMode)
225+
csParam("unusedPullMode", unusedPullMode),
226+
csParam("invertActiveState", invertActiveState)
224227
).filter(_.nonEmpty).mkString(", ")
225228
s"""@io($params)"""
226229
end codeString

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1041,25 +1041,32 @@ object DFVal extends DFValLP:
10411041
export DFTuple.Val.TCConv.given
10421042
export DFVector.Val.TCConv.given
10431043

1044-
trait TC_Or_OPEN_Or_Resource[T <: DFTypeAny, R] extends TC[T, R]
1044+
trait TC_Or_OPEN_Or_Resource[T <: DFTypeAny, R] extends TC[T, R]:
1045+
def connect(dfVal: DFValOf[T], that: R)(using DFC): Unit
10451046
object TC_Or_OPEN_Or_Resource:
10461047
type Exact[T <: DFTypeAny] =
10471048
Exact1[DFTypeAny, T, [t <: DFTypeAny] =>> t, DFC, TC_Or_OPEN_Or_Resource]
10481049
given fromOPEN[T <: DFTypeAny]: TC_Or_OPEN_Or_Resource[T, OPEN] with
10491050
type OutP = NOTCONST
10501051
def conv(dfType: T, from: OPEN)(using DFC): Out = DFVal.OPEN(dfType)
1052+
def connect(dfVal: DFValOf[T], that: OPEN)(using DFC): Unit =
1053+
dfVal.connect(conv(dfVal.dfType, that))
10511054
given fromTC[
10521055
T <: DFTypeAny,
10531056
R,
10541057
TC <: DFVal.TC[T, R]
10551058
](using tc: TC): TC_Or_OPEN_Or_Resource[T, R] with
10561059
type OutP = tc.OutP
10571060
def conv(dfType: T, from: R)(using DFC): Out = tc(dfType, from)
1061+
def connect(dfVal: DFValOf[T], that: R)(using DFC): Unit =
1062+
dfVal.connect(conv(dfVal.dfType, that))
10581063
given fromResource[T <: DFTypeAny, R <: Resource](using
1059-
Resource.CanConnect[R, DFValOf[T]] // just type checking
1064+
cc: Resource.CanConnect[R, DFValOf[T]]
10601065
): TC_Or_OPEN_Or_Resource[T, R] with
10611066
type OutP = NOTCONST
10621067
def conv(dfType: T, from: R)(using DFC): Out = ???
1068+
def connect(dfVal: DFValOf[T], that: R)(using DFC): Unit =
1069+
cc.connect(that, dfVal)
10631070
end TC_Or_OPEN_Or_Resource
10641071

10651072
trait Compare[T <: DFTypeAny, V, Op <: FuncOp, C <: Boolean] extends TCCommon[T, V, DFValAny]:
@@ -1443,9 +1450,7 @@ object DFPortOps:
14431450
): ConnectPlaceholder =
14441451
given CTName = CTName("<>")
14451452
trydf {
1446-
rhs.exactFrom match
1447-
case resource: Resource => resource.connect(dfPort)
1448-
case _ => dfPort.connect(rhs(dfPort.dfType))
1453+
rhs.tc.connect(dfPort, rhs.exactFrom)
14491454
}
14501455
ConnectPlaceholder
14511456
end extension

core/src/main/scala/dfhdl/hw/annotation.scala

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,13 @@ object constraints:
101101
driveStrength: ir.ConfigN[Int] = None,
102102
pullMode: ir.ConfigN[io.PullMode] = None,
103103
dualPurposeGroups: ir.ConfigN[String] = None,
104-
unusedPullMode: ir.ConfigN[io.PullMode] = None
104+
unusedPullMode: ir.ConfigN[io.PullMode] = None,
105+
invertActiveState: ir.ConfigN[Boolean] = None
105106
) extends SigConstraint:
106107
val asIR: ir.constraints.IO =
107108
ir.constraints.IO(
108109
bitIdx, loc, levelVolt, standard, slewRate, driveStrength, pullMode, dualPurposeGroups,
109-
unusedPullMode
110+
unusedPullMode, invertActiveState
110111
)
111112
end io
112113
object io:

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ trait ResourceContext extends OnCreateEvents, HasDFC, HasClsMetaArgs:
3939
protected def __dfc: DFC =
4040
println("Severe error: missing DFHDL context!\nMake sure you enable the DFHDL compiler plugin.")
4141
sys.exit(1)
42-
protected def injectConstraint(constraint: Constraint): Unit =
42+
final protected[resources] def injectConstraint(constraint: Constraint): this.type =
4343
resourceConstraints += constraint
44+
this
4445
protected def setClsNamePos(
4546
name: String,
4647
position: Position,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package dfhdl.platforms.resources
2+
import dfhdl.Encoded.Toggle
3+
import dfhdl.core.*
4+
import Resource.CanConnect
5+
import dfhdl.internals.*
6+
import dfhdl.compiler.ir.constraints
7+
8+
trait ToggleIO[T <: Toggle] extends IO:
9+
val activeState: T
10+
11+
object ToggleIO:
12+
given [T <: Toggle, R <: ToggleIO[T], V <: DFValOf[DFBoolOrBit]](using
13+
dfc: DFC,
14+
t: ShowType[T]
15+
)(using
16+
expectedActiveState: GivenOrError[
17+
ExpectedActiveState[T],
18+
"Missing implicit expected active state for toggle resource `" +
19+
t.Out +
20+
"`.\nTo fix this, add:\n `given ExpectedActiveState[" + t.Out + "] = " + t.Out + ".EXPECTED_ACTIVE_STATE`"
21+
]
22+
): CanConnect[R, V] = (resource: R, dfVal: V) =>
23+
resource.injectConstraint(constraints.IO(invertActiveState =
24+
resource.activeState != expectedActiveState.value
25+
)).connect(dfVal)
26+
end ToggleIO
27+
28+
opaque type ExpectedActiveState[T <: Toggle] <: T = T
29+
object ExpectedActiveState:
30+
given [T <: Toggle]: Conversion[T, ExpectedActiveState[T]] = identity

internals/src/main/scala/dfhdl/internals/helpers.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,15 @@ object OptionalGiven extends OptionalGivenLP:
278278
given fromValue[T](using t: T): OptionalGiven[T] with
279279
val value: Option[T] = Some(t)
280280

281+
trait GivenOrError[T, Msg <: String]:
282+
val value: T
283+
protected trait GivenOrErrorLP:
284+
inline given [T, Msg <: String](using ValueOf[Msg]): GivenOrError[T, Msg] =
285+
compiletime.error(valueOf[Msg])
286+
object GivenOrError extends GivenOrErrorLP:
287+
given fromValue[T, Msg <: String](using t: T): GivenOrError[T, Msg] with
288+
val value: T = t
289+
281290
trait IsGiven[T]:
282291
type Out <: Boolean
283292
val value: Out

lib/src/main/scala/dfhdl/platforms/resources/Button.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ enum Button extends Encoded.Toggle:
77

88
object Button:
99
@io(standard = io.Standard.LVCMOS)
10-
class Resource(val activeState: Button = Button.Pressed) extends ToggleIO
10+
class Resource(val activeState: Button = Button.Pressed) extends ToggleIO[Button]

lib/src/main/scala/dfhdl/platforms/resources/IOBus.scala

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,9 @@ import Resource.CanConnect
99
class IOBus[T <: IO, L <: Int] private (val ios: List[T]) extends ResourceDeps:
1010
def apply(i: Int): T = ios(i)
1111
lazy val upstreamDeps: List[Resource] = ios
12-
@dfhdl.internals.metaContextIgnore
13-
override protected[dfhdl] def connect(that: DFValAny)(using dfc: DFC): Unit =
14-
import dfc.getSet
15-
assert(ios.length == that.asIR.width, "Width mismatch")
16-
for (i <- 0 until ios.length)
17-
ios(i).connect(that.bits(i))
18-
end connect
1912
object IOBus:
20-
def fill[L <: Int & Singleton](length: L)(f: => IO)(using dfc: DFC): IOBus[IO, L] =
21-
forced[IO, L](List.tabulate(length)(i => f.injectID(s"${dfc.getMeta.name}($i)")))
13+
def fill[T <: IO, L <: Int & Singleton](length: L)(f: => T)(using dfc: DFC): IOBus[T, L] =
14+
forced[T, L](List.tabulate(length)(i => f.injectID(s"${dfc.getMeta.name}($i)")))
2215
private def forced[T <: IO, L <: Int](ios: List[T])(using DFC): IOBus[T, L] =
2316
new IOBus[T, L](ios.toList)
2417
transparent inline def apply[T <: IO](inline ios: T*): IOBus[T, ?] = ${ applyMacro[T]('ios) }
@@ -42,6 +35,9 @@ object IOBus:
4235
dfc: DFC,
4336
wT: Width[T]
4437
)(using
45-
check: AssertGiven[RL =:= wT.OutI, "Width mismatch"]
46-
): CanConnect[R, V] = (resource: R, dfVal: V) => resource.connect(dfVal)
38+
check: AssertGiven[RL =:= wT.OutI, "Width mismatch"],
39+
cc: CanConnect[RT, DFValOf[DFBit]]
40+
): CanConnect[R, V] = (resource: R, dfVal: V) =>
41+
for (i <- 0 until resource.ios.length)
42+
cc.connect(resource.ios(i), dfVal.bits(i))
4743
end IOBus

lib/src/main/scala/dfhdl/platforms/resources/Led.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@ import dfhdl.compiler.ir.constraints.IO
55
enum Led extends Encoded.Toggle:
66
case Off, On
77
object Led:
8-
class Resource(val activeState: Led = Led.On) extends ToggleIO:
8+
class Resource(val activeState: Led = Led.On) extends ToggleIO[Led]:
99
private val pullMode = if (activeState == Led.On) IO.PullMode.DOWN else IO.PullMode.UP
1010
injectConstraint(IO(standard = IO.Standard.LVCMOS, unusedPullMode = pullMode))

lib/src/main/scala/dfhdl/platforms/resources/Switches.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,22 @@ enum SwitchUD extends Encoded.Toggle:
66
case Down, Up
77
object SwitchUD:
88
@io(standard = io.Standard.LVCMOS)
9-
class Resource(val activeState: SwitchUD = SwitchUD.Up) extends ToggleIO
9+
class Resource(val activeState: SwitchUD = SwitchUD.Up) extends ToggleIO[SwitchUD]
1010

1111
enum SwitchRL extends Encoded.Toggle:
1212
case Left, Right
1313
object SwitchRL:
1414
@io(standard = io.Standard.LVCMOS)
15-
class Resource(val activeState: SwitchRL = SwitchRL.Right) extends ToggleIO
15+
class Resource(val activeState: SwitchRL = SwitchRL.Right) extends ToggleIO[SwitchRL]
1616

1717
enum SwitchNS extends Encoded.Toggle:
1818
case South, North
1919
object SwitchNS:
2020
@io(standard = io.Standard.LVCMOS)
21-
class Resource(val activeState: SwitchNS = SwitchNS.North) extends ToggleIO
21+
class Resource(val activeState: SwitchNS = SwitchNS.North) extends ToggleIO[SwitchNS]
2222

2323
enum SwitchEW extends Encoded.Toggle:
2424
case West, East
2525
object SwitchEW:
2626
@io(standard = io.Standard.LVCMOS)
27-
class Resource(val activeState: SwitchEW = SwitchEW.East) extends ToggleIO
27+
class Resource(val activeState: SwitchEW = SwitchEW.East) extends ToggleIO[SwitchEW]

0 commit comments

Comments
 (0)