Merge pull request #295 from ucb-bar/tl2-irrevocable
TL2 -> IrrevocableIO
This commit is contained in:
		@@ -1,5 +1,7 @@
 | 
			
		||||
package junctions
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.util.{DecoupledIO, Decoupled, Irrevocable, IrrevocableIO, ReadyValidIO}
 | 
			
		||||
 | 
			
		||||
class CrossingIO[T <: Data](gen: T) extends Bundle {
 | 
			
		||||
  // Enqueue clock domain
 | 
			
		||||
@@ -22,7 +24,7 @@ object AsyncScope { def apply() = Module(new AsyncScope) }
 | 
			
		||||
object AsyncDecoupledCrossing
 | 
			
		||||
{
 | 
			
		||||
  // takes from_source from the 'from' clock domain and puts it into the 'to' clock domain
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
    val crossing = Module(new AsyncQueue(from_source.bits, depth, sync)).io
 | 
			
		||||
    crossing.enq_clock := from_clock
 | 
			
		||||
    crossing.enq_reset := from_reset
 | 
			
		||||
@@ -36,7 +38,7 @@ object AsyncDecoupledCrossing
 | 
			
		||||
object AsyncDecoupledTo
 | 
			
		||||
{
 | 
			
		||||
  // takes source from your clock domain and puts it into the 'to' clock domain
 | 
			
		||||
  def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: DecoupledIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
  def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
    val scope = AsyncScope()
 | 
			
		||||
    AsyncDecoupledCrossing(scope.clock, scope.reset, source, to_clock, to_reset, depth, sync)
 | 
			
		||||
  }
 | 
			
		||||
@@ -45,12 +47,44 @@ object AsyncDecoupledTo
 | 
			
		||||
object AsyncDecoupledFrom
 | 
			
		||||
{
 | 
			
		||||
  // takes from_source from the 'from' clock domain and puts it into your clock domain
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: DecoupledIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): DecoupledIO[T] = {
 | 
			
		||||
    val scope = AsyncScope()
 | 
			
		||||
    AsyncDecoupledCrossing(from_clock, from_reset, from_source, scope.clock, scope.reset, depth, sync)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object PostQueueIrrevocablize
 | 
			
		||||
{
 | 
			
		||||
  def apply[T <: Data](deq: DecoupledIO[T]): IrrevocableIO[T] = {
 | 
			
		||||
    val irr = Wire(new IrrevocableIO(deq.bits))
 | 
			
		||||
    irr.bits := deq.bits
 | 
			
		||||
    irr.valid := deq.valid
 | 
			
		||||
    deq.ready := irr.ready
 | 
			
		||||
    irr
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object AsyncIrrevocableCrossing {
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], to_clock: Clock, to_reset: Bool, depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
 | 
			
		||||
    PostQueueIrrevocablize(AsyncDecoupledCrossing(from_clock, from_reset, from_source, to_clock, to_reset, depth, sync))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object AsyncIrrevocableTo
 | 
			
		||||
{
 | 
			
		||||
  // takes source from your clock domain and puts it into the 'to' clock domain
 | 
			
		||||
  def apply[T <: Data](to_clock: Clock, to_reset: Bool, source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
 | 
			
		||||
    PostQueueIrrevocablize(AsyncDecoupledTo(to_clock, to_reset, source, depth, sync))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object AsyncIrrevocableFrom
 | 
			
		||||
{
 | 
			
		||||
  // takes from_source from the 'from' clock domain and puts it into your clock domain
 | 
			
		||||
  def apply[T <: Data](from_clock: Clock, from_reset: Bool, from_source: ReadyValidIO[T], depth: Int = 8, sync: Int = 3): IrrevocableIO[T] = {
 | 
			
		||||
    PostQueueIrrevocablize(AsyncDecoupledFrom(from_clock, from_reset, from_source, depth, sync))
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**  Because Chisel/FIRRTL does not allow us
 | 
			
		||||
  *  to directly assign clocks from Signals,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.util.Irrevocable
 | 
			
		||||
 | 
			
		||||
abstract class GenericParameterizedBundle[T <: Object](val params: T) extends Bundle
 | 
			
		||||
{
 | 
			
		||||
@@ -100,13 +101,16 @@ object TLAtomics
 | 
			
		||||
  def isLogical(x: UInt) = x <= SWAP
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
sealed trait TLChannel extends TLBundleBase
 | 
			
		||||
sealed trait TLChannel extends TLBundleBase {
 | 
			
		||||
  val channelName: String
 | 
			
		||||
}
 | 
			
		||||
sealed trait TLDataChannel extends TLChannel
 | 
			
		||||
sealed trait TLAddrChannel extends TLDataChannel
 | 
			
		||||
 | 
			
		||||
final class TLBundleA(params: TLBundleParameters)
 | 
			
		||||
  extends TLBundleBase(params) with TLAddrChannel
 | 
			
		||||
{
 | 
			
		||||
  val channelName = "'A' channel"
 | 
			
		||||
  // fixed fields during multibeat:
 | 
			
		||||
  val opcode  = UInt(width = 3)
 | 
			
		||||
  val param   = UInt(width = 3) // amo_opcode || perms || hint
 | 
			
		||||
@@ -121,6 +125,7 @@ final class TLBundleA(params: TLBundleParameters)
 | 
			
		||||
final class TLBundleB(params: TLBundleParameters)
 | 
			
		||||
  extends TLBundleBase(params) with TLAddrChannel
 | 
			
		||||
{
 | 
			
		||||
  val channelName = "'B' channel"
 | 
			
		||||
  // fixed fields during multibeat:
 | 
			
		||||
  val opcode  = UInt(width = 3)
 | 
			
		||||
  val param   = UInt(width = 3)
 | 
			
		||||
@@ -135,6 +140,7 @@ final class TLBundleB(params: TLBundleParameters)
 | 
			
		||||
final class TLBundleC(params: TLBundleParameters)
 | 
			
		||||
  extends TLBundleBase(params) with TLAddrChannel
 | 
			
		||||
{
 | 
			
		||||
  val channelName = "'C' channel"
 | 
			
		||||
  // fixed fields during multibeat:
 | 
			
		||||
  val opcode  = UInt(width = 3)
 | 
			
		||||
  val param   = UInt(width = 3)
 | 
			
		||||
@@ -150,6 +156,7 @@ final class TLBundleC(params: TLBundleParameters)
 | 
			
		||||
final class TLBundleD(params: TLBundleParameters)
 | 
			
		||||
  extends TLBundleBase(params) with TLDataChannel
 | 
			
		||||
{
 | 
			
		||||
  val channelName = "'D' channel"
 | 
			
		||||
  // fixed fields during multibeat:
 | 
			
		||||
  val opcode  = UInt(width = 3)
 | 
			
		||||
  val param   = UInt(width = 2)
 | 
			
		||||
@@ -165,16 +172,17 @@ final class TLBundleD(params: TLBundleParameters)
 | 
			
		||||
final class TLBundleE(params: TLBundleParameters)
 | 
			
		||||
  extends TLBundleBase(params) with TLChannel
 | 
			
		||||
{
 | 
			
		||||
  val channelName = "'E' channel"
 | 
			
		||||
  val sink = UInt(width = params.sinkBits) // to
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class TLBundle(params: TLBundleParameters) extends TLBundleBase(params)
 | 
			
		||||
{
 | 
			
		||||
  val a = Decoupled(new TLBundleA(params))
 | 
			
		||||
  val b = Decoupled(new TLBundleB(params)).flip
 | 
			
		||||
  val c = Decoupled(new TLBundleC(params))
 | 
			
		||||
  val d = Decoupled(new TLBundleD(params)).flip
 | 
			
		||||
  val e = Decoupled(new TLBundleE(params))
 | 
			
		||||
  val a = Irrevocable(new TLBundleA(params))
 | 
			
		||||
  val b = Irrevocable(new TLBundleB(params)).flip
 | 
			
		||||
  val c = Irrevocable(new TLBundleC(params))
 | 
			
		||||
  val d = Irrevocable(new TLBundleD(params)).flip
 | 
			
		||||
  val e = Irrevocable(new TLBundleE(params))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object TLBundle
 | 
			
		||||
 
 | 
			
		||||
@@ -22,13 +22,13 @@ class TLAsyncCrossing(depth: Int = 8, sync: Int = 3) extends LazyModule
 | 
			
		||||
 | 
			
		||||
    // Transfer all TL2 bundles from/to the same domains
 | 
			
		||||
    ((io.in zip io.out) zip (node.edgesIn zip node.edgesOut)) foreach { case ((in, out), (edgeIn, edgeOut)) =>
 | 
			
		||||
      out.a <> AsyncDecoupledCrossing(io.in_clock, io.in_reset, in.a, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
      in.d <> AsyncDecoupledCrossing(io.out_clock, io.out_reset, out.d, io.in_clock, io.in_reset, depth, sync)
 | 
			
		||||
      out.a <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.a, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
      in.d <> AsyncIrrevocableCrossing(io.out_clock, io.out_reset, out.d, io.in_clock, io.in_reset, depth, sync)
 | 
			
		||||
 | 
			
		||||
      if (edgeOut.manager.anySupportAcquire && edgeOut.client.anySupportProbe) {
 | 
			
		||||
        in.b <> AsyncDecoupledCrossing(io.out_clock, io.out_reset, out.b, io.in_clock, io.in_reset, depth, sync)
 | 
			
		||||
        out.c <> AsyncDecoupledCrossing(io.in_clock, io.in_reset, in.c, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
        out.e <> AsyncDecoupledCrossing(io.in_clock, io.in_reset, in.e, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
        in.b <> AsyncIrrevocableCrossing(io.out_clock, io.out_reset, out.b, io.in_clock, io.in_reset, depth, sync)
 | 
			
		||||
        out.c <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.c, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
        out.e <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.e, io.out_clock, io.out_reset, depth, sync)
 | 
			
		||||
      } else {
 | 
			
		||||
        in.b.valid := Bool(false)
 | 
			
		||||
        in.c.ready := Bool(true)
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
 | 
			
		||||
import chisel3.util.{Irrevocable, IrrevocableIO}
 | 
			
		||||
 | 
			
		||||
object TLMonitor
 | 
			
		||||
{
 | 
			
		||||
@@ -14,7 +15,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormatA(bundle: TLBundleA, edge: TLEdgeOut)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeFormatA(bundle: TLBundleA, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    assert (TLMessages.isA(bundle.opcode), "'A' channel has invalid opcode" + extra)
 | 
			
		||||
 | 
			
		||||
    // Reuse these subexpressions to save some firrtl lines
 | 
			
		||||
@@ -79,7 +80,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormatB(bundle: TLBundleB, edge: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeFormatB(bundle: TLBundleB, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    assert (TLMessages.isB(bundle.opcode), "'B' channel has invalid opcode" + extra)
 | 
			
		||||
 | 
			
		||||
    // Reuse these subexpressions to save some firrtl lines
 | 
			
		||||
@@ -144,7 +145,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormatC(bundle: TLBundleC, edge: TLEdgeOut)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeFormatC(bundle: TLBundleC, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    assert (TLMessages.isC(bundle.opcode), "'C' channel has invalid opcode" + extra)
 | 
			
		||||
 | 
			
		||||
    val source_ok = edge.client.contains(bundle.source)
 | 
			
		||||
@@ -210,7 +211,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormatD(bundle: TLBundleD, edge: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeFormatD(bundle: TLBundleD, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    assert (TLMessages.isD(bundle.opcode), "'D' channel has invalid opcode" + extra)
 | 
			
		||||
 | 
			
		||||
    val source_ok = edge.client.contains(bundle.source)
 | 
			
		||||
@@ -268,19 +269,19 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormatE(bundle: TLBundleE, edge: TLEdgeOut)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeFormatE(bundle: TLBundleE, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    assert (edge.manager.containsById(bundle.sink), "'E' channels carries invalid sink ID" + extra)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeFormat(bundleOut: TLBundle, edgeOut: TLEdgeOut, bundleIn: TLBundle, edgeIn: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
    when (bundleOut.a.valid) { legalizeFormatA(bundleOut.a.bits, edgeOut) }
 | 
			
		||||
    when (bundleIn .b.valid) { legalizeFormatB(bundleIn .b.bits, edgeIn)  }
 | 
			
		||||
    when (bundleOut.c.valid) { legalizeFormatC(bundleOut.c.bits, edgeOut) }
 | 
			
		||||
    when (bundleIn .d.valid) { legalizeFormatD(bundleIn .d.bits, edgeIn)  }
 | 
			
		||||
    when (bundleOut.e.valid) { legalizeFormatE(bundleOut.e.bits, edgeOut) }
 | 
			
		||||
  def legalizeFormat(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
    when (bundle.a.valid) { legalizeFormatA(bundle.a.bits, edge) }
 | 
			
		||||
    when (bundle.b.valid) { legalizeFormatB(bundle.b.bits, edge) }
 | 
			
		||||
    when (bundle.c.valid) { legalizeFormatC(bundle.c.bits, edge) }
 | 
			
		||||
    when (bundle.d.valid) { legalizeFormatD(bundle.d.bits, edge) }
 | 
			
		||||
    when (bundle.e.valid) { legalizeFormatE(bundle.e.bits, edge) }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeMultibeatA(a: DecoupledIO[TLBundleA], edge: TLEdgeOut)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeMultibeatA(a: IrrevocableIO[TLBundleA], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
 | 
			
		||||
    val opcode  = Reg(UInt())
 | 
			
		||||
    val param   = Reg(UInt())
 | 
			
		||||
@@ -307,7 +308,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeMultibeatB(b: DecoupledIO[TLBundleB], edge: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeMultibeatB(b: IrrevocableIO[TLBundleB], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
 | 
			
		||||
    val opcode  = Reg(UInt())
 | 
			
		||||
    val param   = Reg(UInt())
 | 
			
		||||
@@ -334,7 +335,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeMultibeatC(c: DecoupledIO[TLBundleC], edge: TLEdgeOut)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeMultibeatC(c: IrrevocableIO[TLBundleC], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
 | 
			
		||||
    val opcode  = Reg(UInt())
 | 
			
		||||
    val param   = Reg(UInt())
 | 
			
		||||
@@ -364,7 +365,7 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeMultibeatD(d: DecoupledIO[TLBundleD], edge: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
  def legalizeMultibeatD(d: IrrevocableIO[TLBundleD], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
 | 
			
		||||
    val opcode  = Reg(UInt())
 | 
			
		||||
    val param   = Reg(UInt())
 | 
			
		||||
@@ -378,7 +379,7 @@ object TLMonitor
 | 
			
		||||
      assert (d.bits.size   === size,   "'D' channel size changed within multibeat operation" + extra)
 | 
			
		||||
      assert (d.bits.source === source, "'D' channel source changed within multibeat operation" + extra)
 | 
			
		||||
      assert (d.bits.sink   === sink,   "'D' channel sink changed with multibeat operation" + extra)
 | 
			
		||||
      assert (d.bits.addr_lo=== addr_lo,"'C' channel addr_lo changed with multibeat operation" + extra)
 | 
			
		||||
      assert (d.bits.addr_lo=== addr_lo,"'D' channel addr_lo changed with multibeat operation" + extra)
 | 
			
		||||
    }
 | 
			
		||||
    when (d.fire()) {
 | 
			
		||||
      counter := counter - UInt(1)
 | 
			
		||||
@@ -394,16 +395,37 @@ object TLMonitor
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeMultibeat(bundleOut: TLBundle, edgeOut: TLEdgeOut, bundleIn: TLBundle, edgeIn: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
    legalizeMultibeatA(bundleOut.a, edgeOut)
 | 
			
		||||
    legalizeMultibeatB(bundleOut.b, edgeIn)
 | 
			
		||||
    legalizeMultibeatC(bundleOut.c, edgeOut)
 | 
			
		||||
    legalizeMultibeatD(bundleOut.d, edgeIn)
 | 
			
		||||
  def legalizeMultibeat(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    legalizeMultibeatA(bundle.a, edge)
 | 
			
		||||
    legalizeMultibeatB(bundle.b, edge)
 | 
			
		||||
    legalizeMultibeatC(bundle.c, edge)
 | 
			
		||||
    legalizeMultibeatD(bundle.d, edge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalize(bundleOut: TLBundle, edgeOut: TLEdgeOut, bundleIn: TLBundle, edgeIn: TLEdgeIn)(implicit sourceInfo: SourceInfo) = {
 | 
			
		||||
    legalizeFormat   (bundleOut, edgeOut, bundleIn, edgeIn)
 | 
			
		||||
    legalizeMultibeat(bundleOut, edgeOut, bundleIn, edgeIn)
 | 
			
		||||
  def legalizeIrrevocable(irr: IrrevocableIO[TLChannel], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    val last_v = RegNext(irr.valid, Bool(false))
 | 
			
		||||
    val last_r = RegNext(irr.ready, Bool(false))
 | 
			
		||||
    val last_b = RegNext(irr.bits)
 | 
			
		||||
    val bits_changed = irr.bits.toBits === last_b.toBits
 | 
			
		||||
 | 
			
		||||
    when (last_v && !last_r) {
 | 
			
		||||
      assert(irr.valid,    s"${irr.bits.channelName} had contents that were revoked by the supplier (valid lowered)" + extra)
 | 
			
		||||
      assert(bits_changed, s"${irr.bits.channelName} had contents that were revoked by the supplier (contents changed)" + extra)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalizeIrrevocable(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    legalizeIrrevocable(bundle.a, edge)
 | 
			
		||||
    legalizeIrrevocable(bundle.b, edge)
 | 
			
		||||
    legalizeIrrevocable(bundle.c, edge)
 | 
			
		||||
    legalizeIrrevocable(bundle.d, edge)
 | 
			
		||||
    legalizeIrrevocable(bundle.e, edge)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def legalize(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
 | 
			
		||||
    legalizeFormat     (bundle, edge)
 | 
			
		||||
    legalizeMultibeat  (bundle, edge)
 | 
			
		||||
    legalizeIrrevocable(bundle, edge)
 | 
			
		||||
    // !!! validate source uniqueness
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
 | 
			
		||||
import chisel3.util.{Irrevocable, IrrevocableIO}
 | 
			
		||||
import uncore.util.{SimpleRegIO}
 | 
			
		||||
 | 
			
		||||
case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt))
 | 
			
		||||
@@ -34,8 +34,8 @@ object RegReadFn
 | 
			
		||||
      val (ovalid, data) = x(oready)
 | 
			
		||||
      (Bool(true), ovalid, data)
 | 
			
		||||
    })
 | 
			
		||||
  // read from a DecoupledIO (only safe if there is a consistent source of data)
 | 
			
		||||
  implicit def apply(x: DecoupledIO[UInt]):RegReadFn = RegReadFn(ready => { x.ready := ready; (x.valid, x.bits) })
 | 
			
		||||
  // read from a IrrevocableIO (only safe if there is a consistent source of data)
 | 
			
		||||
  implicit def apply(x: IrrevocableIO[UInt]):RegReadFn = RegReadFn(ready => { x.ready := ready; (x.valid, x.bits) })
 | 
			
		||||
  // read from a register
 | 
			
		||||
  implicit def apply(x: UInt):RegReadFn = RegReadFn(ready => (Bool(true), x))
 | 
			
		||||
  // noop
 | 
			
		||||
@@ -69,8 +69,8 @@ object RegWriteFn
 | 
			
		||||
    new RegWriteFn(true, { case (_, oready, data) =>
 | 
			
		||||
      (Bool(true), x(oready, data))
 | 
			
		||||
    })
 | 
			
		||||
  // write to a DecoupledIO (only safe if there is a consistent sink draining data)
 | 
			
		||||
  implicit def apply(x: DecoupledIO[UInt]): RegWriteFn = RegWriteFn((valid, data) => { x.valid := valid; x.bits := data; x.ready })
 | 
			
		||||
  // write to a IrrevocableIO (only safe if there is a consistent sink draining data)
 | 
			
		||||
  implicit def apply(x: IrrevocableIO[UInt]): RegWriteFn = RegWriteFn((valid, data) => { x.valid := valid; x.bits := data; x.ready })
 | 
			
		||||
  // updates a register (or adds a mux to a wire)
 | 
			
		||||
  implicit def apply(x: UInt): RegWriteFn = RegWriteFn((valid, data) => { when (valid) { x := data }; Bool(true) })
 | 
			
		||||
  // noop
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.util.{Irrevocable, IrrevocableIO}
 | 
			
		||||
 | 
			
		||||
// A bus agnostic register interface to a register-based device
 | 
			
		||||
 | 
			
		||||
@@ -46,8 +47,8 @@ object RegMapper
 | 
			
		||||
    val endIndex = 1 << log2Ceil(regmap.map(_._1).max+1)
 | 
			
		||||
    val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits)
 | 
			
		||||
 | 
			
		||||
    val out = Wire(Decoupled(new RegMapperOutput(params)))
 | 
			
		||||
    val front = Wire(Decoupled(new RegMapperInput(params)))
 | 
			
		||||
    val out = Wire(Irrevocable(new RegMapperOutput(params)))
 | 
			
		||||
    val front = Wire(Irrevocable(new RegMapperInput(params)))
 | 
			
		||||
    front.bits := in.bits
 | 
			
		||||
 | 
			
		||||
    // Must this device pipeline the control channel?
 | 
			
		||||
 
 | 
			
		||||
@@ -3,6 +3,7 @@
 | 
			
		||||
package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.util.{Irrevocable, IrrevocableIO}
 | 
			
		||||
import junctions._
 | 
			
		||||
import uncore.util.{AsyncResetRegVec}
 | 
			
		||||
 | 
			
		||||
@@ -25,8 +26,8 @@ class BusyRegisterCrossing(clock: Clock, reset: Bool)
 | 
			
		||||
 | 
			
		||||
// RegField should support connecting to one of these
 | 
			
		||||
class RegisterWriteIO[T <: Data](gen: T) extends Bundle {
 | 
			
		||||
  val request  = Decoupled(gen).flip()
 | 
			
		||||
  val response = Decoupled(Bool()) // ignore .bits
 | 
			
		||||
  val request  = Irrevocable(gen).flip()
 | 
			
		||||
  val response = Irrevocable(Bool()) // ignore .bits
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// To turn on/off a domain:
 | 
			
		||||
@@ -85,8 +86,8 @@ class RegisterWriteCrossing[T <: Data](gen: T, sync: Int = 3) extends Module {
 | 
			
		||||
 | 
			
		||||
// RegField should support connecting to one of these
 | 
			
		||||
class RegisterReadIO[T <: Data](gen: T) extends Bundle {
 | 
			
		||||
  val request  = Decoupled(Bool()).flip() // ignore .bits
 | 
			
		||||
  val response = Decoupled(gen)
 | 
			
		||||
  val request  = Irrevocable(Bool()).flip() // ignore .bits
 | 
			
		||||
  val response = Irrevocable(gen)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
class RegisterReadCrossingIO[T <: Data](gen: T) extends Bundle {
 | 
			
		||||
 
 | 
			
		||||
@@ -33,18 +33,24 @@ class RRTestCombinational(val bits: Int, rvalid: Bool => Bool, wready: Bool => B
 | 
			
		||||
  io.rvalid := rvalid(rfire)
 | 
			
		||||
  io.wready := wready(wfire)
 | 
			
		||||
 | 
			
		||||
  io.rdata := Mux(rfire, reg, UInt(0))
 | 
			
		||||
  io.rdata := reg
 | 
			
		||||
  when (wfire) { reg := io.wdata }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
object RRTestCombinational
 | 
			
		||||
{
 | 
			
		||||
  private var seed = 42
 | 
			
		||||
 | 
			
		||||
  def always: Bool => Bool = _ => Bool(true)
 | 
			
		||||
  def random: Bool => Bool = {
 | 
			
		||||
 | 
			
		||||
  def random: Bool => Bool = { fire =>
 | 
			
		||||
    seed = seed + 1
 | 
			
		||||
    _ => LFSR16Seed(seed)(0)
 | 
			
		||||
    val lfsr = LFSR16Seed(seed)
 | 
			
		||||
    val reg = RegInit(Bool(true))
 | 
			
		||||
    reg := Mux(reg, !fire, lfsr(0) && lfsr(1))
 | 
			
		||||
    reg
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def delay(x: Int): Bool => Bool = { fire =>
 | 
			
		||||
    val reg = RegInit(UInt(0, width = log2Ceil(x+1)))
 | 
			
		||||
    val ready = reg === UInt(0)
 | 
			
		||||
@@ -89,7 +95,7 @@ class RRTestRequest(val bits: Int,
 | 
			
		||||
  val rofire = io.roready && rovalid
 | 
			
		||||
  val wofire = io.woready && wovalid
 | 
			
		||||
 | 
			
		||||
  io.rdata := Mux(rofire, reg, UInt(0))
 | 
			
		||||
  io.rdata := reg
 | 
			
		||||
  when (wofire) { reg := wdata }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -115,22 +121,27 @@ object RRTestRequest
 | 
			
		||||
    }
 | 
			
		||||
    (ready(0), full(x-1), data(x-1))
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def busy: (Bool, Bool, UInt) => (Bool, Bool, UInt) = {
 | 
			
		||||
    seed = seed + 1
 | 
			
		||||
    (ivalid, oready, idata) => {
 | 
			
		||||
      val lfsr = LFSR16Seed(seed)
 | 
			
		||||
      val busy = RegInit(Bool(false))
 | 
			
		||||
      val data = Reg(UInt(width = idata.getWidth))
 | 
			
		||||
      val progress = lfsr(0)
 | 
			
		||||
      when (progress) {
 | 
			
		||||
        busy := Mux(busy, !oready, ivalid)
 | 
			
		||||
      }
 | 
			
		||||
      val progress = RegInit(Bool(false))
 | 
			
		||||
      val iready = progress && !busy
 | 
			
		||||
      val ovalid = progress && busy
 | 
			
		||||
      when (progress) {
 | 
			
		||||
        busy := Mux(busy, !oready, ivalid)
 | 
			
		||||
        progress := Mux(busy, !oready, !ivalid)
 | 
			
		||||
      } .otherwise {
 | 
			
		||||
        progress := lfsr(0)
 | 
			
		||||
      }
 | 
			
		||||
      when (ivalid && iready) { data := idata }
 | 
			
		||||
      (iready, ovalid, data)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  def request(bits: Int,
 | 
			
		||||
    rflow: (Bool, Bool, UInt) => (Bool, Bool, UInt),
 | 
			
		||||
    wflow: (Bool, Bool, UInt) => (Bool, Bool, UInt)): RegField = {
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL
 | 
			
		||||
 | 
			
		||||
  def connect(bo: TLBundle, eo: TLEdgeOut, bi: TLBundle, ei: TLEdgeIn)(implicit sourceInfo: SourceInfo): Unit = {
 | 
			
		||||
    require (eo.asInstanceOf[TLEdgeParameters] == ei.asInstanceOf[TLEdgeParameters])
 | 
			
		||||
    TLMonitor.legalize(bo, eo, bi, ei)
 | 
			
		||||
    TLMonitor.legalize(bo, eo)
 | 
			
		||||
    bi <> bo
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,7 @@ package uncore.tilelink2
 | 
			
		||||
 | 
			
		||||
import Chisel._
 | 
			
		||||
import chisel3.internal.sourceinfo.SourceInfo
 | 
			
		||||
import chisel3.util.{Irrevocable, IrrevocableIO}
 | 
			
		||||
import scala.math.{min,max}
 | 
			
		||||
 | 
			
		||||
// innBeatBytes => the new client-facing bus width
 | 
			
		||||
@@ -19,7 +20,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule
 | 
			
		||||
      val out = node.bundleOut
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    def merge[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = {
 | 
			
		||||
    def merge[T <: TLDataChannel](edgeIn: TLEdge, in: IrrevocableIO[T], edgeOut: TLEdge, out: IrrevocableIO[T]) = {
 | 
			
		||||
      val inBytes = edgeIn.manager.beatBytes
 | 
			
		||||
      val outBytes = edgeOut.manager.beatBytes
 | 
			
		||||
      val ratio = outBytes / inBytes
 | 
			
		||||
@@ -81,7 +82,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    def split[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = {
 | 
			
		||||
    def split[T <: TLDataChannel](edgeIn: TLEdge, in: IrrevocableIO[T], edgeOut: TLEdge, out: IrrevocableIO[T]) = {
 | 
			
		||||
      val inBytes = edgeIn.manager.beatBytes
 | 
			
		||||
      val outBytes = edgeOut.manager.beatBytes
 | 
			
		||||
      val ratio = inBytes / outBytes
 | 
			
		||||
@@ -131,7 +132,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule
 | 
			
		||||
      // addr_lo gets truncated automagically
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    def splice[T <: TLDataChannel](edgeIn: TLEdge, in: DecoupledIO[T], edgeOut: TLEdge, out: DecoupledIO[T]) = {
 | 
			
		||||
    def splice[T <: TLDataChannel](edgeIn: TLEdge, in: IrrevocableIO[T], edgeOut: TLEdge, out: IrrevocableIO[T]) = {
 | 
			
		||||
      if (edgeIn.manager.beatBytes == edgeOut.manager.beatBytes) {
 | 
			
		||||
        // nothing to do; pass it through
 | 
			
		||||
        out <> in
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user