Skip to content

Commit

Permalink
Merge pull request #2641 from chipsalliance/beu-interrupt-cdc-hcook
Browse files Browse the repository at this point in the history
Define ResetCrossingType and use with BlockDuringReset in TilePRCIDomain
  • Loading branch information
hcook authored Nov 18, 2020
2 parents eb186d0 + d585e68 commit 147bdcc
Show file tree
Hide file tree
Showing 33 changed files with 602 additions and 182 deletions.
45 changes: 43 additions & 2 deletions src/main/scala/amba/axi4/CrossingHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,22 @@ package freechips.rocketchip.amba.axi4

import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing}

case class AXI4InwardCrossingHelper(name: String, scope: LazyScope, node: AXI4InwardNode) {
trait AXI4OutwardCrossingHelper {
type HelperCrossingType <: CrossingType
def apply(xing: HelperCrossingType)(implicit p: Parameters): AXI4OutwardNode
}

trait AXI4InwardCrossingHelper {
type HelperCrossingType <: CrossingType
def apply(xing: HelperCrossingType)(implicit p: Parameters): AXI4InwardNode
}

case class AXI4InwardClockCrossingHelper(name: String, scope: LazyScope, node: AXI4InwardNode)
extends AXI4InwardCrossingHelper
{
type HelperCrossingType = ClockCrossingType
def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): AXI4InwardNode = {
xing match {
case x: AsynchronousCrossing =>
Expand All @@ -20,7 +34,22 @@ case class AXI4InwardCrossingHelper(name: String, scope: LazyScope, node: AXI4In
}
}

case class AXI4OutwardCrossingHelper(name: String, scope: LazyScope, node: AXI4OutwardNode) {
case class AXI4InwardResetCrossingHelper(name: String, scope: LazyScope, node: AXI4InwardNode)
extends AXI4InwardCrossingHelper
{
type HelperCrossingType = ResetCrossingType
def apply(xing: ResetCrossingType)(implicit p: Parameters): AXI4InwardNode = {
xing match {
case _: NoResetCrossing => node
case _: StretchedResetCrossing => throw new Exception("No ResetStretcher adapter for AXI$")
}
}
}

case class AXI4OutwardClockCrossingHelper(name: String, scope: LazyScope, node: AXI4OutwardNode)
extends AXI4OutwardCrossingHelper
{
type HelperCrossingType = ClockCrossingType
def apply(xing: ClockCrossingType = NoCrossing)(implicit p: Parameters): AXI4OutwardNode = {
xing match {
case x: AsynchronousCrossing =>
Expand All @@ -34,3 +63,15 @@ case class AXI4OutwardCrossingHelper(name: String, scope: LazyScope, node: AXI4O
}
}
}

case class AXI4OutwardResetCrossingHelper(name: String, scope: LazyScope, node: AXI4OutwardNode)
extends AXI4OutwardCrossingHelper
{
type HelperCrossingType = ResetCrossingType
def apply(xing: ResetCrossingType)(implicit p: Parameters): AXI4OutwardNode = {
xing match {
case _: NoResetCrossing => node
case _: StretchedResetCrossing => throw new Exception("No ResetStretcher adapter for AXI$")
}
}
}
2 changes: 1 addition & 1 deletion src/main/scala/amba/axi4/RegisterRouter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ trait HasAXI4ControlRegMap { this: RegisterRouter =>
executable = executable)

// Externally, this helper should be used to connect the register control port to a bus
val controlXing: AXI4InwardCrossingHelper = this.crossIn(controlNode)
val controlXing: AXI4InwardClockCrossingHelper = this.crossIn(controlNode)

// Internally, this function should be used to populate the control port with registers
protected def regmap(mapping: RegField.Map*): Unit = { controlNode.regmap(mapping:_*) }
Expand Down
14 changes: 11 additions & 3 deletions src/main/scala/amba/axi4/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

package freechips.rocketchip.amba

import freechips.rocketchip.diplomacy._
import freechips.rocketchip.diplomacy.{HasClockDomainCrossing, _}
import freechips.rocketchip.prci.{HasResetDomainCrossing}

package object axi4
{
Expand All @@ -11,8 +12,15 @@ package object axi4
type AXI4InwardNode = InwardNodeHandle[AXI4MasterPortParameters, AXI4SlavePortParameters, AXI4EdgeParameters, AXI4Bundle]

implicit class AXI4ClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal {
def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardCrossingHelper(valName.name, x, n)
def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardCrossingHelper(valName.name, x, n)
def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardClockCrossingHelper(valName.name, x, n)
def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardClockCrossingHelper(valName.name, x, n)
def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n)
def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n)
}

implicit class AXI4ResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal {
def crossIn (n: AXI4InwardNode) (implicit valName: ValName) = AXI4InwardResetCrossingHelper(valName.name, x, n)
def crossOut(n: AXI4OutwardNode)(implicit valName: ValName) = AXI4OutwardResetCrossingHelper(valName.name, x, n)
def cross(n: AXI4InwardNode) (implicit valName: ValName) = crossIn(n)
def cross(n: AXI4OutwardNode)(implicit valName: ValName) = crossOut(n)
}
Expand Down
36 changes: 35 additions & 1 deletion src/main/scala/diplomacy/ClockDomain.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,39 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.diplomacy
import freechips.rocketchip.util.{RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay}

trait HasClockDomainCrossing extends LazyScope { this: LazyModule => }
// TODO this should all be moved to package freechips.rocketchip.prci now that it exists

trait CrossingType

trait HasDomainCrossing extends LazyScope { this: LazyModule =>
type DomainCrossingType <: CrossingType
}

trait HasClockDomainCrossing extends HasDomainCrossing { this: LazyModule =>
type DomainCrossingType = ClockCrossingType
}

/** Enumerates the types of clock crossings generally supported by Diplomatic bus protocols */
sealed trait ClockCrossingType extends CrossingType
{
def sameClock = this match {
case _: SynchronousCrossing | _: CreditedCrossing => true
case _ => false
}
}

case object NoCrossing // converts to SynchronousCrossing(BufferParams.none) via implicit def in package
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossingType
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends ClockCrossingType
case class AsynchronousCrossing(depth: Int = 8, sourceSync: Int = 3, sinkSync: Int = 3, safe: Boolean = true, narrow: Boolean = false) extends ClockCrossingType
{
def asSinkParams = AsyncQueueParams(depth, sinkSync, safe, narrow)
}
case class CreditedCrossing(sourceDelay: CreditedDelay, sinkDelay: CreditedDelay) extends ClockCrossingType

object CreditedCrossing {
def apply(delay: CreditedDelay): CreditedCrossing = CreditedCrossing(delay, delay.flip)
def apply(): CreditedCrossing = CreditedCrossing(CreditedDelay(1, 1))
}
25 changes: 1 addition & 24 deletions src/main/scala/diplomacy/Parameters.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ package freechips.rocketchip.diplomacy

import Chisel._
import chisel3.util.ReadyValidIO
import freechips.rocketchip.util.{ShiftQueue, RationalDirection, FastToSlow, AsyncQueueParams, CreditedDelay}
import freechips.rocketchip.util.{ShiftQueue}

/** Options for describing the attributes of memory regions */
object RegionType {
Expand Down Expand Up @@ -300,29 +300,6 @@ object TriStateValue
def unset = TriStateValue(false, false)
}

/** Enumerates the types of clock crossings generally supported by Diplomatic bus protocols */
sealed trait ClockCrossingType
{
def sameClock = this match {
case _: SynchronousCrossing => true
case _ => false
}
}

case object NoCrossing // converts to SynchronousCrossing(BufferParams.none) via implicit def in package
case class SynchronousCrossing(params: BufferParams = BufferParams.default) extends ClockCrossingType
case class RationalCrossing(direction: RationalDirection = FastToSlow) extends ClockCrossingType
case class AsynchronousCrossing(depth: Int = 8, sourceSync: Int = 3, sinkSync: Int = 3, safe: Boolean = true, narrow: Boolean = false) extends ClockCrossingType
{
def asSinkParams = AsyncQueueParams(depth, sinkSync, safe, narrow)
}
case class CreditedCrossing(sourceDelay: CreditedDelay, sinkDelay: CreditedDelay) extends ClockCrossingType

object CreditedCrossing {
def apply(delay: CreditedDelay): CreditedCrossing = CreditedCrossing(delay, delay.flip)
def apply(): CreditedCrossing = CreditedCrossing(CreditedDelay(1, 1))
}

trait DirectedBuffers[T] {
def copyIn(x: BufferParams): T
def copyOut(x: BufferParams): T
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/groundtest/TraceGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import freechips.rocketchip.tile._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.subsystem.{TileCrossingParamsLike, CanAttachTile}
import freechips.rocketchip.util._
import freechips.rocketchip.prci.{ClockSinkParameters}

// =======
// Outline
Expand Down Expand Up @@ -75,6 +76,7 @@ case class TraceGenParams(
val beuAddr = None
val blockerCtrlAddr = None
val name = None
val clockSinkParams = ClockSinkParameters()
}

trait HasTraceGenParams {
Expand Down
26 changes: 26 additions & 0 deletions src/main/scala/interrupts/BlockDuringReset.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.interrupts

import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
import freechips.rocketchip.util.BlockDuringReset

/** BlockDuringReset ensures that no interrupt is raised while reset is raised. */
class IntBlockDuringReset(stretchResetCycles: Int = 0)(implicit p: Parameters) extends LazyModule
{
val intnode = IntAdapterNode()
override def shouldBeInlined = true
lazy val module = new LazyModuleImp(this) {
intnode.in.zip(intnode.out).foreach { case ((in, _), (out, _)) =>
in.zip(out).foreach { case (i, o) => o := BlockDuringReset(i, stretchResetCycles) }
}
}
}

object IntBlockDuringReset {
def apply(stretchResetCycles: Int = 0)(implicit p: Parameters): IntNode = {
val block_during_reset = LazyModule(new IntBlockDuringReset(stretchResetCycles))
block_during_reset.intnode
}
}
49 changes: 47 additions & 2 deletions src/main/scala/interrupts/CrossingHelper.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,24 @@ package freechips.rocketchip.interrupts

import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.prci.{ResetCrossingType, NoResetCrossing, StretchedResetCrossing}
import freechips.rocketchip.util.CreditedDelay

case class IntInwardCrossingHelper(name: String, scope: LazyScope, node: IntInwardNode) {
trait IntOutwardCrossingHelper {
type HelperCrossingType <: CrossingType
def apply(xing: HelperCrossingType)(implicit p: Parameters): IntOutwardNode
}

trait IntInwardCrossingHelper {
type HelperCrossingType <: CrossingType
def apply(xing: HelperCrossingType)(implicit p: Parameters): IntInwardNode
}

case class IntInwardClockCrossingHelper(name: String, scope: LazyScope, node: IntInwardNode)
extends IntInwardCrossingHelper
{
type HelperCrossingType = ClockCrossingType
def apply(xing: ClockCrossingType)(implicit p: Parameters): IntInwardNode = apply(xing, false)
def apply(xing: ClockCrossingType = NoCrossing, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntInwardNode = {
xing match {
case x: AsynchronousCrossing =>
Expand All @@ -21,7 +36,24 @@ case class IntInwardCrossingHelper(name: String, scope: LazyScope, node: IntInwa
}
}

case class IntOutwardCrossingHelper(name: String, scope: LazyScope, node: IntOutwardNode) {
case class IntInwardResetCrossingHelper(name: String, scope: LazyScope, node: IntInwardNode)
extends IntInwardCrossingHelper
{
type HelperCrossingType = ResetCrossingType
def apply(xing: ResetCrossingType)(implicit p: Parameters): IntInwardNode = {
xing match {
case _: NoResetCrossing => node
case s: StretchedResetCrossing =>
node :*=* scope { IntNameNode(name) } :*=* IntBlockDuringReset(s.cycles)
}
}
}

case class IntOutwardClockCrossingHelper(name: String, scope: LazyScope, node: IntOutwardNode)
extends IntOutwardCrossingHelper
{
type HelperCrossingType = ClockCrossingType
def apply(xing: ClockCrossingType)(implicit p: Parameters): IntOutwardNode = apply(xing, false)
def apply(xing: ClockCrossingType = NoCrossing, alreadyRegistered: Boolean = false)(implicit p: Parameters): IntOutwardNode = {
xing match {
case x: AsynchronousCrossing =>
Expand All @@ -35,3 +67,16 @@ case class IntOutwardCrossingHelper(name: String, scope: LazyScope, node: IntOut
}
}
}

case class IntOutwardResetCrossingHelper(name: String, scope: LazyScope, node: IntOutwardNode)
extends IntOutwardCrossingHelper
{
type HelperCrossingType = ResetCrossingType
def apply(xing: ResetCrossingType)(implicit p: Parameters): IntOutwardNode = {
xing match {
case _: NoResetCrossing => node
case s: StretchedResetCrossing =>
IntBlockDuringReset(s.cycles) :*=* scope { IntNameNode(name) } :*=* node
}
}
}
4 changes: 4 additions & 0 deletions src/main/scala/interrupts/Nodes.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ object IntNameNode {
def apply(name: String): IntIdentityNode = apply(Some(name))
}

object IntTempNode {
def apply(): IntEphemeralNode = IntEphemeralNode()(ValName("temp"))
}

case class IntNexusNode(
sourceFn: Seq[IntSourcePortParameters] => IntSourcePortParameters,
sinkFn: Seq[IntSinkPortParameters] => IntSinkPortParameters,
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/interrupts/RegisterRouter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ trait HasInterruptSources { this: RegisterRouter =>
protected val intnode = IntSourceNode(IntSourcePortSimple(num = nInterrupts, resources = Seq(Resource(device, "int"))))

// Externally, this helper should be used to connect the interrupts to a bus
val intXing: IntOutwardCrossingHelper = this.crossOut(intnode)
val intXing: IntOutwardClockCrossingHelper = this.crossOut(intnode)

// Internally, this wire should be used to drive interrupt values
val interrupts: ModuleValue[Vec[Bool]] = InModuleBody { if (intnode.out.isEmpty) Vec(0, Bool()) else intnode.out(0)._1 }
Expand Down
16 changes: 12 additions & 4 deletions src/main/scala/interrupts/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@

package freechips.rocketchip

import Chisel._
import freechips.rocketchip.diplomacy._
import chisel3.{Bool, Vec}
import freechips.rocketchip.diplomacy.{HasClockDomainCrossing, _}
import freechips.rocketchip.prci.{HasResetDomainCrossing}

package object interrupts
{
Expand All @@ -12,8 +13,15 @@ package object interrupts
type IntNode = SimpleNodeHandle[IntSourcePortParameters, IntSinkPortParameters, IntEdge, Vec[Bool]]

implicit class IntClockDomainCrossing(private val x: HasClockDomainCrossing) extends AnyVal {
def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardCrossingHelper(valName.name, x, n)
def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardCrossingHelper(valName.name, x, n)
def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardClockCrossingHelper(valName.name, x, n)
def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardClockCrossingHelper(valName.name, x, n)
def cross(n: IntInwardNode) (implicit valName: ValName) = crossIn(n)
def cross(n: IntOutwardNode)(implicit valName: ValName) = crossOut(n)
}

implicit class IntResetDomainCrossing(private val x: HasResetDomainCrossing) extends AnyVal {
def crossIn (n: IntInwardNode) (implicit valName: ValName) = IntInwardResetCrossingHelper(valName.name, x, n)
def crossOut(n: IntOutwardNode)(implicit valName: ValName) = IntOutwardResetCrossingHelper(valName.name, x, n)
def cross(n: IntInwardNode) (implicit valName: ValName) = crossIn(n)
def cross(n: IntOutwardNode)(implicit valName: ValName) = crossOut(n)
}
Expand Down
36 changes: 36 additions & 0 deletions src/main/scala/prci/BundleBridgeBlockDuringReset.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// See LICENSE.SiFive for license details.

package freechips.rocketchip.prci

import chisel3._
import freechips.rocketchip.config.{Parameters}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.diplomacy.BundleBridgeNexus.fillN
import freechips.rocketchip.util.{BlockDuringReset, Blockable}

object BundleBridgeBlockDuringReset {
def apply[T <: Data : Blockable](
resetCrossingType: ResetCrossingType,
name: Option[String] = None,
registered: Boolean = false,
default: Option[() => T] = None,
inputRequiresOutput: Boolean = false,
shouldBeInlined: Boolean = true
)(implicit p: Parameters): BundleBridgeNexusNode[T] = {
val nexus = LazyModule(new BundleBridgeNexus[T](
inputFn = (s: Seq[T]) => {
val data = BundleBridgeNexus.requireOne[T](registered)(s)
resetCrossingType match {
case _: NoResetCrossing => data
case s: StretchedResetCrossing => BlockDuringReset(data, s.cycles)
}
},
outputFn = fillN[T](registered) _,
default = default,
inputRequiresOutput = inputRequiresOutput,
shouldBeInlined = shouldBeInlined
))
name.foreach(nexus.suggestName(_))
nexus.node
}
}
Loading

0 comments on commit 147bdcc

Please sign in to comment.