[tilelink2] Convert TileLink2 to use IrrevocableIO. Add checks to the Monitor to enforce Irrevocable semantics on TLEdges. Update the RegisterRouterTests to pass the new Monitor assertions.
This commit is contained in:
parent
3030718f72
commit
e02d149cbe
@ -3,6 +3,7 @@
|
|||||||
package uncore.tilelink2
|
package uncore.tilelink2
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import chisel3.util.Irrevocable
|
||||||
|
|
||||||
abstract class GenericParameterizedBundle[T <: Object](val params: T) extends Bundle
|
abstract class GenericParameterizedBundle[T <: Object](val params: T) extends Bundle
|
||||||
{
|
{
|
||||||
@ -100,13 +101,16 @@ object TLAtomics
|
|||||||
def isLogical(x: UInt) = x <= SWAP
|
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 TLDataChannel extends TLChannel
|
||||||
sealed trait TLAddrChannel extends TLDataChannel
|
sealed trait TLAddrChannel extends TLDataChannel
|
||||||
|
|
||||||
final class TLBundleA(params: TLBundleParameters)
|
final class TLBundleA(params: TLBundleParameters)
|
||||||
extends TLBundleBase(params) with TLAddrChannel
|
extends TLBundleBase(params) with TLAddrChannel
|
||||||
{
|
{
|
||||||
|
val channelName = "'A' channel"
|
||||||
// fixed fields during multibeat:
|
// fixed fields during multibeat:
|
||||||
val opcode = UInt(width = 3)
|
val opcode = UInt(width = 3)
|
||||||
val param = UInt(width = 3) // amo_opcode || perms || hint
|
val param = UInt(width = 3) // amo_opcode || perms || hint
|
||||||
@ -121,6 +125,7 @@ final class TLBundleA(params: TLBundleParameters)
|
|||||||
final class TLBundleB(params: TLBundleParameters)
|
final class TLBundleB(params: TLBundleParameters)
|
||||||
extends TLBundleBase(params) with TLAddrChannel
|
extends TLBundleBase(params) with TLAddrChannel
|
||||||
{
|
{
|
||||||
|
val channelName = "'B' channel"
|
||||||
// fixed fields during multibeat:
|
// fixed fields during multibeat:
|
||||||
val opcode = UInt(width = 3)
|
val opcode = UInt(width = 3)
|
||||||
val param = UInt(width = 3)
|
val param = UInt(width = 3)
|
||||||
@ -135,6 +140,7 @@ final class TLBundleB(params: TLBundleParameters)
|
|||||||
final class TLBundleC(params: TLBundleParameters)
|
final class TLBundleC(params: TLBundleParameters)
|
||||||
extends TLBundleBase(params) with TLAddrChannel
|
extends TLBundleBase(params) with TLAddrChannel
|
||||||
{
|
{
|
||||||
|
val channelName = "'C' channel"
|
||||||
// fixed fields during multibeat:
|
// fixed fields during multibeat:
|
||||||
val opcode = UInt(width = 3)
|
val opcode = UInt(width = 3)
|
||||||
val param = UInt(width = 3)
|
val param = UInt(width = 3)
|
||||||
@ -150,6 +156,7 @@ final class TLBundleC(params: TLBundleParameters)
|
|||||||
final class TLBundleD(params: TLBundleParameters)
|
final class TLBundleD(params: TLBundleParameters)
|
||||||
extends TLBundleBase(params) with TLDataChannel
|
extends TLBundleBase(params) with TLDataChannel
|
||||||
{
|
{
|
||||||
|
val channelName = "'D' channel"
|
||||||
// fixed fields during multibeat:
|
// fixed fields during multibeat:
|
||||||
val opcode = UInt(width = 3)
|
val opcode = UInt(width = 3)
|
||||||
val param = UInt(width = 2)
|
val param = UInt(width = 2)
|
||||||
@ -165,16 +172,17 @@ final class TLBundleD(params: TLBundleParameters)
|
|||||||
final class TLBundleE(params: TLBundleParameters)
|
final class TLBundleE(params: TLBundleParameters)
|
||||||
extends TLBundleBase(params) with TLChannel
|
extends TLBundleBase(params) with TLChannel
|
||||||
{
|
{
|
||||||
|
val channelName = "'E' channel"
|
||||||
val sink = UInt(width = params.sinkBits) // to
|
val sink = UInt(width = params.sinkBits) // to
|
||||||
}
|
}
|
||||||
|
|
||||||
class TLBundle(params: TLBundleParameters) extends TLBundleBase(params)
|
class TLBundle(params: TLBundleParameters) extends TLBundleBase(params)
|
||||||
{
|
{
|
||||||
val a = Decoupled(new TLBundleA(params))
|
val a = Irrevocable(new TLBundleA(params))
|
||||||
val b = Decoupled(new TLBundleB(params)).flip
|
val b = Irrevocable(new TLBundleB(params)).flip
|
||||||
val c = Decoupled(new TLBundleC(params))
|
val c = Irrevocable(new TLBundleC(params))
|
||||||
val d = Decoupled(new TLBundleD(params)).flip
|
val d = Irrevocable(new TLBundleD(params)).flip
|
||||||
val e = Decoupled(new TLBundleE(params))
|
val e = Irrevocable(new TLBundleE(params))
|
||||||
}
|
}
|
||||||
|
|
||||||
object TLBundle
|
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
|
// 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)) =>
|
((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)
|
out.a <> AsyncIrrevocableCrossing(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)
|
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) {
|
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)
|
in.b <> AsyncIrrevocableCrossing(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.c <> AsyncIrrevocableCrossing(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)
|
out.e <> AsyncIrrevocableCrossing(io.in_clock, io.in_reset, in.e, io.out_clock, io.out_reset, depth, sync)
|
||||||
} else {
|
} else {
|
||||||
in.b.valid := Bool(false)
|
in.b.valid := Bool(false)
|
||||||
in.c.ready := Bool(true)
|
in.c.ready := Bool(true)
|
||||||
|
@ -4,6 +4,7 @@ package uncore.tilelink2
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
|
import chisel3.internal.sourceinfo.{SourceInfo, SourceLine}
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
|
|
||||||
object TLMonitor
|
object TLMonitor
|
||||||
{
|
{
|
||||||
@ -14,7 +15,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeFormatA(bundle: TLBundleA, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeFormatA(bundle: TLBundleA, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
assert (TLMessages.isA(bundle.opcode), "'A' channel has invalid opcode" + extra)
|
assert (TLMessages.isA(bundle.opcode), "'A' channel has invalid opcode" + extra)
|
||||||
|
|
||||||
// Reuse these subexpressions to save some firrtl lines
|
// Reuse these subexpressions to save some firrtl lines
|
||||||
@ -79,7 +80,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeFormatB(bundle: TLBundleB, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeFormatB(bundle: TLBundleB, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
assert (TLMessages.isB(bundle.opcode), "'B' channel has invalid opcode" + extra)
|
assert (TLMessages.isB(bundle.opcode), "'B' channel has invalid opcode" + extra)
|
||||||
|
|
||||||
// Reuse these subexpressions to save some firrtl lines
|
// Reuse these subexpressions to save some firrtl lines
|
||||||
@ -144,7 +145,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeFormatC(bundle: TLBundleC, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeFormatC(bundle: TLBundleC, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
assert (TLMessages.isC(bundle.opcode), "'C' channel has invalid opcode" + extra)
|
assert (TLMessages.isC(bundle.opcode), "'C' channel has invalid opcode" + extra)
|
||||||
|
|
||||||
val source_ok = edge.client.contains(bundle.source)
|
val source_ok = edge.client.contains(bundle.source)
|
||||||
@ -210,7 +211,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeFormatD(bundle: TLBundleD, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeFormatD(bundle: TLBundleD, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
assert (TLMessages.isD(bundle.opcode), "'D' channel has invalid opcode" + extra)
|
assert (TLMessages.isD(bundle.opcode), "'D' channel has invalid opcode" + extra)
|
||||||
|
|
||||||
val source_ok = edge.client.contains(bundle.source)
|
val source_ok = edge.client.contains(bundle.source)
|
||||||
@ -268,7 +269,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeFormatE(bundle: TLBundleE, edge: TLEdge)(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)
|
assert (edge.manager.containsById(bundle.sink), "'E' channels carries invalid sink ID" + extra)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +281,7 @@ object TLMonitor
|
|||||||
when (bundle.e.valid) { legalizeFormatE(bundle.e.bits, edge) }
|
when (bundle.e.valid) { legalizeFormatE(bundle.e.bits, edge) }
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeMultibeatA(a: DecoupledIO[TLBundleA], edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeMultibeatA(a: IrrevocableIO[TLBundleA], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
||||||
val opcode = Reg(UInt())
|
val opcode = Reg(UInt())
|
||||||
val param = Reg(UInt())
|
val param = Reg(UInt())
|
||||||
@ -307,7 +308,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeMultibeatB(b: DecoupledIO[TLBundleB], edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeMultibeatB(b: IrrevocableIO[TLBundleB], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
||||||
val opcode = Reg(UInt())
|
val opcode = Reg(UInt())
|
||||||
val param = Reg(UInt())
|
val param = Reg(UInt())
|
||||||
@ -334,7 +335,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeMultibeatC(c: DecoupledIO[TLBundleC], edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeMultibeatC(c: IrrevocableIO[TLBundleC], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
||||||
val opcode = Reg(UInt())
|
val opcode = Reg(UInt())
|
||||||
val param = Reg(UInt())
|
val param = Reg(UInt())
|
||||||
@ -364,7 +365,7 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeMultibeatD(d: DecoupledIO[TLBundleD], edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeMultibeatD(d: IrrevocableIO[TLBundleD], edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
val counter = RegInit(UInt(0, width = log2Up(edge.maxTransfer)))
|
||||||
val opcode = Reg(UInt())
|
val opcode = Reg(UInt())
|
||||||
val param = Reg(UInt())
|
val param = Reg(UInt())
|
||||||
@ -394,16 +395,37 @@ object TLMonitor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalizeMultibeat(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
def legalizeMultibeat(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) {
|
||||||
legalizeMultibeatA(bundle.a, edge)
|
legalizeMultibeatA(bundle.a, edge)
|
||||||
legalizeMultibeatB(bundle.b, edge)
|
legalizeMultibeatB(bundle.b, edge)
|
||||||
legalizeMultibeatC(bundle.c, edge)
|
legalizeMultibeatC(bundle.c, edge)
|
||||||
legalizeMultibeatD(bundle.d, edge)
|
legalizeMultibeatD(bundle.d, edge)
|
||||||
}
|
}
|
||||||
|
|
||||||
def legalize(bundle: TLBundle, edge: TLEdge)(implicit sourceInfo: SourceInfo) = {
|
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)
|
legalizeFormat (bundle, edge)
|
||||||
legalizeMultibeat (bundle, edge)
|
legalizeMultibeat (bundle, edge)
|
||||||
|
legalizeIrrevocable(bundle, edge)
|
||||||
// !!! validate source uniqueness
|
// !!! validate source uniqueness
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
package uncore.tilelink2
|
package uncore.tilelink2
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
import uncore.util.{SimpleRegIO}
|
import uncore.util.{SimpleRegIO}
|
||||||
|
|
||||||
case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt))
|
case class RegReadFn private(combinational: Boolean, fn: (Bool, Bool) => (Bool, Bool, UInt))
|
||||||
@ -34,8 +34,8 @@ object RegReadFn
|
|||||||
val (ovalid, data) = x(oready)
|
val (ovalid, data) = x(oready)
|
||||||
(Bool(true), ovalid, data)
|
(Bool(true), ovalid, data)
|
||||||
})
|
})
|
||||||
// read from a DecoupledIO (only safe if there is a consistent source of data)
|
// read from a IrrevocableIO (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) })
|
implicit def apply(x: IrrevocableIO[UInt]):RegReadFn = RegReadFn(ready => { x.ready := ready; (x.valid, x.bits) })
|
||||||
// read from a register
|
// read from a register
|
||||||
implicit def apply(x: UInt):RegReadFn = RegReadFn(ready => (Bool(true), x))
|
implicit def apply(x: UInt):RegReadFn = RegReadFn(ready => (Bool(true), x))
|
||||||
// noop
|
// noop
|
||||||
@ -69,8 +69,8 @@ object RegWriteFn
|
|||||||
new RegWriteFn(true, { case (_, oready, data) =>
|
new RegWriteFn(true, { case (_, oready, data) =>
|
||||||
(Bool(true), x(oready, data))
|
(Bool(true), x(oready, data))
|
||||||
})
|
})
|
||||||
// write to a DecoupledIO (only safe if there is a consistent sink draining data)
|
// write to a IrrevocableIO (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 })
|
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)
|
// 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) })
|
implicit def apply(x: UInt): RegWriteFn = RegWriteFn((valid, data) => { when (valid) { x := data }; Bool(true) })
|
||||||
// noop
|
// noop
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package uncore.tilelink2
|
package uncore.tilelink2
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
|
|
||||||
// A bus agnostic register interface to a register-based device
|
// 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 endIndex = 1 << log2Ceil(regmap.map(_._1).max+1)
|
||||||
val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits)
|
val params = RegMapperParams(log2Up(endIndex), bytes, in.bits.params.extraBits)
|
||||||
|
|
||||||
val out = Wire(Decoupled(new RegMapperOutput(params)))
|
val out = Wire(Irrevocable(new RegMapperOutput(params)))
|
||||||
val front = Wire(Decoupled(new RegMapperInput(params)))
|
val front = Wire(Irrevocable(new RegMapperInput(params)))
|
||||||
front.bits := in.bits
|
front.bits := in.bits
|
||||||
|
|
||||||
// Must this device pipeline the control channel?
|
// Must this device pipeline the control channel?
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
package uncore.tilelink2
|
package uncore.tilelink2
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
import junctions._
|
import junctions._
|
||||||
|
|
||||||
// A very simple flow control state machine, run in the specified clock domain
|
// A very simple flow control state machine, run in the specified clock domain
|
||||||
@ -24,8 +25,8 @@ class BusyRegisterCrossing(clock: Clock, reset: Bool)
|
|||||||
|
|
||||||
// RegField should support connecting to one of these
|
// RegField should support connecting to one of these
|
||||||
class RegisterWriteIO[T <: Data](gen: T) extends Bundle {
|
class RegisterWriteIO[T <: Data](gen: T) extends Bundle {
|
||||||
val request = Decoupled(gen).flip()
|
val request = Irrevocable(gen).flip()
|
||||||
val response = Decoupled(Bool()) // ignore .bits
|
val response = Irrevocable(Bool()) // ignore .bits
|
||||||
}
|
}
|
||||||
|
|
||||||
// To turn on/off a domain:
|
// To turn on/off a domain:
|
||||||
@ -84,8 +85,8 @@ class RegisterWriteCrossing[T <: Data](gen: T, sync: Int = 3) extends Module {
|
|||||||
|
|
||||||
// RegField should support connecting to one of these
|
// RegField should support connecting to one of these
|
||||||
class RegisterReadIO[T <: Data](gen: T) extends Bundle {
|
class RegisterReadIO[T <: Data](gen: T) extends Bundle {
|
||||||
val request = Decoupled(Bool()).flip() // ignore .bits
|
val request = Irrevocable(Bool()).flip() // ignore .bits
|
||||||
val response = Decoupled(gen)
|
val response = Irrevocable(gen)
|
||||||
}
|
}
|
||||||
|
|
||||||
class RegisterReadCrossingIO[T <: Data](gen: T) extends Bundle {
|
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.rvalid := rvalid(rfire)
|
||||||
io.wready := wready(wfire)
|
io.wready := wready(wfire)
|
||||||
|
|
||||||
io.rdata := Mux(rfire, reg, UInt(0))
|
io.rdata := reg
|
||||||
when (wfire) { reg := io.wdata }
|
when (wfire) { reg := io.wdata }
|
||||||
}
|
}
|
||||||
|
|
||||||
object RRTestCombinational
|
object RRTestCombinational
|
||||||
{
|
{
|
||||||
private var seed = 42
|
private var seed = 42
|
||||||
|
|
||||||
def always: Bool => Bool = _ => Bool(true)
|
def always: Bool => Bool = _ => Bool(true)
|
||||||
def random: Bool => Bool = {
|
|
||||||
|
def random: Bool => Bool = { fire =>
|
||||||
seed = seed + 1
|
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 =>
|
def delay(x: Int): Bool => Bool = { fire =>
|
||||||
val reg = RegInit(UInt(0, width = log2Ceil(x+1)))
|
val reg = RegInit(UInt(0, width = log2Ceil(x+1)))
|
||||||
val ready = reg === UInt(0)
|
val ready = reg === UInt(0)
|
||||||
@ -89,7 +95,7 @@ class RRTestRequest(val bits: Int,
|
|||||||
val rofire = io.roready && rovalid
|
val rofire = io.roready && rovalid
|
||||||
val wofire = io.woready && wovalid
|
val wofire = io.woready && wovalid
|
||||||
|
|
||||||
io.rdata := Mux(rofire, reg, UInt(0))
|
io.rdata := reg
|
||||||
when (wofire) { reg := wdata }
|
when (wofire) { reg := wdata }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,22 +121,27 @@ object RRTestRequest
|
|||||||
}
|
}
|
||||||
(ready(0), full(x-1), data(x-1))
|
(ready(0), full(x-1), data(x-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
def busy: (Bool, Bool, UInt) => (Bool, Bool, UInt) = {
|
def busy: (Bool, Bool, UInt) => (Bool, Bool, UInt) = {
|
||||||
seed = seed + 1
|
seed = seed + 1
|
||||||
(ivalid, oready, idata) => {
|
(ivalid, oready, idata) => {
|
||||||
val lfsr = LFSR16Seed(seed)
|
val lfsr = LFSR16Seed(seed)
|
||||||
val busy = RegInit(Bool(false))
|
val busy = RegInit(Bool(false))
|
||||||
val data = Reg(UInt(width = idata.getWidth))
|
val data = Reg(UInt(width = idata.getWidth))
|
||||||
val progress = lfsr(0)
|
val progress = RegInit(Bool(false))
|
||||||
when (progress) {
|
|
||||||
busy := Mux(busy, !oready, ivalid)
|
|
||||||
}
|
|
||||||
val iready = progress && !busy
|
val iready = progress && !busy
|
||||||
val ovalid = progress && busy
|
val ovalid = progress && busy
|
||||||
|
when (progress) {
|
||||||
|
busy := Mux(busy, !oready, ivalid)
|
||||||
|
progress := !oready
|
||||||
|
} .otherwise {
|
||||||
|
progress := lfsr(0)
|
||||||
|
}
|
||||||
when (ivalid && iready) { data := idata }
|
when (ivalid && iready) { data := idata }
|
||||||
(iready, ovalid, data)
|
(iready, ovalid, data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def request(bits: Int,
|
def request(bits: Int,
|
||||||
rflow: (Bool, Bool, UInt) => (Bool, Bool, UInt),
|
rflow: (Bool, Bool, UInt) => (Bool, Bool, UInt),
|
||||||
wflow: (Bool, Bool, UInt) => (Bool, Bool, UInt)): RegField = {
|
wflow: (Bool, Bool, UInt) => (Bool, Bool, UInt)): RegField = {
|
||||||
|
@ -4,6 +4,7 @@ package uncore.tilelink2
|
|||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
import chisel3.internal.sourceinfo.SourceInfo
|
import chisel3.internal.sourceinfo.SourceInfo
|
||||||
|
import chisel3.util.{Irrevocable, IrrevocableIO}
|
||||||
import scala.math.{min,max}
|
import scala.math.{min,max}
|
||||||
|
|
||||||
// innBeatBytes => the new client-facing bus width
|
// innBeatBytes => the new client-facing bus width
|
||||||
@ -19,7 +20,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule
|
|||||||
val out = node.bundleOut
|
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 inBytes = edgeIn.manager.beatBytes
|
||||||
val outBytes = edgeOut.manager.beatBytes
|
val outBytes = edgeOut.manager.beatBytes
|
||||||
val ratio = outBytes / inBytes
|
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 inBytes = edgeIn.manager.beatBytes
|
||||||
val outBytes = edgeOut.manager.beatBytes
|
val outBytes = edgeOut.manager.beatBytes
|
||||||
val ratio = inBytes / outBytes
|
val ratio = inBytes / outBytes
|
||||||
@ -131,7 +132,7 @@ class TLWidthWidget(innerBeatBytes: Int) extends LazyModule
|
|||||||
// addr_lo gets truncated automagically
|
// 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) {
|
if (edgeIn.manager.beatBytes == edgeOut.manager.beatBytes) {
|
||||||
// nothing to do; pass it through
|
// nothing to do; pass it through
|
||||||
out <> in
|
out <> in
|
||||||
|
Loading…
Reference in New Issue
Block a user