1
0

tilelink2: use byte-aligned addressing

This makes it possible to fully validate user input in a monitor.
We will override the lower bits with constant 0s in the TL connect.
This commit is contained in:
Wesley W. Terpstra 2016-08-22 13:18:01 -07:00
parent 45e152e97e
commit 8cff45f254
2 changed files with 48 additions and 30 deletions

View File

@ -11,16 +11,13 @@ class TLEdgeOut(
{
// Transfers
def Acquire(fromSource: UInt, toAddress: UInt, lgSize: UInt, growPermissions: UInt) = {
// !!! Monitor: lgSize >= beatBytes
// !!! Monitor: check address alignment
// !!! Monitor: check param values
val legal = manager.supportsAcquire(toAddress, lgSize)
val a = new TLBundleA(bundle)
a.opcode := TLMessages.Acquire
a.param := growPermissions
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := SInt(-1).asUInt
a.data := UInt(0)
(legal, a)
@ -33,7 +30,7 @@ class TLEdgeOut(
c.param := shrinkPermissions
c.size := lgSize
c.source := fromSource
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := UInt(0)
c.error := Bool(false)
(legal, c)
@ -46,7 +43,7 @@ class TLEdgeOut(
c.param := shrinkPermissions
c.size := lgSize
c.source := fromSource
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := data
c.error := Bool(false)
(legal, c)
@ -58,7 +55,7 @@ class TLEdgeOut(
c.param := reportPermissions
c.size := lgSize
c.source := UInt(0)
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := UInt(0)
c.error := Bool(false)
c
@ -70,7 +67,7 @@ class TLEdgeOut(
c.param := reportPermissions
c.size := lgSize
c.source := UInt(0)
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := data
c.error := Bool(false)
c
@ -90,7 +87,7 @@ class TLEdgeOut(
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := fullMask(toAddress, lgSize)
a.data := UInt(0)
(legal, a)
@ -103,21 +100,20 @@ class TLEdgeOut(
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := fullMask(toAddress, lgSize)
a.data := data
(legal, a)
}
def Put(fromSource: UInt, toAddress: UInt, lgSize: UInt, data: UInt, wmask: UInt) = {
// !!! Monitor: check that wmask is contained in lgSize
val legal = manager.supportsPutPartial(toAddress, lgSize)
val a = new TLBundleA(bundle)
a.opcode := TLMessages.PutPartialData
a.param := UInt(0)
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := wmask
a.data := data
(legal, a)
@ -130,7 +126,7 @@ class TLEdgeOut(
a.param := atomic
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := fullMask(toAddress, lgSize)
a.data := data
(legal, a)
@ -143,7 +139,7 @@ class TLEdgeOut(
a.param := atomic
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := fullMask(toAddress, lgSize)
a.data := data
(legal, a)
@ -156,7 +152,7 @@ class TLEdgeOut(
a.param := param
a.size := lgSize
a.source := fromSource
a.address := toAddress >> log2Up(manager.beatBytes)
a.address := toAddress
a.wmask := fullMask(toAddress, lgSize)
a.data := UInt(0)
(legal, a)
@ -168,7 +164,7 @@ class TLEdgeOut(
c.param := UInt(0)
c.size := lgSize
c.source := UInt(0)
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := UInt(0)
c.error := error
c
@ -180,7 +176,7 @@ class TLEdgeOut(
c.param := UInt(0)
c.size := lgSize
c.source := UInt(0)
c.address := toAddress >> log2Up(manager.beatBytes)
c.address := toAddress
c.data := data
c.error := Bool(false)
c
@ -200,7 +196,7 @@ class TLEdgeIn(
b.param := capPermissions
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := UInt(0)
(legal, b)
@ -250,7 +246,7 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := UInt(0)
(legal, b)
@ -263,7 +259,7 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := data
(legal, b)
@ -276,7 +272,7 @@ class TLEdgeIn(
b.param := UInt(0)
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := wmask
b.data := data
(legal, b)
@ -289,7 +285,7 @@ class TLEdgeIn(
b.param := atomic
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := data
(legal, b)
@ -302,7 +298,7 @@ class TLEdgeIn(
b.param := atomic
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := data
(legal, b)
@ -315,13 +311,12 @@ class TLEdgeIn(
b.param := param
b.size := lgSize
b.source := toSource
b.address := fromAddress >> log2Up(manager.beatBytes)
b.address := fromAddress
b.wmask := fullMask(fromAddress, lgSize)
b.data := UInt(0)
(legal, b)
}
def AccessAck(toSource: UInt, lgSize: UInt, error: Bool = Bool(false)) = {
val d = new TLBundleD(bundle)
d.opcode := TLMessages.AccessAck

View File

@ -272,16 +272,39 @@ case class TLEdgeParameters(
val maxTransfer = max(client.maxTransfer, manager.maxTransfer)
val maxLgSize = log2Up(maxTransfer)
// Sanity check the link...
require (maxTransfer >= manager.beatBytes)
val bundle = TLBundleParameters(
addressBits = log2Up(manager.maxAddress + 1) - log2Up(manager.beatBytes),
addressBits = log2Up(manager.maxAddress + 1),
dataBits = manager.beatBytes * 8,
sourceBits = log2Up(client.endSourceId),
sinkBits = log2Up(manager.endSinkId),
sizeBits = log2Up(maxLgSize+1))
def addressMask(lgSize: UInt) = Vec.tabulate(maxLgSize) { UInt(_) < lgSize } .toBits.asUInt
def isAligned(address: UInt, lgSize: UInt) = (address & addressMask(lgSize)) === UInt(0)
def isAligned(address: UInt, lgSize: UInt) =
if (maxLgSize == 0) Bool(true) else {
val mask = Vec.tabulate(maxLgSize) { UInt(_) < lgSize }
address & mask.toBits.asUInt === UInt(0)
}
// !!! wrong:
def fullMask(address: UInt, lgSize: UInt) = UInt(0)
// This gets used everywhere, so make the smallest circuit possible ...
def fullMask(address: UInt, lgSize: UInt) = {
val lgBytes = log2Ceil(manager.beatBytes)
def helper(i: Int): Seq[(Bool, Bool)] = {
if (i == 0) {
Seq((lgSize >= UInt(lgBytes), Bool(true)))
} else {
val sub = helper(i-1)
val size = lgSize === UInt(lgBytes - i)
Seq.tabulate (1 << i) { j =>
val (sub_acc, sub_eq) = sub(j/2)
val eq = sub_eq && address(lgBytes - i) === Bool(j % 2 == 1)
val acc = sub_acc || (size && eq)
(acc, eq)
}
}
}
Vec(helper(lgBytes).map(_._1)).toBits.asUInt
}
}