Skip to content

Commit

Permalink
fix master
Browse files Browse the repository at this point in the history
  • Loading branch information
hansemandse committed Nov 24, 2020
1 parent 54a4c87 commit df7bde4
Show file tree
Hide file tree
Showing 4 changed files with 107 additions and 37 deletions.
2 changes: 1 addition & 1 deletion axi4/src/main/scala/VivadoAXIMemory.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,5 +136,5 @@ class VivadoAXIMemory extends Slave(1, 10, 32) {

/** Clock and reset */
mem.io.s00_axi_aclk := clock
mem.io.s00_axi_aresetn := !reset
mem.io.s00_axi_aresetn := reset
}
72 changes: 37 additions & 35 deletions axi4/src/main/scala/axi4/AXI4FunctionalMaster.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,22 +54,6 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
*/
def hasInflightOps() = inFlightReads.length > 0 || inFlightWrites.length > 0

/** Watch the response channel
*
* @note never call this method explicitly
*/
private[this] def respHandler() = {
println("New response handler")

/** Indicate that interface is ready and wait for response */
wr.ready.poke(true.B)
while (!wr.valid.peek.isLit) {
clk.step()
}
responses = responses :+ (new Response(wr.bits.resp.peek, wr.bits.id.peek.litValue))
wr.ready.poke(false.B)
}

/** Handle the write address channel
*
* @note never call this method explicitly
Expand All @@ -89,9 +73,9 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
aw.bits.prot.poke(prot)
aw.bits.qos.poke(qos)
aw.bits.region.poke(region)
do {
while (!aw.ready.peek.litToBoolean) {
clk.step()
} while (!aw.ready.peek.isLit)
}
clk.step()
aw.valid.poke(false.B)

Expand All @@ -110,15 +94,16 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
println("New write handler")

/** Write data to slave */
dw.valid.poke(true.B)
while (!inFlightWrites.head.complete) {
dw.valid.poke(true.B)
val (data, strb, last) = inFlightWrites.head.next
println("Write " + data.litValue + " with strobe " + strb.toString + " and last " + last.litToBoolean)
dw.bits.data.poke(data)
dw.bits.strb.poke(strb)
dw.bits.last.poke(last)
do {
while (!dw.ready.peek.litToBoolean) {
clk.step()
} while (!dw.ready.peek.isLit)
}
clk.step()
}
dw.valid.poke(false.B)
Expand All @@ -131,6 +116,22 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
}
}

/** Watch the response channel
*
* @note never call this method explicitly
*/
private[this] def respHandler() = {
println("New response handler")

/** Indicate that interface is ready and wait for response */
wr.ready.poke(true.B)
while (!wr.valid.peek.litToBoolean) {
clk.step()
}
responses = responses :+ (new Response(wr.bits.resp.peek, wr.bits.id.peek.litValue))
wr.ready.poke(false.B)
}

/** Handle the read address channel
*
* @note never call this method explicitly
Expand All @@ -150,9 +151,9 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
ar.bits.prot.poke(prot)
ar.bits.qos.poke(qos)
ar.bits.region.poke(region)
do {
while (!ar.ready.peek.litToBoolean) {
clk.step()
} while (!ar.ready.peek.isLit)
}
clk.step()
ar.valid.poke(false.B)

Expand All @@ -168,20 +169,21 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
* @note never call this method explicitly
*/
private[this] def readHandler(): Unit = {
println("New read handler")

/** Read data from slave */
dr.ready.poke(true.B)
while (!inFlightReads.head.complete) {
dr.ready.poke(false.B)
if (dr.valid.peek.isLit) {
// Accept read data
dr.ready.poke(true.B)
val resp = dr.bits.resp.peek
if (resp == ResponseEncodings.Decerr || resp == ResponseEncodings.Slverr)
println(s"[Error] reading failed with response $resp")
inFlightReads.head.add(dr.bits.data.peek.litValue)
if (dr.valid.peek.litToBoolean) {
val (data, resp, last) = (dr.bits.data.peek, dr.bits.resp.peek, dr.bits.last.peek)
println(s"Read " + data.litValue + " with response " + resp.litValue + " and last " + last.litToBoolean)
inFlightReads.head.add(data.litValue)
}
clk.step()
}
readValues = readValues :+ inFlightReads.head.data
inFlightReads = inFlightReads.tail
dr.ready.poke(false.B)
}

/** Initialize the interface (reset)
Expand Down Expand Up @@ -259,7 +261,7 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
* @param id optional id, defaults to ID 0
* @param len optional burst length, defaults to 0 (i.e., 1 beat)
* @param size optional beat size, defaults to 1 byte
* @param burst optional burst type, defaults to INCR
* @param burst optional burst type, defaults to FIXED
* @param lock optional lock type, defaults to normal access
* @param cache optional memory attribute signal, defaults to device non-bufferable
* @param prot optional protection type, defaults to non-secure unprivileged data access
Expand All @@ -277,7 +279,7 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
id: BigInt = 0,
len: Int = 0,
size: Int = 0,
burst: UInt = BurstEncodings.Incr,
burst: UInt = BurstEncodings.Fixed,
lock: Bool = LockEncodings.NormalAccess,
cache: UInt = MemoryEncodings.DeviceNonbuf,
prot: UInt = ProtectionEncodings.DataNsecUpriv,
Expand Down Expand Up @@ -334,7 +336,7 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
* @param id optional id, defaults to ID 0
* @param len optional burst length, defaults to 0 (i.e., 1 beat)
* @param size optional beat size, defaults to 1 byte
* @param burst optional burst type, defaults to INCR
* @param burst optional burst type, defaults to FIXED
* @param lock optional lock type, defaults to normal access
* @param cache optional memory attribute signal, defaults to device non-bufferable
* @param prot optional protection type, defaults to non-secure unprivileged data access
Expand All @@ -350,7 +352,7 @@ class AXI4FunctionalMaster[T <: Slave](dut: T) {
id: BigInt = 0,
len: Int = 0,
size: Int = 0,
burst: UInt = BurstEncodings.Incr,
burst: UInt = BurstEncodings.Fixed,
lock: Bool = LockEncodings.NormalAccess,
cache: UInt = MemoryEncodings.DeviceNonbuf,
prot: UInt = ProtectionEncodings.DataNsecUpriv,
Expand Down
2 changes: 1 addition & 1 deletion axi4/src/main/scala/axi4/Transaction.scala
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class WriteTransaction(addr: BigInt, data: Seq[BigInt], dataW: Int, size: Int =
val offset = (address / dataW) * dataW
val lowerByteLane = address - offset
val upperByteLane = if (aligned) lowerByteLane + numBytes-1 else alignedAddress + numBytes-1 - offset
def within(x: Int) = x >= lowerByteLane && x <= upperByteLane
def within(x: Int) = x >= 0 && x <= (upperByteLane - lowerByteLane)
val strb = ("b"+(0 until (dataW/8)).foldRight("") { (elem, acc) => if (within(elem)) acc + "1" else acc + "0" }).asUInt

/** Update address */
Expand Down
68 changes: 68 additions & 0 deletions axi4/src/test/scala/VivadoAXIMemoryTester.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,4 +92,72 @@ class VivadoAXIMemoryTester extends FlatSpec with ChiselScalatestTester with Mat
master.close()
}
}

it should "write and read with FIXED transactions" in {
test(new VivadoAXIMemory()).withAnnotations(Seq(VerilatorBackendAnnotation)) {
dut =>
val master = new AXI4FunctionalMaster(dut)
master.initialize()

// Create write transaction
master.createWriteTrx(0, Seq(42), size = 2)

// Wait for the write to complete (spin on response)
var resp = master.checkResponse()
while (resp == None) {
resp = master.checkResponse()
dut.clock.step()
}
val r = resp match { case Some(r) => r.resp.litValue; case _ => ResponseEncodings.Slverr.litValue }
assert(r == 0, "expected write to pass")

// Create read transaction
master.createReadTrx(0, size = 2)

// Wait for read to complete (spin on read data)
var data = master.checkReadData()
while (data == None) {
data = master.checkReadData()
dut.clock.step()
}
val d = data match { case Some(v) => v; case _ => Seq() }
assert(d.length == 1 && d(0) == 42, "read data value is incorrect")

master.close()
}
}

it should "write and read with INCR transactions" in {
test(new VivadoAXIMemory()).withAnnotations(Seq(VerilatorBackendAnnotation)) {
dut =>
val master = new AXI4FunctionalMaster(dut)
master.initialize()

// Create write transaction
master.createWriteTrx(128, Seq.fill(128)(0x7FFFFFFF), len = 0x7F, size = 2, burst = BurstEncodings.Incr)

// Wait for the write to complete (spin on response)
var resp = master.checkResponse()
while (resp == None) {
resp = master.checkResponse()
dut.clock.step()
}
val r = resp match { case Some(r) => r.resp.litValue; case _ => ResponseEncodings.Slverr.litValue }
assert(r == 0, "expected write to pass")

// Create read transaction
master.createReadTrx(128, len = 0x7F, size = 2, burst = BurstEncodings.Incr)

// Wait for read to complete (spin on read data)
var data = master.checkReadData()
while (data == None) {
data = master.checkReadData()
dut.clock.step()
}
val d = data match { case Some(v) => v; case _ => Seq() }
assert(d.foldLeft(true) { (acc, elem) => acc && (elem == 0x7FFFFFFF) }, "read data value is incorrect")

master.close()
}
}
}

0 comments on commit df7bde4

Please sign in to comment.