From 9c7d1ad7c4c5ac523493ca78c5bd955d3820d0c5 Mon Sep 17 00:00:00 2001 From: Asherah Connor Date: Thu, 23 May 2024 21:43:30 +0300 Subject: [PATCH] extract resource transforms. --- .../hrzn/chryse/platform/ice40/ICE40Top.scala | 14 +------- .../chryse/platform/resource/Button.scala | 14 ++------ .../hrzn/chryse/platform/resource/LED.scala | 19 ++-------- .../platform/resource/ResourceData.scala | 35 +++++++++++++------ .../scala/ee/hrzn/chryse/tasks/BaseTask.scala | 1 + .../platform/PlatformBoardResourcesSpec.scala | 12 +++++-- 6 files changed, 42 insertions(+), 53 deletions(-) diff --git a/src/main/scala/ee/hrzn/chryse/platform/ice40/ICE40Top.scala b/src/main/scala/ee/hrzn/chryse/platform/ice40/ICE40Top.scala index d3c6f98..a11834e 100644 --- a/src/main/scala/ee/hrzn/chryse/platform/ice40/ICE40Top.scala +++ b/src/main/scala/ee/hrzn/chryse/platform/ice40/ICE40Top.scala @@ -1,17 +1,13 @@ package ee.hrzn.chryse.platform.ice40 import chisel3._ -import chisel3.experimental.dataview._ import chisel3.experimental.noPrefix import chisel3.util._ import chisel3.util.experimental.forceName -import ee.hrzn.chryse.chisel.DirectionOf -import ee.hrzn.chryse.platform.Platform import ee.hrzn.chryse.platform.PlatformBoard import ee.hrzn.chryse.platform.PlatformBoardResources import ee.hrzn.chryse.platform.resource -import java.lang.reflect.Modifier import scala.collection.mutable class ICE40Top[Top <: Module]( @@ -86,15 +82,7 @@ class ICE40Top[Top <: Module]( if (res.ioInst.isDefined) { ios += name -> res.pinId.get - val io = IO(res.makeIo()).suggestName(name) - DirectionOf(io) match { - case SpecifiedDirection.Input => - res.ioInst.get.top := io - case SpecifiedDirection.Output => - io := res.ioInst.get.top - case dir => - throw new Exception(s"unhandled direction: $dir") - } + res.makeIoConnection() } } } diff --git a/src/main/scala/ee/hrzn/chryse/platform/resource/Button.scala b/src/main/scala/ee/hrzn/chryse/platform/resource/Button.scala index 5d65979..2b119a2 100644 --- a/src/main/scala/ee/hrzn/chryse/platform/resource/Button.scala +++ b/src/main/scala/ee/hrzn/chryse/platform/resource/Button.scala @@ -3,23 +3,15 @@ package ee.hrzn.chryse.platform.resource import chisel3._ class Button extends ResourceData[Bool](Input(Bool())) { - private var invert = false // TODO: invert possibly belongs in a higher class + private var invert = false 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 - } - } + override def connectIo(user: Bool, top: Bool) = + user := (if (!invert) top else ~top) } object Button { diff --git a/src/main/scala/ee/hrzn/chryse/platform/resource/LED.scala b/src/main/scala/ee/hrzn/chryse/platform/resource/LED.scala index f7d1775..9669831 100644 --- a/src/main/scala/ee/hrzn/chryse/platform/resource/LED.scala +++ b/src/main/scala/ee/hrzn/chryse/platform/resource/LED.scala @@ -3,28 +3,15 @@ package ee.hrzn.chryse.platform.resource import chisel3._ class LED extends ResourceData[Bool](Output(Bool())) { - private var invert = false // TODO: invert possibly belongs in a higher class + private var invert = false 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(makeIo()).suggestName(s"${name.get}_inv") - if (!invert) { - top := user - } else { - top := ~user - } - ioInst = Some(InstSides(user, top)) - ioInst.get - } - } + override def connectIo(user: Bool, top: Bool) = + top := (if (!invert) user else ~user) } object LED { diff --git a/src/main/scala/ee/hrzn/chryse/platform/resource/ResourceData.scala b/src/main/scala/ee/hrzn/chryse/platform/resource/ResourceData.scala index 0c5607a..eaeb031 100644 --- a/src/main/scala/ee/hrzn/chryse/platform/resource/ResourceData.scala +++ b/src/main/scala/ee/hrzn/chryse/platform/resource/ResourceData.scala @@ -2,6 +2,7 @@ package ee.hrzn.chryse.platform.resource import chisel3._ import chisel3.experimental.dataview._ +import ee.hrzn.chryse.chisel.DirectionOf import scala.language.implicitConversions @@ -10,20 +11,36 @@ abstract class ResourceData[HW <: Data](gen: => HW) extends ResourceSinglePin { final var name: Option[String] = None // Should return Chisel datatype with Input/Output attached. - private[chryse] def makeIo(): HW = gen + def makeIo(): HW = gen - final private[chryse] var ioInst: Option[InstSides[HW]] = None + final private[chryse] var ioInst: Option[HW] = None /* Instantiate an IO in the module at the point of connecting to this * resource. These will be connected to in turn by the platform toplevel * (which implies they can only be used in the user toplevel). */ - private[chryse] def ioInstOrMake(): InstSides[HW] = { + final private[chryse] def ioInstOrMake(): HW = { ioInst match { case Some(r) => r case None => val r = IO(makeIo()).suggestName(s"${name.get}_int") - ioInst = Some(InstSides(r, r)) - ioInst.get + ioInst = Some(r) + r + } + } + + final def makeIoConnection(): Unit = { + val io = IO(makeIo()).suggestName(name.get) + connectIo(ioInst.get, io) + } + + protected def connectIo(user: HW, top: HW): Unit = { + DirectionOf(top) match { + case SpecifiedDirection.Input => + user := top + case SpecifiedDirection.Output => + top := user + case dir => + throw new Exception(s"unhandled direction: $dir") } } @@ -47,15 +64,13 @@ object ResourceData { res: ResourceData[HW], path: String, ): Iterator[(Data, String)] = - Seq(res.ioInst.get.user -> path).iterator + Seq(res.ioInst.get -> path).iterator } implicit def viewBool: DataView[ResourceData[Bool], Bool] = - DataView(res => Bool(), _.ioInstOrMake().user -> _) + DataView(res => Bool(), _.ioInstOrMake() -> _) - implicit def base2Bool(res: ResourceData[Bool]): Bool = + implicit def res2bool(res: ResourceData[Bool]): Bool = res.viewAs[Bool] } - -case class InstSides[HW](user: HW, top: HW) diff --git a/src/main/scala/ee/hrzn/chryse/tasks/BaseTask.scala b/src/main/scala/ee/hrzn/chryse/tasks/BaseTask.scala index a05bcb8..8df9ba2 100644 --- a/src/main/scala/ee/hrzn/chryse/tasks/BaseTask.scala +++ b/src/main/scala/ee/hrzn/chryse/tasks/BaseTask.scala @@ -80,6 +80,7 @@ abstract class BaseTask { ): Unit = { cmds.foreach(reportCmd(step, CmdActionRun, _)) val processes = cmds.map(cmd => (cmd, cmd.run())) + // TODO: consider an upper limit on concurrency. val failed = processes.collect { case (cmd, proc) if proc.exitValue() != 0 => cmd } diff --git a/src/test/scala/ee/hrzn/chryse/platform/PlatformBoardResourcesSpec.scala b/src/test/scala/ee/hrzn/chryse/platform/PlatformBoardResourcesSpec.scala index f5ccc59..6fb3b26 100644 --- a/src/test/scala/ee/hrzn/chryse/platform/PlatformBoardResourcesSpec.scala +++ b/src/test/scala/ee/hrzn/chryse/platform/PlatformBoardResourcesSpec.scala @@ -63,8 +63,10 @@ class PlatformBoardResourcesSpec extends AnyFlatSpec with Matchers { ), ) + // HACK: We should behaviourally evaluate the result. rtl should include("ledg_int = view__ubtn_int") - rtl should include("uart_tx_int = ~view__ubtn_int") + rtl should include("uart_tx_int = view__ubtn_int") + (rtl should include).regex(raw"\.view__ubtn_int\s*\(~ubtn\),") verilog.InterfaceExtractor(rtl) should contain( "ice40top" -> verilog.InterfaceExtractor.Module( @@ -95,10 +97,14 @@ class PlatformBoardResourcesSpec extends AnyFlatSpec with Matchers { ), ) + // HACK: We should behaviourally evaluate the result. rtl should include("pmod1a1_int = view__uart_rx_int") rtl should include("uart_tx_int = view__pmod1a2_int") - rtl should include("pmod1b1_int = ~view__ubtn_int") - rtl should include("ledr_int = ~view__pmod1b2_int") + rtl should include("pmod1b1_int = view__ubtn_int") + (rtl should include).regex(raw"\.view__ubtn_int\s*\(~ubtn\),") + rtl should include("ledr_int = view__pmod1b2_int") + (rtl should include).regex(raw"\.ledr_int\s*\(_top_ledr_int\),") + (rtl should include).regex(raw"assign ledr = ~_top_ledr_int;") verilog.InterfaceExtractor(rtl) should contain( "ice40top" -> verilog.InterfaceExtractor.Module(