tilelink2: refactor address into addr_hi on ABC and addr_lo on CD
We need addr_lo in order to properly convert widths. As part of the refactoring, move all methods out of the Bundles
This commit is contained in:
		| @@ -100,151 +100,72 @@ object TLAtomics | ||||
|   def isLogical(x: UInt) = x <= SWAP | ||||
| } | ||||
|  | ||||
| class Bogus | ||||
| object Bogus | ||||
| { | ||||
|   def apply() = new Bogus | ||||
| } | ||||
| sealed trait TLChannel | ||||
| sealed trait TLDataChannel extends TLChannel | ||||
| sealed trait TLAddrChannel extends TLDataChannel | ||||
|  | ||||
| object ChannelType { | ||||
|   sealed trait T | ||||
|   case object A extends T | ||||
|   case object B extends T | ||||
|   case object C extends T | ||||
|   case object D extends T | ||||
|   case object E extends T | ||||
|   val cases = Seq(A, B, C, D, E) | ||||
| } | ||||
|  | ||||
| trait HasTLOpcode | ||||
| { | ||||
|   // The data field in this message has value | ||||
|   def hasData(x: Bogus = Bogus()): Bool | ||||
|   // This message requires a response | ||||
|   def hasFollowUp(x: Bogus = Bogus()): Bool | ||||
|   // What channel type is this? | ||||
|   def channelType(x: Bogus = Bogus()): ChannelType.T | ||||
|   // The size field of the opcode | ||||
|   def size(x: Bogus = Bogus()): UInt | ||||
| } | ||||
|  | ||||
| trait HasTLData extends HasTLOpcode | ||||
| { | ||||
|   def data(x: Bogus = Bogus()): UInt | ||||
|   def mask(x: Bogus = Bogus()): UInt | ||||
| } | ||||
|  | ||||
| class TLBundleA(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) | ||||
|   with HasTLData | ||||
| final class TLBundleA(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) with TLAddrChannel | ||||
| { | ||||
|   // fixed fields during multibeat: | ||||
|   val opcode  = UInt(width = 3) | ||||
|   val param   = UInt(width = 3) // amo_opcode || perms || hint | ||||
|   val size    = UInt(width = params.sizeBits) | ||||
|   val source  = UInt(width = params.sourceBits)  // from | ||||
|   val address = UInt(width = params.addressBits) // to | ||||
|   val source  = UInt(width = params.sourceBits) // from | ||||
|   val addr_hi = UInt(width = params.addrHiBits) // to | ||||
|   // variable fields during multibeat: | ||||
|   val mask    = UInt(width = params.dataBits/8) | ||||
|   val data    = UInt(width = params.dataBits) | ||||
|  | ||||
|   def hasData(x: Bogus = Bogus()) = !opcode(2) | ||||
| //    opcode === TLMessages.PutFullData    || | ||||
| //    opcode === TLMessages.PutPartialData || | ||||
| //    opcode === TLMessages.ArithmeticData || | ||||
| //    opcode === TLMessages.LogicalData | ||||
|   def hasFollowUp(x: Bogus = Bogus()) = Bool(true) | ||||
|   def channelType(x: Bogus = Bogus()) = ChannelType.A | ||||
|   def size(x: Bogus = Bogus()) = size | ||||
|   def data(x: Bogus = Bogus()) = data | ||||
|   def mask(x: Bogus = Bogus()) = mask | ||||
| } | ||||
|  | ||||
| class TLBundleB(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) | ||||
|   with HasTLData | ||||
| final class TLBundleB(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) with TLAddrChannel | ||||
| { | ||||
|   // fixed fields during multibeat: | ||||
|   val opcode  = UInt(width = 3) | ||||
|   val param   = UInt(width = 3) | ||||
|   val size    = UInt(width = params.sizeBits) | ||||
|   val source  = UInt(width = params.sourceBits)  // to | ||||
|   val address = UInt(width = params.addressBits) // from | ||||
|   val source  = UInt(width = params.sourceBits) // to | ||||
|   val addr_hi = UInt(width = params.addrHiBits) // from | ||||
|   // variable fields during multibeat: | ||||
|   val mask    = UInt(width = params.dataBits/8) | ||||
|   val data    = UInt(width = params.dataBits) | ||||
|  | ||||
|   def hasData(x: Bogus = Bogus()) = !opcode(2) | ||||
|   def hasFollowUp(x: Bogus = Bogus()) = Bool(true) | ||||
|   def channelType(x: Bogus = Bogus()) = ChannelType.B | ||||
|   def size(x: Bogus = Bogus()) = size | ||||
|   def data(x: Bogus = Bogus()) = data | ||||
|   def mask(x: Bogus = Bogus()) = mask | ||||
| } | ||||
|  | ||||
| class TLBundleC(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) | ||||
|   with HasTLData | ||||
| final class TLBundleC(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) with TLAddrChannel | ||||
| { | ||||
|   // fixed fields during multibeat: | ||||
|   val opcode  = UInt(width = 3) | ||||
|   val param   = UInt(width = 3) | ||||
|   val size    = UInt(width = params.sizeBits) | ||||
|   val source  = UInt(width = params.sourceBits)  // from | ||||
|   val address = UInt(width = params.addressBits) // to | ||||
|   val source  = UInt(width = params.sourceBits) // from | ||||
|   val addr_hi = UInt(width = params.addrHiBits) // to | ||||
|   val addr_lo = UInt(width = params.addrLoBits) // instead of mask | ||||
|   // variable fields during multibeat: | ||||
|   val data    = UInt(width = params.dataBits) | ||||
|   val error   = Bool() // AccessAck[Data] | ||||
|  | ||||
|   def hasData(x: Bogus = Bogus()) = opcode(0) | ||||
| //    opcode === TLMessages.AccessAckData || | ||||
| //    opcode === TLMessages.ProbeAckData  || | ||||
| //    opcode === TLMessages.ReleaseData | ||||
|   def hasFollowUp(x: Bogus = Bogus()) = opcode(2) && opcode(1) | ||||
| //    opcode === TLMessages.Release || | ||||
| //    opcode === TLMessages.ReleaseData | ||||
|   def channelType(x: Bogus = Bogus()) = ChannelType.C | ||||
|   def size(x: Bogus = Bogus()) = size | ||||
|   def data(x: Bogus = Bogus()) = data | ||||
|   def mask(x: Bogus = Bogus()) = SInt(-1, width = params.dataBits/8).asUInt | ||||
| } | ||||
|  | ||||
| class TLBundleD(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) | ||||
|   with HasTLData | ||||
| final class TLBundleD(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) with TLDataChannel | ||||
| { | ||||
|   // fixed fields during multibeat: | ||||
|   val opcode = UInt(width = 3) | ||||
|   val param  = UInt(width = 2) | ||||
|   val size   = UInt(width = params.sizeBits) | ||||
|   val source = UInt(width = params.sourceBits) // to | ||||
|   val sink   = UInt(width = params.sinkBits)   // from | ||||
|   val opcode  = UInt(width = 3) | ||||
|   val param   = UInt(width = 2) | ||||
|   val size    = UInt(width = params.sizeBits) | ||||
|   val source  = UInt(width = params.sourceBits) // to | ||||
|   val sink    = UInt(width = params.sinkBits)   // from | ||||
|   val addr_lo = UInt(width = params.addrLoBits) // instead of mask | ||||
|   // variable fields during multibeat: | ||||
|   val data   = UInt(width = params.dataBits) | ||||
|   val error  = Bool() // AccessAck[Data], Grant[Data] | ||||
|  | ||||
|   def hasData(x: Bogus = Bogus()) = opcode(0) | ||||
| //    opcode === TLMessages.AccessAckData || | ||||
| //    opcode === TLMessages.GrantData | ||||
|   def hasFollowUp(x: Bogus = Bogus()) = opcode(2) && !opcode(1) | ||||
| //    opcode === TLMessages.Grant     || | ||||
| //    opcode === TLMessages.GrantData | ||||
|   def channelType(x: Bogus = Bogus()) = ChannelType.D | ||||
|   def size(x: Bogus = Bogus()) = size | ||||
|   def data(x: Bogus = Bogus()) = data | ||||
|   def mask(x: Bogus = Bogus()) = SInt(-1, width = params.dataBits/8).asUInt | ||||
|   val data    = UInt(width = params.dataBits) | ||||
|   val error   = Bool() // AccessAck[Data], Grant[Data] | ||||
| } | ||||
|  | ||||
| class TLBundleE(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) | ||||
|   with HasTLOpcode | ||||
| final class TLBundleE(params: TLBundleParameters) | ||||
|   extends TLBundleBase(params) with TLChannel | ||||
| { | ||||
|   val sink = UInt(width = params.sourceBits) // to | ||||
|  | ||||
|   def hasData(x: Bogus = Bogus()) = Bool(false) | ||||
|   def hasFollowUp(x: Bogus = Bogus()) = Bool(false) | ||||
|   def channelType(x: Bogus = Bogus()) = ChannelType.E | ||||
|   def size(x: Bogus = Bogus()) = UInt(log2Up(params.dataBits/8)) | ||||
| } | ||||
|  | ||||
| class TLBundle(params: TLBundleParameters) extends TLBundleBase(params) | ||||
|   | ||||
| @@ -10,14 +10,22 @@ class TLEdge( | ||||
|   manager: TLManagerPortParameters) | ||||
|   extends TLEdgeParameters(client, manager) | ||||
| { | ||||
|   def isAligned(address: UInt, lgSize: UInt) = | ||||
|   def isHiAligned(addr_hi: UInt, lgSize: UInt): Bool = { | ||||
|     if (maxLgSize == 0) Bool(true) else { | ||||
|       val mask = ~(SInt(-1, width=maxLgSize).asUInt << lgSize)(maxLgSize-1, 0) | ||||
|       (address & mask) === UInt(0) | ||||
|       val mask = UIntToOH1(lgSize, maxLgSize) >> log2Ceil(manager.beatBytes) | ||||
|       (addr_hi & mask) === UInt(0) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def isLoAligned(addr_lo: UInt, lgSize: UInt): Bool = { | ||||
|     if (maxLgSize == 0) Bool(true) else { | ||||
|       val mask = UIntToOH1(lgSize, maxLgSize) | ||||
|       (addr_lo & mask) === UInt(0) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // This gets used everywhere, so make the smallest circuit possible ... | ||||
|   def fullMask(address: UInt, lgSize: UInt) = { | ||||
|   def mask(addr_lo: UInt, lgSize: UInt): UInt = { | ||||
|     val lgBytes = log2Ceil(manager.beatBytes) | ||||
|     val sizeOH = UIntToOH(lgSize, lgBytes) | ||||
|     def helper(i: Int): Seq[(Bool, Bool)] = { | ||||
| @@ -26,7 +34,7 @@ class TLEdge( | ||||
|       } else { | ||||
|         val sub = helper(i-1) | ||||
|         val size = sizeOH(lgBytes - i) | ||||
|         val bit = address(lgBytes - i) | ||||
|         val bit = addr_lo(lgBytes - i) | ||||
|         val nbit = !bit | ||||
|         Seq.tabulate (1 << i) { j => | ||||
|           val (sub_acc, sub_eq) = sub(j/2) | ||||
| @@ -39,8 +47,8 @@ class TLEdge( | ||||
|     Cat(helper(lgBytes).map(_._1).reverse) | ||||
|   } | ||||
|  | ||||
|   def lowAddress(mask: UInt) = { | ||||
|     // Almost OHToUInt, but any bit in low => use low address | ||||
|   def addr_lo(mask: UInt): UInt = { | ||||
|     // Almost OHToUInt, but bits set => bits not set | ||||
|     def helper(mask: UInt, width: Int): UInt = { | ||||
|       if (width <= 1) { | ||||
|         UInt(0) | ||||
| @@ -56,9 +64,9 @@ class TLEdge( | ||||
|     helper(mask, bundle.dataBits/8) | ||||
|   } | ||||
|  | ||||
|   def staticHasData(bundle: HasTLOpcode): Option[Boolean] = { | ||||
|     bundle.channelType() match { | ||||
|       case ChannelType.A => { | ||||
|   def staticHasData(bundle: TLChannel): Option[Boolean] = { | ||||
|     bundle match { | ||||
|       case _:TLBundleA => { | ||||
|         // Do there exist A messages with Data? | ||||
|         val aDataYes = manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportPutFull || manager.anySupportPutPartial | ||||
|         // Do there exist A messages without Data? | ||||
| @@ -66,7 +74,7 @@ class TLEdge( | ||||
|         // Statically optimize the case where hasData is a constant | ||||
|         if (!aDataYes) Some(false) else if (!aDataNo) Some(true) else None | ||||
|       } | ||||
|       case ChannelType.B => { | ||||
|       case _:TLBundleB => { | ||||
|         // Do there exist B messages with Data? | ||||
|         val bDataYes = client.anySupportArithmetic || client.anySupportLogical || client.anySupportPutFull || client.anySupportPutPartial | ||||
|         // Do there exist B messages without Data? | ||||
| @@ -74,34 +82,119 @@ class TLEdge( | ||||
|         // Statically optimize the case where hasData is a constant | ||||
|         if (!bDataYes) Some(false) else if (!bDataNo) Some(true) else None | ||||
|       } | ||||
|       case ChannelType.C => { | ||||
|       case _:TLBundleC => { | ||||
|         // Do there eixst C messages with Data? | ||||
|         val cDataYes = client.anySupportGet || client.anySupportArithmetic || client.anySupportLogical || client.anySupportProbe | ||||
|         // Do there exist C messages without Data? | ||||
|         val cDataNo  = client.anySupportPutFull || client.anySupportPutPartial || client.anySupportHint || client.anySupportProbe | ||||
|         if (!cDataYes) Some(false) else if (!cDataNo) Some(true) else None | ||||
|       } | ||||
|       case ChannelType.D => { | ||||
|       case _:TLBundleD => { | ||||
|         // Do there eixst D messages with Data? | ||||
|         val dDataYes = manager.anySupportGet || manager.anySupportArithmetic || manager.anySupportLogical || manager.anySupportAcquire | ||||
|         // Do there exist D messages without Data? | ||||
|         val dDataNo  = manager.anySupportPutFull || manager.anySupportPutPartial || manager.anySupportHint || manager.anySupportAcquire | ||||
|         if (!dDataYes) Some(false) else if (!dDataNo) Some(true) else None | ||||
|       } | ||||
|       case ChannelType.E => Some(false) | ||||
|       case _:TLBundleE => Some(false) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def hasData(bundle: HasTLOpcode): Bool = | ||||
|     staticHasData(bundle).map(Bool(_)).getOrElse(bundle.hasData()) | ||||
|   def hasFollowUp(x: TLChannel): Bool = { | ||||
|     x match { | ||||
|       case a: TLBundleA => Bool(true) | ||||
|       case b: TLBundleB => Bool(true) | ||||
|       case c: TLBundleC => c.opcode(2) && c.opcode(1) | ||||
|         //    opcode === TLMessages.Release || | ||||
|         //    opcode === TLMessages.ReleaseData | ||||
|       case d: TLBundleD => d.opcode(2) && !d.opcode(1) | ||||
|         //    opcode === TLMessages.Grant     || | ||||
|         //    opcode === TLMessages.GrantData | ||||
|       case e: TLBundleE => Bool(false) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def numBeats(bundle: HasTLOpcode) = { | ||||
|     val hasData = this.hasData(bundle) | ||||
|     val size = bundle.size() | ||||
|     val cutoff = log2Ceil(manager.beatBytes) | ||||
|     val small = if (manager.maxTransfer <= manager.beatBytes) Bool(true) else size <= UInt(cutoff) | ||||
|     val decode = UIntToOH(size, maxLgSize+1) >> cutoff | ||||
|     Mux(!hasData || small, UInt(1), decode) | ||||
|   def hasData(x: TLChannel): Bool = { | ||||
|     val opdata = x match { | ||||
|       case a: TLBundleA => !a.opcode(2) | ||||
|         //    opcode === TLMessages.PutFullData    || | ||||
|         //    opcode === TLMessages.PutPartialData || | ||||
|         //    opcode === TLMessages.ArithmeticData || | ||||
|         //    opcode === TLMessages.LogicalData | ||||
|       case b: TLBundleB => !b.opcode(2) | ||||
|         //    opcode === TLMessages.PutFullData    || | ||||
|         //    opcode === TLMessages.PutPartialData || | ||||
|         //    opcode === TLMessages.ArithmeticData || | ||||
|         //    opcode === TLMessages.LogicalData | ||||
|       case c: TLBundleC => c.opcode(0) | ||||
|         //    opcode === TLMessages.AccessAckData || | ||||
|         //    opcode === TLMessages.ProbeAckData  || | ||||
|         //    opcode === TLMessages.ReleaseData | ||||
|       case d: TLBundleD => d.opcode(0) | ||||
|         //    opcode === TLMessages.AccessAckData || | ||||
|         //    opcode === TLMessages.GrantData | ||||
|       case e: TLBundleE => Bool(false) | ||||
|     } | ||||
|     staticHasData(x).map(Bool(_)).getOrElse(opdata) | ||||
|   } | ||||
|  | ||||
|   def size(x: TLDataChannel): UInt = { | ||||
|     x match { | ||||
|       case a: TLBundleA => a.size | ||||
|       case b: TLBundleB => b.size | ||||
|       case c: TLBundleC => c.size | ||||
|       case d: TLBundleD => d.size | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def data(x: TLDataChannel): UInt = { | ||||
|     x match { | ||||
|       case a: TLBundleA => a.data | ||||
|       case b: TLBundleB => b.data | ||||
|       case c: TLBundleC => c.data | ||||
|       case d: TLBundleD => d.data | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def mask(x: TLDataChannel): UInt = { | ||||
|     x match { | ||||
|       case a: TLBundleA => a.mask | ||||
|       case b: TLBundleB => b.mask | ||||
|       case c: TLBundleC => mask(c.addr_lo, c.size) | ||||
|       case d: TLBundleD => mask(d.addr_lo, d.size) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def addr_lo(x: TLDataChannel): UInt = { | ||||
|     x match { | ||||
|       case a: TLBundleA => addr_lo(a.mask) | ||||
|       case b: TLBundleB => addr_lo(b.mask) | ||||
|       case c: TLBundleC => c.addr_lo | ||||
|       case d: TLBundleD => d.addr_lo | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   def address(x: TLAddrChannel): UInt = { | ||||
|     val hi = x match { | ||||
|       case a: TLBundleA => a.addr_hi | ||||
|       case b: TLBundleB => b.addr_hi | ||||
|       case c: TLBundleC => c.addr_hi | ||||
|     } | ||||
|     if (manager.beatBytes == 1) hi else Cat(hi, addr_lo(x)) | ||||
|   } | ||||
|  | ||||
|   def numBeats(x: TLChannel): UInt = { | ||||
|     x match { | ||||
|       case _: TLBundleE => UInt(1) | ||||
|       case bundle: TLDataChannel => { | ||||
|         val hasData = this.hasData(bundle) | ||||
|         val size = this.size(bundle) | ||||
|         val cutoff = log2Ceil(manager.beatBytes) | ||||
|         val small = if (manager.maxTransfer <= manager.beatBytes) Bool(true) else size <= UInt(cutoff) | ||||
|         val decode = UIntToOH(size, maxLgSize+1) >> cutoff | ||||
|         Mux(!hasData || small, UInt(1), decode) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -119,7 +212,7 @@ class TLEdgeOut( | ||||
|     a.param   := growPermissions | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := SInt(-1).asUInt | ||||
|     a.data    := UInt(0) | ||||
|     (legal, a) | ||||
| @@ -133,7 +226,8 @@ class TLEdgeOut( | ||||
|     c.param   := shrinkPermissions | ||||
|     c.size    := lgSize | ||||
|     c.source  := fromSource | ||||
|     c.address := toAddress | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := UInt(0) | ||||
|     c.error   := Bool(false) | ||||
|     (legal, c) | ||||
| @@ -147,31 +241,34 @@ class TLEdgeOut( | ||||
|     c.param   := shrinkPermissions | ||||
|     c.size    := lgSize | ||||
|     c.source  := fromSource | ||||
|     c.address := toAddress | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := data | ||||
|     c.error   := Bool(false) | ||||
|     (legal, c) | ||||
|   } | ||||
|  | ||||
|   def ProbeAck(toAddress: UInt, lgSize: UInt, reportPermissions: UInt) = { | ||||
|   def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt) = { | ||||
|     val c = Wire(new TLBundleC(bundle)) | ||||
|     c.opcode  := TLMessages.ProbeAck | ||||
|     c.param   := reportPermissions | ||||
|     c.size    := lgSize | ||||
|     c.source  := UInt(0) | ||||
|     c.address := toAddress | ||||
|     c.source  := fromSource | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := UInt(0) | ||||
|     c.error   := Bool(false) | ||||
|     c | ||||
|   } | ||||
|  | ||||
|   def ProbeAck(toAddress: UInt, lgSize: UInt, reportPermissions: UInt, data: UInt) = { | ||||
|   def ProbeAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, reportPermissions: UInt, data: UInt) = { | ||||
|     val c = Wire(new TLBundleC(bundle)) | ||||
|     c.opcode  := TLMessages.ProbeAckData | ||||
|     c.param   := reportPermissions | ||||
|     c.size    := lgSize | ||||
|     c.source  := UInt(0) | ||||
|     c.address := toAddress | ||||
|     c.source  := fromSource | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := data | ||||
|     c.error   := Bool(false) | ||||
|     c | ||||
| @@ -192,8 +289,8 @@ class TLEdgeOut( | ||||
|     a.param   := UInt(0) | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.mask    := fullMask(toAddress, lgSize) | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask(toAddress, lgSize) | ||||
|     a.data    := UInt(0) | ||||
|     (legal, a) | ||||
|   } | ||||
| @@ -206,8 +303,8 @@ class TLEdgeOut( | ||||
|     a.param   := UInt(0) | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.mask    := fullMask(toAddress, lgSize) | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask(toAddress, lgSize) | ||||
|     a.data    := data | ||||
|     (legal, a) | ||||
|   } | ||||
| @@ -220,7 +317,7 @@ class TLEdgeOut( | ||||
|     a.param   := UInt(0) | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask | ||||
|     a.data    := data | ||||
|     (legal, a) | ||||
| @@ -234,8 +331,8 @@ class TLEdgeOut( | ||||
|     a.param   := atomic | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.mask    := fullMask(toAddress, lgSize) | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask(toAddress, lgSize) | ||||
|     a.data    := data | ||||
|     (legal, a) | ||||
|   } | ||||
| @@ -248,8 +345,8 @@ class TLEdgeOut( | ||||
|     a.param   := atomic | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.mask    := fullMask(toAddress, lgSize) | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask(toAddress, lgSize) | ||||
|     a.data    := data | ||||
|     (legal, a) | ||||
|   } | ||||
| @@ -262,45 +359,53 @@ class TLEdgeOut( | ||||
|     a.param   := param | ||||
|     a.size    := lgSize | ||||
|     a.source  := fromSource | ||||
|     a.address := toAddress | ||||
|     a.mask    := fullMask(toAddress, lgSize) | ||||
|     a.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     a.mask    := mask(toAddress, lgSize) | ||||
|     a.data    := UInt(0) | ||||
|     (legal, a) | ||||
|   } | ||||
|  | ||||
|   def AccessAck(toAddress: UInt, lgSize: UInt): TLBundleC = AccessAck(toAddress, lgSize, Bool(false)) | ||||
|   def AccessAck(toAddress: UInt, lgSize: UInt, error: Bool) = { | ||||
|   def AccessAck(b: TLBundleB): TLBundleC = AccessAck(b.source, address(b), b.size) | ||||
|   def AccessAck(b: TLBundleB, error: Bool): TLBundleC = AccessAck(b.source, address(b), b.size, error) | ||||
|   def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt): TLBundleC = AccessAck(fromSource, toAddress, lgSize, Bool(false)) | ||||
|   def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, error: Bool) = { | ||||
|     val c = Wire(new TLBundleC(bundle)) | ||||
|     c.opcode  := TLMessages.AccessAck | ||||
|     c.param   := UInt(0) | ||||
|     c.size    := lgSize | ||||
|     c.source  := UInt(0) | ||||
|     c.address := toAddress | ||||
|     c.source  := fromSource | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := UInt(0) | ||||
|     c.error   := error | ||||
|     c | ||||
|   } | ||||
|  | ||||
|   def AccessAck(toAddress: UInt, lgSize: UInt, data: UInt): TLBundleC = AccessAck(toAddress, lgSize, data, Bool(false)) | ||||
|   def AccessAck(toAddress: UInt, lgSize: UInt, data: UInt, error: Bool) = { | ||||
|   def AccessAck(b: TLBundleB, data: UInt): TLBundleC = AccessAck(b.source, address(b), b.size, data) | ||||
|   def AccessAck(b: TLBundleB, data: UInt, error: Bool): TLBundleC = AccessAck(b.source, address(b), b.size, data, error) | ||||
|   def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt): TLBundleC = AccessAck(fromSource, toAddress, lgSize, data, Bool(false)) | ||||
|   def AccessAck(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, error: Bool) = { | ||||
|     val c = Wire(new TLBundleC(bundle)) | ||||
|     c.opcode  := TLMessages.AccessAckData | ||||
|     c.param   := UInt(0) | ||||
|     c.size    := lgSize | ||||
|     c.source  := UInt(0) | ||||
|     c.address := toAddress | ||||
|     c.source  := fromSource | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := data | ||||
|     c.error   := error | ||||
|     c | ||||
|   } | ||||
|  | ||||
|   def HintAck(toAddress: UInt, lgSize: UInt) = { | ||||
|   def HintAck(b: TLBundleB): TLBundleC = HintAck(b.source, address(b), b.size) | ||||
|   def HintAck(fromSource: UInt, toAddress: UInt, lgSize: UInt) = { | ||||
|     val c = Wire(new TLBundleC(bundle)) | ||||
|     c.opcode  := TLMessages.HintAck | ||||
|     c.param   := UInt(0) | ||||
|     c.size    := lgSize | ||||
|     c.source  := UInt(0) | ||||
|     c.address := toAddress | ||||
|     c.source  := fromSource | ||||
|     c.addr_hi := toAddress >> log2Ceil(manager.beatBytes) | ||||
|     c.addr_lo := toAddress | ||||
|     c.data    := UInt(0) | ||||
|     c.error   := Bool(false) | ||||
|     c | ||||
| @@ -321,47 +426,50 @@ class TLEdgeIn( | ||||
|     b.param   := capPermissions | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := SInt(-1).asUInt | ||||
|     b.data    := UInt(0) | ||||
|     (legal, b) | ||||
|   } | ||||
|  | ||||
|   def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt): TLBundleD = Grant(fromSink, toSource, lgSize, capPermissions, Bool(false)) | ||||
|   def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, error: Bool) = { | ||||
|   def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt): TLBundleD = Grant(fromAddress, fromSink, toSource, lgSize, capPermissions, Bool(false)) | ||||
|   def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, error: Bool) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.Grant | ||||
|     d.param  := capPermissions | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := fromSink | ||||
|     d.data   := UInt(0) | ||||
|     d.error  := error | ||||
|     d.opcode  := TLMessages.Grant | ||||
|     d.param   := capPermissions | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := UInt(0) | ||||
|     d.error   := error | ||||
|     d | ||||
|   } | ||||
|  | ||||
|   def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt): TLBundleD = Grant(fromSink, toSource, lgSize, capPermissions, data, Bool(false)) | ||||
|   def Grant(fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt, error: Bool) = { | ||||
|   def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt): TLBundleD = Grant(fromAddress, fromSink, toSource, lgSize, capPermissions, data, Bool(false)) | ||||
|   def Grant(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, capPermissions: UInt, data: UInt, error: Bool) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.GrantData | ||||
|     d.param  := capPermissions | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := fromSink | ||||
|     d.data   := data | ||||
|     d.error  := error | ||||
|     d.opcode  := TLMessages.GrantData | ||||
|     d.param   := capPermissions | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := data | ||||
|     d.error   := error | ||||
|     d | ||||
|   } | ||||
|  | ||||
|   def ReleaseAck(toSource: UInt, lgSize: UInt) = { | ||||
|   def ReleaseAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.ReleaseAck | ||||
|     d.param  := UInt(0) | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := UInt(0) | ||||
|     d.data   := UInt(0) | ||||
|     d.error  := Bool(false) | ||||
|     d.opcode  := TLMessages.ReleaseAck | ||||
|     d.param   := UInt(0) | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := UInt(0) | ||||
|     d.error   := Bool(false) | ||||
|     d | ||||
|   } | ||||
|  | ||||
| @@ -374,8 +482,8 @@ class TLEdgeIn( | ||||
|     b.param   := UInt(0) | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.mask    := fullMask(fromAddress, lgSize) | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask(fromAddress, lgSize) | ||||
|     b.data    := UInt(0) | ||||
|     (legal, b) | ||||
|   } | ||||
| @@ -388,8 +496,8 @@ class TLEdgeIn( | ||||
|     b.param   := UInt(0) | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.mask    := fullMask(fromAddress, lgSize) | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask(fromAddress, lgSize) | ||||
|     b.data    := data | ||||
|     (legal, b) | ||||
|   } | ||||
| @@ -402,7 +510,7 @@ class TLEdgeIn( | ||||
|     b.param   := UInt(0) | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask | ||||
|     b.data    := data | ||||
|     (legal, b) | ||||
| @@ -416,8 +524,8 @@ class TLEdgeIn( | ||||
|     b.param   := atomic | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.mask    := fullMask(fromAddress, lgSize) | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask(fromAddress, lgSize) | ||||
|     b.data    := data | ||||
|     (legal, b) | ||||
|   } | ||||
| @@ -430,8 +538,8 @@ class TLEdgeIn( | ||||
|     b.param   := atomic | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.mask    := fullMask(fromAddress, lgSize) | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask(fromAddress, lgSize) | ||||
|     b.data    := data | ||||
|     (legal, b) | ||||
|   } | ||||
| @@ -444,47 +552,55 @@ class TLEdgeIn( | ||||
|     b.param   := param | ||||
|     b.size    := lgSize | ||||
|     b.source  := toSource | ||||
|     b.address := fromAddress | ||||
|     b.mask    := fullMask(fromAddress, lgSize) | ||||
|     b.addr_hi := fromAddress >> log2Ceil(manager.beatBytes) | ||||
|     b.mask    := mask(fromAddress, lgSize) | ||||
|     b.data    := UInt(0) | ||||
|     (legal, b) | ||||
|   } | ||||
|  | ||||
|   def AccessAck(toSource: UInt, lgSize: UInt): TLBundleD = AccessAck(toSource, lgSize, Bool(false)) | ||||
|   def AccessAck(toSource: UInt, lgSize: UInt, error: Bool) = { | ||||
|   def AccessAck(a: TLBundleA, fromSink: UInt): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size) | ||||
|   def AccessAck(a: TLBundleA, fromSink: UInt, error: Bool): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, error) | ||||
|   def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt): TLBundleD = AccessAck(fromAddress, fromSink, toSource, lgSize, Bool(false)) | ||||
|   def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, error: Bool) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.AccessAck | ||||
|     d.param  := UInt(0) | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := UInt(0) | ||||
|     d.data   := UInt(0) | ||||
|     d.error  := error | ||||
|     d.opcode  := TLMessages.AccessAck | ||||
|     d.param   := UInt(0) | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := UInt(0) | ||||
|     d.error   := error | ||||
|     d | ||||
|   } | ||||
|  | ||||
|   def AccessAck(toSource: UInt, lgSize: UInt, data: UInt): TLBundleD = AccessAck(toSource, lgSize, data, Bool(false)) | ||||
|   def AccessAck(toSource: UInt, lgSize: UInt, data: UInt, error: Bool) = { | ||||
|   def AccessAck(a: TLBundleA, fromSink: UInt, data: UInt): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, data) | ||||
|   def AccessAck(a: TLBundleA, fromSink: UInt, data: UInt, error: Bool): TLBundleD = AccessAck(address(a), fromSink, a.source, a.size, data, error) | ||||
|   def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, data: UInt): TLBundleD = AccessAck(fromAddress, fromSink, toSource, lgSize, data, Bool(false)) | ||||
|   def AccessAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt, data: UInt, error: Bool) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.AccessAckData | ||||
|     d.param  := UInt(0) | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := UInt(0) | ||||
|     d.data   := data | ||||
|     d.error  := error | ||||
|     d.opcode  := TLMessages.AccessAckData | ||||
|     d.param   := UInt(0) | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := data | ||||
|     d.error   := error | ||||
|     d | ||||
|   } | ||||
|  | ||||
|   def HintAck(toSource: UInt, lgSize: UInt) = { | ||||
|   def HintAck(a: TLBundleA, sink: UInt = UInt(0)): TLBundleD = HintAck(address(a), sink, a.source, a.size) | ||||
|   def HintAck(fromAddress: UInt, fromSink: UInt, toSource: UInt, lgSize: UInt) = { | ||||
|     val d = Wire(new TLBundleD(bundle)) | ||||
|     d.opcode := TLMessages.HintAck | ||||
|     d.param  := UInt(0) | ||||
|     d.size   := lgSize | ||||
|     d.source := toSource | ||||
|     d.sink   := UInt(0) | ||||
|     d.data   := UInt(0) | ||||
|     d.error  := Bool(false) | ||||
|     d.opcode  := TLMessages.HintAck | ||||
|     d.param   := UInt(0) | ||||
|     d.size    := lgSize | ||||
|     d.source  := toSource | ||||
|     d.sink    := fromSink | ||||
|     d.addr_lo := fromAddress | ||||
|     d.data    := UInt(0) | ||||
|     d.error   := Bool(false) | ||||
|     d | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -57,7 +57,9 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten | ||||
|     } | ||||
|  | ||||
|     // All managers must share a common FIFO domain (responses might end up interleaved) | ||||
|     val manager   = node.edgesOut(0).manager | ||||
|     val edgeOut   = node.edgesOut(0) | ||||
|     val edgeIn    = node.edgesIn(0) | ||||
|     val manager   = edgeOut.manager | ||||
|     val managers  = manager.managers | ||||
|     val beatBytes = manager.beatBytes | ||||
|     val fifoId = managers(0).fifoId | ||||
| @@ -137,9 +139,6 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten | ||||
|     val counterBits = log2Up(maxSize/beatBytes) | ||||
|     val maxDownSize = if (alwaysMin) minSize else manager.maxTransfer | ||||
|  | ||||
|     def OH1ToUInt(x: UInt) = OHToUInt((x << 1 | UInt(1)) ^ x) | ||||
|     def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) | ||||
|  | ||||
|     // First, handle the return path | ||||
|     val acknum = RegInit(UInt(0, width = counterBits)) | ||||
|     val dOrig = Reg(UInt()) | ||||
| @@ -147,7 +146,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten | ||||
|     val dFirst = acknum === UInt(0) | ||||
|     val dsizeOH  = UIntToOH (out.d.bits.size, log2Ceil(maxDownSize)+1) | ||||
|     val dsizeOH1 = UIntToOH1(out.d.bits.size, log2Ceil(maxDownSize)) | ||||
|     val dHasData = node.edgesOut(0).hasData(out.d.bits) | ||||
|     val dHasData = edgeOut.hasData(out.d.bits) | ||||
|  | ||||
|     // calculate new acknum | ||||
|     val acknum_fragment = dFragnum << log2Ceil(minSize/beatBytes) | ||||
| @@ -189,7 +188,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten | ||||
|     val maxLgHints       = maxHints      .map(m => if (m == 0) lgMinSize else UInt(log2Ceil(m))) | ||||
|  | ||||
|     // If this is infront of a single manager, these become constants | ||||
|     val find = manager.find(in.a.bits.address) | ||||
|     val find = manager.find(edgeIn.address(in.a.bits)) | ||||
|     val maxLgArithmetic  = Mux1H(find, maxLgArithmetics) | ||||
|     val maxLgLogical     = Mux1H(find, maxLgLogicals) | ||||
|     val maxLgGet         = Mux1H(find, maxLgGets) | ||||
| @@ -225,7 +224,7 @@ class TLFragmenter(minSize: Int, maxSize: Int, alwaysMin: Boolean = false) exten | ||||
|     out.a.valid := in.a.valid | ||||
|     in.a.ready := out.a.ready && !delay | ||||
|     out.a.bits := in.a.bits | ||||
|     out.a.bits.address := in.a.bits.address | (~aFragnum << log2Ceil(minSize) & aOrigOH1) | ||||
|     out.a.bits.addr_hi := in.a.bits.addr_hi | (~aFragnum << log2Ceil(minSize/beatBytes) & aOrigOH1 >> log2Ceil(beatBytes)) | ||||
|     out.a.bits.source := Cat(in.a.bits.source, aFragnum) | ||||
|     out.a.bits.size := aFrag | ||||
|  | ||||
|   | ||||
| @@ -28,13 +28,13 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f | ||||
|     require (!supportClients || bce) | ||||
|  | ||||
|     if (supportManagers) { | ||||
|       val handleA = if (passthrough) !edgeOut.manager.supportsHint(in.a.bits.address) else Bool(true) | ||||
|       val handleA = if (passthrough) !edgeOut.manager.supportsHint(edgeIn.address(in.a.bits)) else Bool(true) | ||||
|       val bypassD = handleA && in.a.bits.opcode === TLMessages.Hint | ||||
|  | ||||
|       // Prioritize existing D traffic over HintAck | ||||
|       in.d.valid  := out.d.valid || (bypassD && in.a.valid) | ||||
|       out.d.ready := in.d.ready | ||||
|       in.d.bits   := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits.source, in.a.bits.size)) | ||||
|       in.d.bits   := Mux(out.d.valid, out.d.bits, edgeIn.HintAck(in.a.bits)) | ||||
|  | ||||
|       in.a.ready  := Mux(bypassD, in.d.ready && !out.d.valid, out.a.ready) | ||||
|       out.a.valid := in.a.valid && !bypassD | ||||
| @@ -56,7 +56,7 @@ class TLHintHandler(supportManagers: Boolean = true, supportClients: Boolean = f | ||||
|       // Prioritize existing C traffic over HintAck | ||||
|       out.c.valid := in.c.valid || (bypassC && in.b.valid) | ||||
|       in.c.ready  := out.c.ready | ||||
|       out.c.bits  := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits.address, out.b.bits.size)) | ||||
|       out.c.bits  := Mux(in.c.valid, in.c.bits, edgeOut.HintAck(out.b.bits)) | ||||
|  | ||||
|       out.b.ready := Mux(bypassC, out.c.ready && !in.c.valid, in.b.ready) | ||||
|       in.b.valid  := out.b.valid && !bypassC | ||||
|   | ||||
| @@ -50,7 +50,7 @@ object LazyModule | ||||
|   } | ||||
| } | ||||
|  | ||||
| abstract class LazyModuleImp(val outer: LazyModule) extends Module | ||||
| abstract class LazyModuleImp(outer: LazyModule) extends Module | ||||
| { | ||||
|   // .module had better not be accessed while LazyModules are still being built! | ||||
|   require (LazyModule.stack.isEmpty) | ||||
|   | ||||
| @@ -104,14 +104,14 @@ class TLLegacy(implicit val p: Parameters) extends LazyModule with HasTileLinkPa | ||||
|     // Get rid of some unneeded muxes | ||||
|     out.a.bits.source  := source | ||||
|     out.a.bits.data    := data | ||||
|     out.a.bits.address := ~(~address | addressMask) | ||||
|     out.a.bits.addr_hi := ~(~address | addressMask) >> log2Ceil(tlDataBytes) | ||||
|  | ||||
|     // TL legacy does not support bus errors | ||||
|     assert (!out.d.bits.error) | ||||
|  | ||||
|     // Recreate the beat address counter | ||||
|     val beatCounter = RegInit(UInt(0, width = tlBeatAddrBits)) | ||||
|     when (out.d.fire() && out.d.bits.hasData() && out.d.bits.size === block) { | ||||
|     when (out.d.fire() && edge.hasData(out.d.bits) && out.d.bits.size === block) { | ||||
|       beatCounter := beatCounter + UInt(1) | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -19,20 +19,20 @@ object TLMonitor | ||||
|  | ||||
|     // Reuse these subexpressions to save some firrtl lines | ||||
|     val source_ok = edge.client.contains(bundle.source) | ||||
|     val is_aligned = edge.isAligned(bundle.address, bundle.size) | ||||
|     val mask = edge.fullMask(bundle.address | edge.lowAddress(bundle.mask), bundle.size) | ||||
|     val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size) | ||||
|     val mask = edge.mask(edge.addr_lo(bundle.mask), bundle.size) | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Acquire) { | ||||
|       assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'A' channel carries Acquire type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel Acquire carries invalid source ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'A' channel Acquire smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'A' channel Acquire address not aligned to size" + extra) | ||||
|       assert (TLPermissions.isGrow(bundle.param), "'A' channel Acquire carries invalid grow param" + extra) | ||||
|       assert (bundle.mask === SInt(-1).asUInt, "'A' channel Acquire contains invalid mask" + extra) | ||||
|       assert (~bundle.mask === UInt(0), "'A' channel Acquire contains invalid mask" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Get) { | ||||
|       assert (edge.manager.supportsGet(bundle.address, bundle.size), "'A' channel carries Get type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsGet(edge.address(bundle), bundle.size), "'A' channel carries Get type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel Get carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel Get address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'A' channel Get carries invalid param" + extra) | ||||
| @@ -40,7 +40,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.PutFullData) { | ||||
|       assert (edge.manager.supportsPutFull(bundle.address, bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsPutFull(edge.address(bundle), bundle.size), "'A' channel carries PutFull type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel PutFull carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel PutFull address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'A' channel PutFull carries invalid param" + extra) | ||||
| @@ -48,7 +48,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.PutPartialData) { | ||||
|       assert (edge.manager.supportsPutPartial(bundle.address, bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsPutPartial(edge.address(bundle), bundle.size), "'A' channel carries PutPartial type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel PutPartial carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel PutPartial address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'A' channel PutPartial carries invalid param" + extra) | ||||
| @@ -57,7 +57,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.ArithmeticData) { | ||||
|       assert (edge.manager.supportsArithmetic(bundle.address, bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsArithmetic(edge.address(bundle), bundle.size), "'A' channel carries Arithmetic type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel Arithmetic carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel Arithmetic address not aligned to size" + extra) | ||||
|       assert (TLAtomics.isArithmetic(bundle.param), "'A' channel Arithmetic carries invalid opcode param" + extra) | ||||
| @@ -65,7 +65,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.LogicalData) { | ||||
|       assert (edge.manager.supportsLogical(bundle.address, bundle.size), "'A' channel carries Logical type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsLogical(edge.address(bundle), bundle.size), "'A' channel carries Logical type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel Logical carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel Logical address not aligned to size" + extra) | ||||
|       assert (TLAtomics.isLogical(bundle.param), "'A' channel Logical carries invalid opcode param" + extra) | ||||
| @@ -73,7 +73,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Hint) { | ||||
|       assert (edge.manager.supportsHint(bundle.address), "'A' channel carries Hint type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsHint(edge.address(bundle)), "'A' channel carries Hint type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'A' channel Hint carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'A' channel Hint address not aligned to size" + extra) | ||||
|       assert (bundle.mask === mask, "'A' channel Hint contains invalid mask" + extra) | ||||
| @@ -85,8 +85,8 @@ object TLMonitor | ||||
|  | ||||
|     // Reuse these subexpressions to save some firrtl lines | ||||
|     val address_ok = edge.manager.contains(bundle.source) | ||||
|     val is_aligned = edge.isAligned(bundle.address, bundle.size) | ||||
|     val mask = edge.fullMask(bundle.address | edge.lowAddress(bundle.mask), bundle.size) | ||||
|     val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size) | ||||
|     val mask = edge.mask(edge.addr_lo(bundle.mask), bundle.size) | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Probe) { | ||||
|       assert (edge.client.supportsProbe(bundle.source, bundle.size), "'B' channel carries Probe type unsupported by client" + extra) | ||||
| @@ -94,7 +94,7 @@ object TLMonitor | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'B' channel Probe smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'B' channel Probe address not aligned to size" + extra) | ||||
|       assert (TLPermissions.isCap(bundle.param), "'B' channel Probe carries invalid cap param" + extra) | ||||
|       assert (bundle.mask === SInt(-1).asUInt, "'B' channel Probe contains invalid mask" + extra) | ||||
|       assert (~bundle.mask === UInt(0).asUInt, "'B' channel Probe contains invalid mask" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Get) { | ||||
| @@ -150,12 +150,12 @@ object TLMonitor | ||||
|     assert (TLMessages.isC(bundle.opcode), "'C' channel has invalid opcode" + extra) | ||||
|  | ||||
|     val source_ok = edge.client.contains(bundle.source) | ||||
|     val is_aligned = edge.isAligned(bundle.address, bundle.size) | ||||
|     val is_aligned = edge.isHiAligned(bundle.addr_hi, bundle.size) && edge.isLoAligned(bundle.addr_lo, bundle.size) | ||||
|     val address_ok = edge.manager.contains(bundle.source) | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.ProbeAck) { | ||||
|       assert (address_ok, "'C' channel ProbeAck carries unmanaged address" + extra) | ||||
|       // source is ignored | ||||
|       assert (source_ok, "'C' channel ProbeAck carries invalid source ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAck smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'C' channel ProbeAck address not aligned to size" + extra) | ||||
|       assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAck carries invalid report param" + extra) | ||||
| @@ -164,7 +164,7 @@ object TLMonitor | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.ProbeAckData) { | ||||
|       assert (address_ok, "'C' channel ProbeAckData carries unmanaged address" + extra) | ||||
|       // source is ignored | ||||
|       assert (source_ok, "'C' channel ProbeAckData carries invalid source ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ProbeAckData smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'C' channel ProbeAckData address not aligned to size" + extra) | ||||
|       assert (TLPermissions.isReport(bundle.param), "'C' channel ProbeAckData carries invalid report param" + extra) | ||||
| @@ -172,7 +172,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Release) { | ||||
|       assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'C' channel carries Release type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries Release type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'C' channel Release carries invalid source ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel Release smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'C' channel Release address not aligned to size" + extra) | ||||
| @@ -181,7 +181,7 @@ object TLMonitor | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.ReleaseData) { | ||||
|       assert (edge.manager.supportsAcquire(bundle.address, bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra) | ||||
|       assert (edge.manager.supportsAcquire(edge.address(bundle), bundle.size), "'C' channel carries ReleaseData type unsupported by manager" + extra) | ||||
|       assert (source_ok, "'C' channel ReleaseData carries invalid source ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'C' channel ReleaseData smaller than a beat" + extra) | ||||
|       assert (is_aligned, "'C' channel ReleaseData address not aligned to size" + extra) | ||||
| @@ -191,21 +191,21 @@ object TLMonitor | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.AccessAck) { | ||||
|       assert (address_ok, "'C' channel AccessAck carries unmanaged address" + extra) | ||||
|       // source is ignored | ||||
|       assert (source_ok, "'C' channel AccessAck carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'C' channel AccessAck address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'C' channel AccessAck carries invalid param" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.AccessAckData) { | ||||
|       assert (address_ok, "'C' channel AccessAckData carries unmanaged address" + extra) | ||||
|       // source is ignored | ||||
|       assert (source_ok, "'C' channel AccessAckData carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'C' channel AccessAckData address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'C' channel AccessAckData carries invalid param" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.HintAck) { | ||||
|       assert (address_ok, "'C' channel HintAck carries unmanaged address" + extra) | ||||
|       // source is ignored | ||||
|       assert (source_ok, "'C' channel HintAck carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'C' channel HintAck address not aligned to size" + extra) | ||||
|       assert (bundle.param === UInt(0), "'C' channel HintAck carries invalid param" + extra) | ||||
|       assert (!bundle.error, "'C' channel HintAck carries an error" + extra) | ||||
| @@ -216,11 +216,13 @@ object TLMonitor | ||||
|     assert (TLMessages.isD(bundle.opcode), "'D' channel has invalid opcode" + extra) | ||||
|  | ||||
|     val source_ok = edge.client.contains(bundle.source) | ||||
|     val is_aligned = edge.isLoAligned(bundle.addr_lo, bundle.size) | ||||
|     val sink_ok = edge.manager.containsById(bundle.sink) | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.ReleaseAck) { | ||||
|       assert (source_ok, "'D' channel ReleaseAck carries invalid source ID" + extra) | ||||
|       // sink is ignored | ||||
|       assert (is_aligned, "'D' channel ReleaseAck address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel ReleaseAck carries invalid sink ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel ReleaseAck smaller than a beat" + extra) | ||||
|       assert (bundle.param === UInt(0), "'D' channel ReleaseeAck carries invalid param" + extra) | ||||
|       assert (!bundle.error, "'D' channel ReleaseAck carries an error" + extra) | ||||
| @@ -228,6 +230,7 @@ object TLMonitor | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.Grant) { | ||||
|       assert (source_ok, "'D' channel Grant carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'D' channel Grant address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel Grant carries invalid sink ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel Grant smaller than a beat" + extra) | ||||
|       assert (TLPermissions.isCap(bundle.param), "'D' channel Grant carries invalid cap param" + extra) | ||||
| @@ -235,6 +238,7 @@ object TLMonitor | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.GrantData) { | ||||
|       assert (source_ok, "'D' channel GrantData carries invalid source ID" + extra) | ||||
|       assert (is_aligned, "'D' channel GrantData address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel GrantData carries invalid sink ID" + extra) | ||||
|       assert (bundle.size >= UInt(log2Ceil(edge.manager.beatBytes)), "'D' channel GrantData smaller than a beat" + extra) | ||||
|       assert (TLPermissions.isCap(bundle.param), "'D' channel GrantData carries invalid cap param" + extra) | ||||
| @@ -242,21 +246,24 @@ object TLMonitor | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.AccessAck) { | ||||
|       assert (source_ok, "'D' channel AccessAck carries invalid source ID" + extra) | ||||
|       // sink is ignored | ||||
|       assert (is_aligned, "'D' channel AccessAck address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel AccessAck carries invalid sink ID" + extra) | ||||
|       // size is ignored | ||||
|       assert (bundle.param === UInt(0), "'D' channel AccessAck carries invalid param" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.AccessAckData) { | ||||
|       assert (source_ok, "'D' channel AccessAckData carries invalid source ID" + extra) | ||||
|       // sink is ignored | ||||
|       assert (is_aligned, "'D' channel AccessAckData address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel AccessAckData carries invalid sink ID" + extra) | ||||
|       // size is ignored | ||||
|       assert (bundle.param === UInt(0), "'D' channel AccessAckData carries invalid param" + extra) | ||||
|     } | ||||
|  | ||||
|     when (bundle.opcode === TLMessages.HintAck) { | ||||
|       assert (source_ok, "'D' channel HintAck carries invalid source ID" + extra) | ||||
|       // sink is ignored | ||||
|       assert (is_aligned, "'D' channel HintAck address not aligned to size" + extra) | ||||
|       assert (sink_ok, "'D' channel HintAck carries invalid sink ID" + extra) | ||||
|       // size is ignored | ||||
|       assert (bundle.param === UInt(0), "'D' channel HintAck carries invalid param" + extra) | ||||
|       assert (!bundle.error, "'D' channel HintAck carries an error" + extra) | ||||
| @@ -281,13 +288,13 @@ object TLMonitor | ||||
|     val param   = Reg(UInt()) | ||||
|     val size    = Reg(UInt()) | ||||
|     val source  = Reg(UInt()) | ||||
|     val address = Reg(UInt()) | ||||
|     val addr_hi = Reg(UInt()) | ||||
|     when (a.valid && counter =/= UInt(0)) { | ||||
|       assert (a.bits.opcode === opcode, "'A' channel opcode changed within multibeat operation" + extra) | ||||
|       assert (a.bits.param  === param,  "'A' channel param changed within multibeat operation" + extra) | ||||
|       assert (a.bits.size   === size,   "'A' channel size changed within multibeat operation" + extra) | ||||
|       assert (a.bits.source === source, "'A' channel source changed within multibeat operation" + extra) | ||||
|       assert (a.bits.address=== address,"'A' channel address changed with multibeat operation" + extra) | ||||
|       assert (a.bits.addr_hi=== addr_hi,"'A' channel addr_hi changed with multibeat operation" + extra) | ||||
|     } | ||||
|     when (a.fire()) { | ||||
|       counter := counter - UInt(1) | ||||
| @@ -297,7 +304,7 @@ object TLMonitor | ||||
|         param   := a.bits.param | ||||
|         size    := a.bits.size | ||||
|         source  := a.bits.source | ||||
|         address := a.bits.address | ||||
|         addr_hi := a.bits.addr_hi | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -308,13 +315,13 @@ object TLMonitor | ||||
|     val param   = Reg(UInt()) | ||||
|     val size    = Reg(UInt()) | ||||
|     val source  = Reg(UInt()) | ||||
|     val address = Reg(UInt()) | ||||
|     val addr_hi = Reg(UInt()) | ||||
|     when (b.valid && counter =/= UInt(0)) { | ||||
|       assert (b.bits.opcode === opcode, "'B' channel opcode changed within multibeat operation" + extra) | ||||
|       assert (b.bits.param  === param,  "'B' channel param changed within multibeat operation" + extra) | ||||
|       assert (b.bits.size   === size,   "'B' channel size changed within multibeat operation" + extra) | ||||
|       assert (b.bits.source === source, "'B' channel source changed within multibeat operation" + extra) | ||||
|       assert (b.bits.address=== address,"'B' channel address changed with multibeat operation" + extra) | ||||
|       assert (b.bits.addr_hi=== addr_hi,"'B' channel addr_hi changed with multibeat operation" + extra) | ||||
|     } | ||||
|     when (b.fire()) { | ||||
|       counter := counter - UInt(1) | ||||
| @@ -324,7 +331,7 @@ object TLMonitor | ||||
|         param   := b.bits.param | ||||
|         size    := b.bits.size | ||||
|         source  := b.bits.source | ||||
|         address := b.bits.address | ||||
|         addr_hi := b.bits.addr_hi | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -335,13 +342,15 @@ object TLMonitor | ||||
|     val param   = Reg(UInt()) | ||||
|     val size    = Reg(UInt()) | ||||
|     val source  = Reg(UInt()) | ||||
|     val address = Reg(UInt()) | ||||
|     val addr_hi = Reg(UInt()) | ||||
|     val addr_lo = Reg(UInt()) | ||||
|     when (c.valid && counter =/= UInt(0)) { | ||||
|       assert (c.bits.opcode === opcode, "'C' channel opcode changed within multibeat operation" + extra) | ||||
|       assert (c.bits.param  === param,  "'C' channel param changed within multibeat operation" + extra) | ||||
|       assert (c.bits.size   === size,   "'C' channel size changed within multibeat operation" + extra) | ||||
|       assert (c.bits.source === source, "'C' channel source changed within multibeat operation" + extra) | ||||
|       assert (c.bits.address=== address,"'C' channel address changed with multibeat operation" + extra) | ||||
|       assert (c.bits.addr_hi=== addr_hi,"'C' channel addr_hi changed with multibeat operation" + extra) | ||||
|       assert (c.bits.addr_lo=== addr_lo,"'C' channel addr_lo changed with multibeat operation" + extra) | ||||
|     } | ||||
|     when (c.fire()) { | ||||
|       counter := counter - UInt(1) | ||||
| @@ -351,7 +360,8 @@ object TLMonitor | ||||
|         param   := c.bits.param | ||||
|         size    := c.bits.size | ||||
|         source  := c.bits.source | ||||
|         address := c.bits.address | ||||
|         addr_hi := c.bits.addr_hi | ||||
|         addr_lo := c.bits.addr_lo | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| @@ -363,12 +373,14 @@ object TLMonitor | ||||
|     val size    = Reg(UInt()) | ||||
|     val source  = Reg(UInt()) | ||||
|     val sink    = Reg(UInt()) | ||||
|     val addr_lo = Reg(UInt()) | ||||
|     when (d.valid && counter =/= UInt(0)) { | ||||
|       assert (d.bits.opcode === opcode, "'D' channel opcode changed within multibeat operation" + extra) | ||||
|       assert (d.bits.param  === param,  "'D' channel param changed within multibeat operation" + extra) | ||||
|       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) | ||||
|     } | ||||
|     when (d.fire()) { | ||||
|       counter := counter - UInt(1) | ||||
| @@ -379,6 +391,7 @@ object TLMonitor | ||||
|         size    := d.bits.size | ||||
|         source  := d.bits.source | ||||
|         sink    := d.bits.sink | ||||
|         addr_lo := d.bits.addr_lo | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -19,25 +19,25 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule | ||||
|       val out = node.bundleOut | ||||
|     } | ||||
|  | ||||
|     val edge = node.edgesOut(0) | ||||
|     val outerBeatBytes = edge.manager.beatBytes | ||||
|     val edgeOut = node.edgesOut(0) | ||||
|     val edgeIn  = node.edgesIn(0) | ||||
|     val outerBeatBytes = edgeOut.manager.beatBytes | ||||
|     require (outerBeatBytes < innerBeatBytes) | ||||
|  | ||||
|     val ratio = innerBeatBytes / outerBeatBytes | ||||
|     val bce = edge.manager.anySupportAcquire && edge.client.anySupportProbe | ||||
|     val bce = edgeOut.manager.anySupportAcquire && edgeIn.client.anySupportProbe | ||||
|  | ||||
|     def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) | ||||
|     def trailingZeros(x: Int) = if (x > 0) Some(log2Ceil(x & -x)) else None | ||||
|  | ||||
|     def split(in: HasTLData, fire: Bool): (Bool, UInt, UInt) = { | ||||
|       val dataSlices = Vec.tabulate (ratio) { i => in.data()((i+1)*outerBeatBytes*8-1, i*outerBeatBytes*8) } | ||||
|       val maskSlices = Vec.tabulate (ratio) { i => in.mask()((i+1)*outerBeatBytes  -1, i*outerBeatBytes)   } | ||||
|     def split(edge: TLEdge, in: TLDataChannel, fire: Bool): (Bool, UInt, UInt) = { | ||||
|       val dataSlices = Vec.tabulate (ratio) { i => edge.data(in)((i+1)*outerBeatBytes*8-1, i*outerBeatBytes*8) } | ||||
|       val maskSlices = Vec.tabulate (ratio) { i => edge.mask(in)((i+1)*outerBeatBytes  -1, i*outerBeatBytes)   } | ||||
|       val filter = Reg(UInt(width = ratio), init = SInt(-1, width = ratio).asUInt) | ||||
|       val mask = maskSlices.map(_.orR) | ||||
|       val hasData = edge.hasData(in) | ||||
|  | ||||
|       // decoded_size = 1111 (for smallest), 0101, 0001 (for largest) | ||||
|       val sizeOH1 = UIntToOH1(in.size(), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes) | ||||
|       val sizeOH1 = UIntToOH1(edge.size(in), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes) | ||||
|       val decoded_size = Seq.tabulate(ratio) { i => trailingZeros(i).map(!sizeOH1(_)).getOrElse(Bool(true)) } | ||||
|  | ||||
|       val first = filter(ratio-1) | ||||
| @@ -56,12 +56,12 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     def merge(in: HasTLData, fire: Bool): (Bool, UInt) = { | ||||
|     def merge(edge: TLEdge, in: TLDataChannel, fire: Bool): (Bool, UInt) = { | ||||
|       val count = RegInit(UInt(0, width = log2Ceil(ratio))) | ||||
|       val rdata = Reg(UInt(width = (ratio-1)*outerBeatBytes*8)) | ||||
|       val data = Cat(in.data(), rdata) | ||||
|       val data = Cat(edge.data(in), rdata) | ||||
|       val first = count === UInt(0) | ||||
|       val limit = UIntToOH1(in.size(), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes) | ||||
|       val limit = UIntToOH1(edge.size(in), log2Ceil(innerBeatBytes)) >> log2Ceil(outerBeatBytes) | ||||
|       val last = count === limit || !edge.hasData(in) | ||||
|  | ||||
|       when (fire) { | ||||
| @@ -82,21 +82,22 @@ class TLNarrower(innerBeatBytes: Int) extends LazyModule | ||||
|       if (edge.staticHasData(in) == Some(false)) { | ||||
|         (Bool(true), UInt(0)) | ||||
|       } else { | ||||
|         (last, mux(in.size())) | ||||
|         (last, mux(edge.size(in))) | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val out = io.out(0) | ||||
|  | ||||
|     val (alast, adata, amask) = split(in.a.bits, out.a.fire()) | ||||
|     val (alast, adata, amask) = split(edgeIn, in.a.bits, out.a.fire()) | ||||
|     in.a.ready := out.a.ready && alast | ||||
|     out.a.valid := in.a.valid | ||||
|     out.a.bits := in.a.bits | ||||
|     out.a.bits.addr_hi := Cat(in.a.bits.addr_hi, edgeIn.addr_lo(in.a.bits) >> log2Ceil(outerBeatBytes)) | ||||
|     out.a.bits.data := adata | ||||
|     out.a.bits.mask := amask | ||||
|  | ||||
|     val (dlast, ddata) = merge(out.d.bits, out.d.fire()) | ||||
|     val (dlast, ddata) = merge(edgeOut, out.d.bits, out.d.fire()) | ||||
|     out.d.ready := in.d.ready || !dlast | ||||
|     in.d.valid := out.d.valid && dlast | ||||
|     in.d.bits := out.d.bits | ||||
|   | ||||
| @@ -286,23 +286,25 @@ case class TLClientPortParameters(clients: Seq[TLClientParameters]) { | ||||
| } | ||||
|  | ||||
| case class TLBundleParameters( | ||||
|   addressBits: Int, | ||||
|   dataBits:    Int, | ||||
|   sourceBits:  Int, | ||||
|   sinkBits:    Int, | ||||
|   sizeBits:    Int) | ||||
|   addrHiBits: Int, | ||||
|   dataBits:   Int, | ||||
|   sourceBits: Int, | ||||
|   sinkBits:   Int, | ||||
|   sizeBits:   Int) | ||||
| { | ||||
|   // Chisel has issues with 0-width wires | ||||
|   require (addressBits >= 1) | ||||
|   require (dataBits    >= 1) | ||||
|   require (addrHiBits  >= 1) | ||||
|   require (dataBits    >= 8) | ||||
|   require (sourceBits  >= 1) | ||||
|   require (sinkBits    >= 1) | ||||
|   require (sizeBits    >= 1) | ||||
|   require (isPow2(dataBits)) | ||||
|    | ||||
|  | ||||
|   val addrLoBits = log2Up(dataBits/8) | ||||
|  | ||||
|   def union(x: TLBundleParameters) = | ||||
|     TLBundleParameters( | ||||
|       max(addressBits, x.addressBits), | ||||
|       max(addrHiBits,  x.addrHiBits), | ||||
|       max(dataBits,    x.dataBits), | ||||
|       max(sourceBits,  x.sourceBits), | ||||
|       max(sinkBits,    x.sinkBits), | ||||
| @@ -320,7 +322,7 @@ case class TLEdgeParameters( | ||||
|   require (maxTransfer >= manager.beatBytes) | ||||
|  | ||||
|   val bundle = TLBundleParameters( | ||||
|     addressBits = log2Up(manager.maxAddress + 1), | ||||
|     addrHiBits  = log2Up(manager.maxAddress + 1) - log2Up(manager.beatBytes), | ||||
|     dataBits    = manager.beatBytes * 8, | ||||
|     sourceBits  = log2Up(client.endSourceId), | ||||
|     sinkBits    = log2Up(manager.endSinkId), | ||||
|   | ||||
| @@ -20,14 +20,20 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB | ||||
|     val a = bundleIn(0).a | ||||
|     val d = bundleIn(0).d | ||||
|     val edge = edgesIn(0) | ||||
|   | ||||
|     val params = RegMapperParams(log2Up(address.mask+1), beatBytes, edge.bundle.sourceBits + edge.bundle.sizeBits) | ||||
|  | ||||
|     // Please forgive me ... | ||||
|     val baseEnd = 0 | ||||
|     val (sizeEnd,   sizeOff)   = (edge.bundle.sizeBits   + baseEnd, baseEnd) | ||||
|     val (sourceEnd, sourceOff) = (edge.bundle.sourceBits + sizeEnd, sizeEnd) | ||||
|     val (addrLoEnd, addrLoOff) = (log2Ceil(beatBytes)    + sourceEnd, sourceEnd) | ||||
|  | ||||
|     val params = RegMapperParams(log2Up(address.mask+1), beatBytes, addrLoEnd) | ||||
|     val in = Wire(Decoupled(new RegMapperInput(params))) | ||||
|     in.bits.read  := a.bits.opcode === TLMessages.Get | ||||
|     in.bits.index := a.bits.address >> log2Ceil(beatBytes) | ||||
|     in.bits.index := a.bits.addr_hi | ||||
|     in.bits.data  := a.bits.data | ||||
|     in.bits.mask  := a.bits.mask | ||||
|     in.bits.extra := Cat(a.bits.source, a.bits.size) | ||||
|     in.bits.extra := Cat(edge.addr_lo(a.bits), a.bits.source, a.bits.size) | ||||
|  | ||||
|     // Invoke the register map builder | ||||
|     val (endIndex, out) = RegMapper(beatBytes, concurrency, in, mapping:_*) | ||||
| @@ -41,8 +47,13 @@ class TLRegisterNode(address: AddressSet, concurrency: Option[Int] = None, beatB | ||||
|     d.valid   := out.valid | ||||
|     out.ready := d.ready | ||||
|  | ||||
|     val sizeBits = edge.bundle.sizeBits | ||||
|     d.bits := edge.AccessAck(out.bits.extra >> sizeBits, out.bits.extra(sizeBits-1, 0)) | ||||
|     // We must restore the size and addr_lo to enable width adapters to work | ||||
|     d.bits := edge.AccessAck( | ||||
|       fromAddress = out.bits.extra(addrLoEnd-1, addrLoOff), | ||||
|       fromSink    = UInt(0), // our unique sink id | ||||
|       toSource    = out.bits.extra(sourceEnd-1, sourceOff), | ||||
|       lgSize      = out.bits.extra(sizeEnd-1, sizeOff)) | ||||
|  | ||||
|     // avoid a Mux on the data bus by manually overriding two fields | ||||
|     d.bits.data := out.bits.data | ||||
|     d.bits.opcode := Mux(out.bits.read, TLMessages.AccessAckData, TLMessages.AccessAck) | ||||
|   | ||||
| @@ -24,10 +24,10 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule | ||||
|  | ||||
|     def bigBits(x: BigInt, tail: List[Boolean] = List.empty[Boolean]): List[Boolean] = | ||||
|       if (x == 0) tail.reverse else bigBits(x >> 1, ((x & 1) == 1) :: tail) | ||||
|     val mask = bigBits(address.mask - (beatBytes-1)) | ||||
|     val mask = bigBits(address.mask >> log2Ceil(beatBytes)) | ||||
|  | ||||
|     val in = io.in(0) | ||||
|     val addrBits = (mask zip in.a.bits.address.toBools).filter(_._1).map(_._2) | ||||
|     val addrBits = (mask zip in.a.bits.addr_hi.toBools).filter(_._1).map(_._2) | ||||
|     val memAddress = Cat(addrBits.reverse) | ||||
|     val mem = SeqMem(1 << addrBits.size, Vec(beatBytes, Bits(width = 8))) | ||||
|  | ||||
| @@ -35,6 +35,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule | ||||
|     val d_read = Reg(Bool()) | ||||
|     val d_size = Reg(UInt()) | ||||
|     val d_source = Reg(UInt()) | ||||
|     val d_addr = Reg(UInt()) | ||||
|     val d_data = Wire(UInt()) | ||||
|  | ||||
|     // Flow control | ||||
| @@ -43,7 +44,8 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule | ||||
|     in.d.valid := d_full | ||||
|     in.a.ready := in.d.ready || !d_full | ||||
|  | ||||
|     in.d.bits := node.edgesIn(0).AccessAck(d_source, d_size) | ||||
|     val edge = node.edgesIn(0) | ||||
|     in.d.bits := edge.AccessAck(d_addr, UInt(0), d_source, d_size) | ||||
|     // avoid data-bus Mux | ||||
|     in.d.bits.data := d_data | ||||
|     in.d.bits.opcode := Mux(d_read, TLMessages.AccessAckData, TLMessages.AccessAck) | ||||
| @@ -56,6 +58,7 @@ class TLRAM(address: AddressSet, beatBytes: Int = 4) extends LazyModule | ||||
|       d_read   := read | ||||
|       d_size   := in.a.bits.size | ||||
|       d_source := in.a.bits.source | ||||
|       d_addr   := edge.addr_lo(in.a.bits) | ||||
|       when (read) { | ||||
|         rdata := mem.read(memAddress) | ||||
|       } .otherwise { | ||||
|   | ||||
| @@ -23,10 +23,6 @@ object TLImp extends NodeImp[TLClientPortParameters, TLManagerPortParameters, TL | ||||
|     require (eo.asInstanceOf[TLEdgeParameters] == ei.asInstanceOf[TLEdgeParameters]) | ||||
|     TLMonitor.legalize(bo, eo, bi, ei) | ||||
|     bi <> bo | ||||
|     val mask = UInt(ei.manager.beatBytes - 1) | ||||
|     bi.a.bits.address := ~(mask | ~bo.a.bits.address) | ||||
|     bo.b.bits.address := ~(mask | ~bi.b.bits.address) | ||||
|     bi.c.bits.address := ~(mask | ~bo.c.bits.address) | ||||
|   } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -145,11 +145,11 @@ class TLXbar(policy: (Vec[Bool], Bool) => Seq[Bool] = TLXbar.lowestIndex) extend | ||||
|       in(i).e.ready := Mux1C(grantedEIO(i), out.map(_.e.ready)) | ||||
|     } | ||||
|  | ||||
|     val requestAIO = Vec(in.map  { i => Vec(node.edgesOut.map  { o => i.a.valid && o.manager.contains(i.a.bits.address) }) }) | ||||
|     val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map  { i => o.b.valid && i        .contains(o.b.bits.source)  }) }) | ||||
|     val requestCIO = Vec(in.map  { i => Vec(node.edgesOut.map  { o => i.c.valid && o.manager.contains(i.c.bits.address) }) }) | ||||
|     val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map  { i => o.d.valid && i        .contains(o.d.bits.source)  }) }) | ||||
|     val requestEIO = Vec(in.map  { i => Vec(outputIdRanges.map { o => i.e.valid && o        .contains(i.e.bits.sink)    }) }) | ||||
|     val requestAIO = Vec(in.map  { i => Vec(node.edgesOut.map  { o => i.a.valid && o.manager.contains(o.address(i.a.bits)) }) }) | ||||
|     val requestBOI = Vec(out.map { o => Vec(inputIdRanges.map  { i => o.b.valid && i        .contains(o.b.bits.source)     }) }) | ||||
|     val requestCIO = Vec(in.map  { i => Vec(node.edgesOut.map  { o => i.c.valid && o.manager.contains(o.address(i.c.bits)) }) }) | ||||
|     val requestDOI = Vec(out.map { o => Vec(inputIdRanges.map  { i => o.d.valid && i        .contains(o.d.bits.source)     }) }) | ||||
|     val requestEIO = Vec(in.map  { i => Vec(outputIdRanges.map { o => i.e.valid && o        .contains(i.e.bits.sink)       }) }) | ||||
|  | ||||
|     val beatsA = Vec((in  zip node.edgesIn)  map { case (i, e) => e.numBeats(i.a.bits) }) | ||||
|     val beatsB = Vec((out zip node.edgesOut) map { case (o, e) => e.numBeats(o.b.bits) }) | ||||
|   | ||||
| @@ -5,4 +5,6 @@ import Chisel._ | ||||
| package object tilelink2 | ||||
| { | ||||
|   type TLBaseNode = BaseNode[TLClientPortParameters, TLManagerPortParameters, TLEdgeOut, TLEdgeIn, TLBundle] | ||||
|   def OH1ToUInt(x: UInt) = OHToUInt((x << 1 | UInt(1)) ^ x) | ||||
|   def UIntToOH1(x: UInt, width: Int) = ~(SInt(-1, width=width).asUInt << x)(width-1, 0) | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user