Skip to content
This repository has been archived by the owner on Jun 16, 2024. It is now read-only.

Commit

Permalink
inversions working.
Browse files Browse the repository at this point in the history
  • Loading branch information
kivikakk committed May 21, 2024
1 parent 0c79d5e commit 6708c02
Show file tree
Hide file tree
Showing 8 changed files with 63 additions and 27 deletions.
16 changes: 8 additions & 8 deletions src/main/scala/ee/hrzn/chryse/platform/ice40/ICE40Top.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package ee.hrzn.chryse.platform.ice40

import chisel3._
import chisel3.experimental.noPrefix
import chisel3.experimental.dataview._
import chisel3.experimental.noPrefix
import chisel3.util._
import chisel3.util.experimental.forceName
import ee.hrzn.chryse.ChryseModule
Expand Down Expand Up @@ -53,7 +53,6 @@ class ICE40Top[Top <: Module](
private val top =
withClockAndReset(clk, finalReset)(Module(genTop))

// TODO: get clock from "defaultClock", hook that up to the SB_GB.
// TODO: allow clock override.
// TODO: refactor this out to a non-ICE40Top level.
val sb = new StringBuilder
Expand All @@ -62,24 +61,25 @@ class ICE40Top[Top <: Module](
f.setAccessible(true)
f.get(platform.resources) match {
case clock: resource.ClockSource =>
if (clock.inst.isDefined) {
if (clock.ioInst.isDefined) {
throw new Exception("clock must be manually handled for now")
}
// NOTE: we can't just say clki := platform.resources.clock in our top
// here, since that'll define an input IO in *this* module which we
// can't then sink like we would in the resource.Base[_] case.
sb.append(s"set_io $name ${clock.pinId.get}\n")
clki := IO(Input(Clock())).suggestName(name)
val io = IO(Input(Clock())).suggestName(name)
clki := io

case res: resource.Base[_] =>
if (res.inst.isDefined) {
if (res.ioInst.isDefined) {
sb.append(s"set_io $name ${res.pinId.get}\n")
val io = res.make()
val io = IO(res.makeIo()).suggestName(name)
DirectionOf(io) match {
case SpecifiedDirection.Input =>
res.inst.get := IO(io).suggestName(name)
res.ioInst.get.top := io
case SpecifiedDirection.Output =>
IO(io).suggestName(name) := res.inst.get
io := res.ioInst.get.top
case dir =>
throw new Exception(s"unhandled direction: $dir")
}
Expand Down
25 changes: 16 additions & 9 deletions src/main/scala/ee/hrzn/chryse/platform/resource/Base.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,24 @@ package ee.hrzn.chryse.platform.resource
import chisel3._

trait Base[HW <: Data] {
private[chryse] var pinId: Option[Pin] = None
private[chryse] var name: Option[String] = None
final private[chryse] var pinId: Option[Pin] = None
final private[chryse] var name: Option[String] = None

private[chryse] var inst: Option[HW] = None
private[chryse] def make(): HW
// Should return Input/Output Chisel datatype.
private[chryse] def makeIo(): HW

private[chryse] def instOrMake(): HW = {
inst match {
final private[chryse] var ioInst: Option[InstSides[HW]] = None

/* Instantiate an IO in the module at the point of connection. These will be
* connected by the platform toplevel (which implies they can only be used in
* the user toplevel). */
private[chryse] def ioInstOrMake(): InstSides[HW] = {
ioInst match {
case Some(r) => r
case None =>
val r = IO(make()).suggestName(s"${name.get}_int")
inst = Some(r)
inst.get
val r = IO(makeIo()).suggestName(s"${name.get}_int")
ioInst = Some(InstSides(r, r))
ioInst.get
}
}

Expand All @@ -24,3 +29,5 @@ trait Base[HW <: Data] {
this
}
}

case class InstSides[HW](user: HW, top: HW)
6 changes: 3 additions & 3 deletions src/main/scala/ee/hrzn/chryse/platform/resource/BaseIn.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import chisel3.experimental.dataview._
import scala.language.implicitConversions

class BaseIn[HW <: Data](gen: => HW) extends Base[HW] {
private[chryse] def make(): HW = Input(gen)
private[chryse] def makeIo(): HW = Input(gen)

object Implicits {
implicit val BaseInProduct: DataProduct[BaseIn[HW]] =
Expand All @@ -15,11 +15,11 @@ class BaseIn[HW <: Data](gen: => HW) extends Base[HW] {
res: BaseIn[HW],
path: String,
): Iterator[(Data, String)] =
List(res.inst.get -> path).iterator
List(res.ioInst.get.user -> path).iterator
}

implicit def view: DataView[BaseIn[HW], HW] =
DataView(res => gen, _.instOrMake() -> _)
DataView(res => gen, _.ioInstOrMake().user -> _)

implicit def BaseIn2HW(res: BaseIn[HW]): HW =
res.viewAs[HW]
Expand Down
6 changes: 3 additions & 3 deletions src/main/scala/ee/hrzn/chryse/platform/resource/BaseOut.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import chisel3.experimental.dataview._
import scala.language.implicitConversions

class BaseOut[HW <: Data](gen: => HW) extends Base[HW] {
private[chryse] def make(): HW = Output(gen)
private[chryse] def makeIo(): HW = Output(gen)

object Implicits {
implicit val BaseOutProduct: DataProduct[BaseOut[HW]] =
Expand All @@ -15,11 +15,11 @@ class BaseOut[HW <: Data](gen: => HW) extends Base[HW] {
res: BaseOut[HW],
path: String,
): Iterator[(Data, String)] =
List(res.inst.get -> path).iterator
List(res.ioInst.get.user -> path).iterator
}

implicit def view: DataView[BaseOut[HW], HW] =
DataView(res => gen, _.instOrMake() -> _)
DataView(res => gen, _.ioInstOrMake().user -> _)

implicit def BaseOut2HW(res: BaseOut[HW]): HW =
res.viewAs[HW]
Expand Down
13 changes: 12 additions & 1 deletion src/main/scala/ee/hrzn/chryse/platform/resource/Button.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,23 @@ package ee.hrzn.chryse.platform.resource
import chisel3._

class Button extends BaseIn[Bool](Bool()) {
private var invert = false // TODO: invert should do something, and possibly belongs in a higher class
private var invert = false // TODO: possibly belongs in a higher class

def inverted: this.type = {
invert = true
this
}

override private[chryse] def ioInstOrMake(): InstSides[Bool] = {
ioInst match {
case Some(r) => r
case None =>
val top = IO(makeIo()).suggestName(s"${name.get}_int")
val user = if (!invert) top else ~top
ioInst = Some(InstSides(user, top))
ioInst.get
}
}
}

object Button {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import chisel3._
import chisel3.experimental.Analog

class InOut extends Base[Analog] {
private[chryse] def make(): Analog = Analog(1.W)
private[chryse] def makeIo(): Analog = Analog(1.W)
}

object InOut {
Expand Down
18 changes: 17 additions & 1 deletion src/main/scala/ee/hrzn/chryse/platform/resource/LED.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,28 @@ package ee.hrzn.chryse.platform.resource
import chisel3._

class LED extends BaseOut[Bool](Bool()) {
private var invert = false // TODO: invert should do something, and possibly belongs in a higher class
private var invert = false // TODO: possibly belongs in a higher class

def inverted: this.type = {
invert = true
this
}

override private[chryse] def ioInstOrMake(): InstSides[Bool] = {
ioInst match {
case Some(r) => r
case None =>
val top = IO(makeIo()).suggestName(s"${name.get}_int")
val user = Wire(Bool()).suggestName(s"${name.get}_inv")
if (!invert) {
top := user
} else {
top := ~user
}
ioInst = Some(InstSides(user, top))
ioInst.get
}
}
}

object LED {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@ import chisel3._
import circt.stage.ChiselStage
import ee.hrzn.chryse.ChryseModule
import ee.hrzn.chryse.chisel.BuilderContext
import ee.hrzn.chryse.platform.ice40.ICE40Top
import ee.hrzn.chryse.platform.ice40.IceBreakerPlatform
import ee.hrzn.chryse.platform.resource.BaseInBool.Implicits._
import ee.hrzn.chryse.platform.resource.BaseOutBool.Implicits._
import org.scalatest.flatspec.AnyFlatSpec
import org.scalatest.matchers.should._
import ee.hrzn.chryse.platform.ice40.ICE40Top

class BoardResourcesSpec extends AnyFlatSpec with Matchers {
behavior.of("BoardResources")
Expand Down Expand Up @@ -41,6 +41,8 @@ class BoardResourcesSpec extends AnyFlatSpec with Matchers {
|set_io uart_tx 9
|set_io ubtn 10""".stripMargin,
)
// XXX: we aren't generating input names correctly. (¿Sometimes?)
// Test for this.
rtl should include("ledg_int = view__ubtn_int")
(rtl should not).include("uart_tx_int = view__ubtn_int")
rtl should include("uart_tx_int = ~view__ubtn_int")
Expand Down

0 comments on commit 6708c02

Please sign in to comment.