diff --git a/axi4/src/main/scala/VivadoAXIMemory.scala b/axi4/src/main/scala/VivadoAXIMemory.scala index 54659cd..43c0b61 100644 --- a/axi4/src/main/scala/VivadoAXIMemory.scala +++ b/axi4/src/main/scala/VivadoAXIMemory.scala @@ -79,34 +79,34 @@ class VivadoAXIMemory extends Slave(10, 32, 1) { val mem = Module(new mymem()) /** Connect it up with the slave's AXI interface */ - val aw = io.aw.bits - val dw = io.dw.bits + val wa = io.wa.bits + val wd = io.wd.bits val wr = io.wr.bits - val ar = io.ar.bits - val dr = io.dr.bits + val ra = io.ra.bits + val rd = io.rd.bits /** Address write */ - mem.io.s00_axi_awid := aw.id - mem.io.s00_axi_awaddr := aw.addr - mem.io.s00_axi_awlen := aw.len - mem.io.s00_axi_awsize := aw.size - mem.io.s00_axi_awburst := aw.burst - mem.io.s00_axi_awlock := aw.lock - mem.io.s00_axi_awcache := aw.cache - mem.io.s00_axi_awprot := aw.prot - mem.io.s00_axi_awregion := aw.region - mem.io.s00_axi_awqos := aw.qos + mem.io.s00_axi_awid := wa.id + mem.io.s00_axi_awaddr := wa.addr + mem.io.s00_axi_awlen := wa.len + mem.io.s00_axi_awsize := wa.size + mem.io.s00_axi_awburst := wa.burst + mem.io.s00_axi_awlock := wa.lock + mem.io.s00_axi_awcache := wa.cache + mem.io.s00_axi_awprot := wa.prot + mem.io.s00_axi_awregion := wa.region + mem.io.s00_axi_awqos := wa.qos // Leave user port unconnected - mem.io.s00_axi_awvalid := io.aw.valid - io.aw.ready := mem.io.s00_axi_awready + mem.io.s00_axi_awvalid := io.wa.valid + io.wa.ready := mem.io.s00_axi_awready /** Data write */ - mem.io.s00_axi_wdata := dw.data - mem.io.s00_axi_wstrb := dw.strb - mem.io.s00_axi_wlast := dw.last + mem.io.s00_axi_wdata := wd.data + mem.io.s00_axi_wstrb := wd.strb + mem.io.s00_axi_wlast := wd.last // Leave user port unconnected - mem.io.s00_axi_wvalid := io.dw.valid - io.dw.ready := mem.io.s00_axi_wready + mem.io.s00_axi_wvalid := io.wd.valid + io.wd.ready := mem.io.s00_axi_wready /** Write response */ wr.id := mem.io.s00_axi_bid @@ -117,29 +117,29 @@ class VivadoAXIMemory extends Slave(10, 32, 1) { mem.io.s00_axi_bready := io.wr.ready /** Address read */ - mem.io.s00_axi_arid := ar.id - mem.io.s00_axi_araddr := ar.addr - mem.io.s00_axi_arlen := ar.len - mem.io.s00_axi_arsize := ar.size - mem.io.s00_axi_arburst := ar.burst - mem.io.s00_axi_arlock := ar.lock - mem.io.s00_axi_arcache := ar.cache - mem.io.s00_axi_arprot := ar.prot - mem.io.s00_axi_arregion := ar.region - mem.io.s00_axi_arqos := ar.qos + mem.io.s00_axi_arid := ra.id + mem.io.s00_axi_araddr := ra.addr + mem.io.s00_axi_arlen := ra.len + mem.io.s00_axi_arsize := ra.size + mem.io.s00_axi_arburst := ra.burst + mem.io.s00_axi_arlock := ra.lock + mem.io.s00_axi_arcache := ra.cache + mem.io.s00_axi_arprot := ra.prot + mem.io.s00_axi_arregion := ra.region + mem.io.s00_axi_arqos := ra.qos // Leave user port unconnected - mem.io.s00_axi_arvalid := io.ar.valid - io.ar.ready := mem.io.s00_axi_arready + mem.io.s00_axi_arvalid := io.ra.valid + io.ra.ready := mem.io.s00_axi_arready /** Data read */ - dr.id := mem.io.s00_axi_rid - dr.data := mem.io.s00_axi_rdata - dr.resp := mem.io.s00_axi_rresp - dr.last := mem.io.s00_axi_rlast + rd.id := mem.io.s00_axi_rid + rd.data := mem.io.s00_axi_rdata + rd.resp := mem.io.s00_axi_rresp + rd.last := mem.io.s00_axi_rlast // Connect user port to constant 0 - dr.user := 0.U - io.dr.valid := mem.io.s00_axi_rvalid - mem.io.s00_axi_rready := io.dr.ready + rd.user := 0.U + io.rd.valid := mem.io.s00_axi_rvalid + mem.io.s00_axi_rready := io.rd.ready /** Clock and reset */ mem.io.s00_axi_aclk := clock diff --git a/axi4/src/main/scala/axi4/FunctionalMaster.scala b/axi4/src/main/scala/axi4/FunctionalMaster.scala index 136e754..eea6643 100644 --- a/axi4/src/main/scala/axi4/FunctionalMaster.scala +++ b/axi4/src/main/scala/axi4/FunctionalMaster.scala @@ -10,6 +10,7 @@ package axi4 import chisel3._ import chisel3.util._ +import chisel3.experimental.BundleLiterals._ import chiseltest._ import chiseltest.internal.TesterThreadList import scala.util.Random @@ -26,11 +27,11 @@ class FunctionalMaster[T <: Slave](dut: T) { private[this] val dataW = dut.dataW /** Shortcuts to the channel IO */ - private[this] val aw = dut.io.aw - private[this] val dw = dut.io.dw + private[this] val wa = dut.io.wa + private[this] val wd = dut.io.wd private[this] val wr = dut.io.wr - private[this] val ar = dut.io.ar - private[this] val dr = dut.io.dr + private[this] val ra = dut.io.ra + private[this] val rd = dut.io.rd private[this] val resetn = dut.reset private[this] val clk = dut.clock @@ -54,22 +55,22 @@ class FunctionalMaster[T <: Slave](dut: T) { /** Default values on all signals */ // Address write - aw.bits.pokePartial(WA.default(aw.bits)) - aw.valid.poke(false.B) + wa.bits.pokePartial(WA.default(wa.bits)) + wa.valid.poke(false.B) // Data write - dw.bits.pokePartial(WD.default(dw.bits)) - dw.valid.poke(false.B) + wd.bits.pokePartial(WD.default(wd.bits)) + wd.valid.poke(false.B) // Write response wr.ready.poke(false.B) // Address read - ar.bits.pokePartial(RA.default(ar.bits)) - ar.valid.poke(false.B) + ra.bits.pokePartial(RA.default(ra.bits)) + ra.valid.poke(false.B) // Data read - dr.ready.poke(false.B) + rd.ready.poke(false.B) // Reset slave device controller resetn.poke(false.B) @@ -101,23 +102,11 @@ class FunctionalMaster[T <: Slave](dut: T) { val head = awaitingWAddr.head /** Write address to slave */ - aw.valid.poke(true.B) - if (aw.bits.idW > 0) aw.bits.id.poke(head.id.U) - aw.bits.addr.poke(head.addr.U) - aw.bits.len.poke(head.len.U) - aw.bits.size.poke(head.size.U) - aw.bits.burst.poke(head.burst) - aw.bits.lock.poke(head.lock) - aw.bits.cache.poke(head.cache) - aw.bits.prot.poke(head.prot) - aw.bits.qos.poke(head.qos) - aw.bits.region.poke(head.region) - if (aw.bits.userW > 0) aw.bits.user.poke(head.user) - while (!aw.ready.peek.litToBoolean) { - clk.step() - } + wa.valid.poke(true.B) + wa.bits.pokePartial(head.ctrl) + while (!wa.ready.peek.litToBoolean) clk.step() clk.step() - aw.valid.poke(false.B) + wa.valid.poke(false.B) /** Update transaction and queue */ awaitingWAddr = awaitingWAddr.tail @@ -137,25 +126,18 @@ class FunctionalMaster[T <: Slave](dut: T) { while (!awaitingWrite.isEmpty) { /** Get the current transaction */ val head = awaitingWrite.head - while (!head.addrSent) { - clk.step() - } + while (!head.addrSent) clk.step() /** Write data to slave */ - dw.valid.poke(true.B) + wd.valid.poke(true.B) while (!head.complete) { - val (data, strb, last, user) = 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) - if (dw.bits.userW > 0) dw.bits.user.poke(user) - while (!dw.ready.peek.litToBoolean) { - clk.step() - } + val nextVal = head.next + wd.bits.pokePartial(nextVal) + println("Write " + nextVal.data.litValue + " with strobe " + nextVal.strb.toString + " and last " + nextVal.last.litToBoolean) + while (!wd.ready.peek.litToBoolean) clk.step() clk.step() } - dw.valid.poke(false.B) + wd.valid.poke(false.B) /** Update transaction and queue */ awaitingWrite = awaitingWrite.tail @@ -175,15 +157,11 @@ class FunctionalMaster[T <: Slave](dut: T) { while (!awaitingResp.isEmpty) { /** Get the current transaction */ val head = awaitingResp.head - while (!head.dataSent) { - clk.step() - } + while (!head.dataSent) clk.step() /** Indicate that interface is ready and wait for response */ wr.ready.poke(true.B) - while (!wr.valid.peek.litToBoolean) { - clk.step() - } + while (!wr.valid.peek.litToBoolean) clk.step() responses = responses :+ (new Response(wr.bits.resp.peek, if (wr.bits.idW > 0) wr.bits.id.peek.litValue else 0)) wr.ready.poke(false.B) @@ -206,23 +184,11 @@ class FunctionalMaster[T <: Slave](dut: T) { val head = awaitingRAddr.head /** Write address to slave */ - ar.valid.poke(true.B) - if (ar.bits.idW > 0) ar.bits.id.poke(head.id.U) - ar.bits.addr.poke(head.addr.U) - ar.bits.len.poke(head.len.U) - ar.bits.size.poke(head.size.U) - ar.bits.burst.poke(head.burst) - ar.bits.lock.poke(head.lock) - ar.bits.cache.poke(head.cache) - ar.bits.prot.poke(head.prot) - ar.bits.qos.poke(head.qos) - ar.bits.region.poke(head.region) - if (ar.bits.userW > 0) ar.bits.user.poke(head.user) - while (!ar.ready.peek.litToBoolean) { - clk.step() - } + ra.valid.poke(true.B) + ra.bits.pokePartial(head.ctrl) + while (!ra.ready.peek.litToBoolean) clk.step() clk.step() - ar.valid.poke(false.B) + ra.valid.poke(false.B) /** Update transaction and queue */ awaitingRAddr = awaitingRAddr.tail @@ -242,22 +208,20 @@ class FunctionalMaster[T <: Slave](dut: T) { while (!awaitingRead.isEmpty) { /** Get the current transaction */ val head = awaitingRead.head - while (!head.addrSent) { - clk.step() - } + while (!head.addrSent) clk.step() /** Read data from slave */ - dr.ready.poke(true.B) + rd.ready.poke(true.B) while (!head.complete) { - if (dr.valid.peek.litToBoolean) { - val (data, resp, last) = (dr.bits.data.peek, dr.bits.resp.peek, dr.bits.last.peek) + if (rd.valid.peek.litToBoolean) { + val (data, resp, last) = (rd.bits.data.peek, rd.bits.resp.peek, rd.bits.last.peek) println(s"Read " + data.litValue + " with response " + resp.litValue + " and last " + last.litToBoolean) head.add(data.litValue) } clk.step() } readValues = readValues :+ head.data - dr.ready.poke(false.B) + rd.ready.poke(false.B) /** Update queue */ awaitingRead = awaitingRead.tail @@ -294,6 +258,7 @@ class FunctionalMaster[T <: Slave](dut: T) { * @param prot optional protection type, defaults to non-secure unprivileged data access * @param qos optional QoS, defaults to 0 * @param region optional region, defaults to 0 + * @param user optional user, defaults to 0 * * @note [[addr]] must fit within the slave DUT's write address width * @note entries in [[data]] must fit within the slave DUT's write data width, and the list can have at most [[len]] entries @@ -311,7 +276,8 @@ class FunctionalMaster[T <: Slave](dut: T) { cache: UInt = MemoryEncodings.DeviceNonbuf, prot: UInt = ProtectionEncodings.DataNsecUpriv, qos: UInt = 0.U, - region: UInt = 0.U) = { + region: UInt = 0.U, + user: UInt = 0.U) = { require(log2Up(addr) <= addrW, s"address must fit within DUT's write address width (got $addr)") require(log2Up(id) <= idW, s"ID must fit within DUT's ID width (got $id)") @@ -343,11 +309,15 @@ class FunctionalMaster[T <: Slave](dut: T) { val tdata = if (data != Nil) { require(data.length == burstLen, "given data length should match burst length") data - } else - Seq.fill(burstLen) { BigInt(numBytes, rng) } + } else Seq.fill(burstLen) { BigInt(numBytes, rng) } /** Create and queue new write transaction */ - val trx = new WriteTransaction(addr, data, dataW, id, len, size, burst, lock, cache, prot, qos, region) + var lits = Seq((x: WA) => x.addr -> addr.U, (x: WA) => x.len -> len.U, (x: WA) => x.size -> size.U, + (x: WA) => x.burst -> burst, (x: WA) => x.lock -> lock, (x: WA) => x.cache -> cache, + (x: WA) => x.prot -> prot, (x: WA) => x.qos -> qos, (x: WA) => x.region -> region) + if (wa.bits.idW > 0) lits = lits :+ ((x: WA) => x.id -> id.U) + if (wa.bits.userW > 0) lits = lits :+ ((x: WA) => x.user -> user) + val trx = new WriteTransaction((new WA(wa.bits.addrW, wa.bits.idW, wa.bits.userW)).Lit(lits :_*), wd.bits, data) awaitingWAddr = awaitingWAddr :+ trx awaitingWrite = awaitingWrite :+ trx awaitingResp = awaitingResp :+ trx @@ -370,6 +340,7 @@ class FunctionalMaster[T <: Slave](dut: T) { * @param prot optional protection type, defaults to non-secure unprivileged data access * @param qos optional QoS, defaults to 0 * @param region optional region, defaults to 0 + * @param user optional user, defaults to 0 * * @note [[addr]] must fit within the slave DUT's write address width * @note [[id]] must fit within DUT's ID width, likewise [[size]] cannot be greater than the DUT's write data width @@ -385,7 +356,8 @@ class FunctionalMaster[T <: Slave](dut: T) { cache: UInt = MemoryEncodings.DeviceNonbuf, prot: UInt = ProtectionEncodings.DataNsecUpriv, qos: UInt = 0.U, - region: UInt = 0.U) = { + region: UInt = 0.U, + user: UInt = 0.U) = { require(log2Up(addr) <= addrW, s"address must fit within DUT's write address width (got $addr)") require(log2Up(id) <= idW, s"ID must fit within DUT's ID width (got $id)") @@ -414,7 +386,12 @@ class FunctionalMaster[T <: Slave](dut: T) { } /** Create and queue new read transaction */ - val trx = new ReadTransaction(addr, id, len, size, burst, lock, cache, prot, qos, region) + var lits = Seq((x: RA) => x.addr -> addr.U, (x: RA) => x.len -> len.U, (x: RA) => x.size -> size.U, + (x: RA) => x.burst -> burst, (x: RA) => x.lock -> lock, (x: RA) => x.cache -> cache, + (x: RA) => x.prot -> prot, (x: RA) => x.qos -> qos, (x: RA) => x.region -> region) + if (ra.bits.idW > 0) lits = lits :+ ((x: RA) => x.id -> id.U) + if (ra.bits.userW > 0) lits = lits :+ ((x: RA) => x.user -> user) + val trx = new ReadTransaction((new RA(ra.bits.addrW, ra.bits.idW, ra.bits.userW)).Lit(lits :_*)) awaitingRAddr = awaitingRAddr :+ trx awaitingRead = awaitingRead :+ trx diff --git a/axi4/src/main/scala/axi4/Interfaces.scala b/axi4/src/main/scala/axi4/Interfaces.scala index 950c83b..3e4f808 100644 --- a/axi4/src/main/scala/axi4/Interfaces.scala +++ b/axi4/src/main/scala/axi4/Interfaces.scala @@ -21,17 +21,17 @@ import chisel3.util.Decoupled class MasterInterface(val addrW: Int, val dataW: Int, val idW: Int = 0, val userW: Int = 0) extends Bundle { /** Fields implementing each of the AXI channels * - * [[aw]] is the write address channel - * [[dw]] is the write data channel + * [[wa]] is the write address channel + * [[wd]] is the write data channel * [[wr]] is the write response channel - * [[ar]] is the read address channel - * [[dr]] is the read data channel + * [[ra]] is the read address channel + * [[rd]] is the read data channel */ - val aw = Decoupled(Output(WA(addrW, idW, userW))) //Decoupled(new WA(addrW, idW, userW)) - val dw = Decoupled(Output(WD(dataW, userW))) //Decoupled(new WD(dataW, userW)) + val wa = Decoupled(Output(WA(addrW, idW, userW))) //Decoupled(new WA(addrW, idW, userW)) + val wd = Decoupled(Output(WD(dataW, userW))) //Decoupled(new WD(dataW, userW)) val wr = Flipped(Decoupled(Output(WR(idW, userW)))) //Flipped(Decoupled(Flipped(new WR(idW, userW)))) - val ar = Decoupled(RA(addrW, idW, userW)) //Decoupled(new RA(addrW, idW, userW)) - val dr = Flipped(Decoupled(Output(RD(dataW, idW, userW)))) //Flipped(Decoupled(Flipped(new RD(dataW, idW, userW)))) + val ra = Decoupled(RA(addrW, idW, userW)) //Decoupled(new RA(addrW, idW, userW)) + val rd = Flipped(Decoupled(Output(RD(dataW, idW, userW)))) //Flipped(Decoupled(Flipped(new RD(dataW, idW, userW)))) } /** AXI4 slave interface @@ -44,15 +44,15 @@ class MasterInterface(val addrW: Int, val dataW: Int, val idW: Int = 0, val user class SlaveInterface(val addrW: Int, val dataW: Int, val idW: Int = 0, val userW: Int = 0) extends Bundle { /** Fields implementing each of the AXI channels * - * [[aw]] is the write address channel - * [[dw]] is the write data channel + * [[wa]] is the write address channel + * [[wd]] is the write data channel * [[wr]] is the write response channel - * [[ar]] is the read address channel - * [[dr]] is the read data channel + * [[ra]] is the read address channel + * [[rd]] is the read data channel */ - val aw = Flipped(Decoupled(Output(WA(addrW, idW, userW)))) //Flipped(Decoupled(new WA(addrW, idW, userW))) - val dw = Flipped(Decoupled(Output(WD(dataW, userW)))) //Flipped(Decoupled(new WD(dataW, userW))) + val wa = Flipped(Decoupled(Output(WA(addrW, idW, userW)))) //Flipped(Decoupled(new WA(addrW, idW, userW))) + val wd = Flipped(Decoupled(Output(WD(dataW, userW)))) //Flipped(Decoupled(new WD(dataW, userW))) val wr = Decoupled(Output(WR(idW, userW))) //Flipped(Flipped(Decoupled(Flipped(new WR(idW, userW))))) - val ar = Flipped(Decoupled(Output(RA(addrW, idW, userW)))) //Flipped(Decoupled(new RA(addrW, idW, userW))) - val dr = Decoupled(Output(RD(dataW, idW, userW))) //Flipped(Flipped(Decoupled(Flipped(new RD(dataW, idW, userW))))) + val ra = Flipped(Decoupled(Output(RA(addrW, idW, userW)))) //Flipped(Decoupled(new RA(addrW, idW, userW))) + val rd = Decoupled(Output(RD(dataW, idW, userW))) //Flipped(Flipped(Decoupled(Flipped(new RD(dataW, idW, userW))))) } diff --git a/axi4/src/main/scala/axi4/Transaction.scala b/axi4/src/main/scala/axi4/Transaction.scala index dfb58a6..643ae43 100644 --- a/axi4/src/main/scala/axi4/Transaction.scala +++ b/axi4/src/main/scala/axi4/Transaction.scala @@ -9,6 +9,8 @@ package axi4 import chisel3._ +import chisel3.experimental.BundleLiterals._ +import chisel3.internal.requireIsHardware /** Transaction superclass */ trait Transaction { @@ -17,41 +19,22 @@ trait Transaction { /** Write transaction * - * @param addr start write address - * @param data list of data to write - * @param dataW slave's data bus width - * @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 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 - * @param qos optional QoS, defaults to 0 - * @param region optional region, defaults to 0 - * @param user optional user, defaults to 0 + * @param ctrl an initialized WA object + * @param dw a WD object representing the write data channel + * @param data a sequence of data to write */ class WriteTransaction( - val addr: BigInt, - val data: Seq[BigInt], - dataW: Int, - val id: BigInt = 0, - val len: Int = 0, - val size: Int = 0, - val burst: UInt = BurstEncodings.Fixed, - val lock: Bool = LockEncodings.NormalAccess, - val cache: UInt = MemoryEncodings.DeviceNonbuf, - val prot: UInt = ProtectionEncodings.DataNsecUpriv, - val qos: UInt = 0.U, - val region: UInt = 0.U, - val user: UInt = 0.U) extends Transaction { - private[this] val numBytes = 1 << size + val ctrl: WA, + val dw: WD, + val data: Seq[BigInt]) extends Transaction { + requireIsHardware(ctrl, "ctrl must be an initialized WA object") + private[this] val numBytes = 1 << ctrl.size.litValue.intValue private[this] val dtsize = numBytes * data.length - private[this] val lowerBoundary = (addr / dtsize) * dtsize + private[this] val lowerBoundary = (ctrl.addr.litValue / dtsize) * dtsize private[this] val upperBoundary = lowerBoundary + dtsize - private[this] val alignedAddress = ((addr / numBytes) * numBytes) - private[this] var aligned = addr == alignedAddress - private[this] var address = addr + private[this] val alignedAddress = ((ctrl.addr.litValue / numBytes) * numBytes) + private[this] var aligned = ctrl.addr.litValue == alignedAddress + private[this] var address = ctrl.addr.litValue private[this] var count = 0 private[this] var _addrSent = false @@ -73,17 +56,17 @@ class WriteTransaction( */ def next() = { /** Strobe calculation */ - val offset = (address / dataW) * dataW + val offset = (address / dw.dataW) * dw.dataW val lowerByteLane = address - offset val upperByteLane = if (aligned) lowerByteLane + numBytes-1 else alignedAddress + numBytes-1 - offset 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 + val strb = ("b"+(0 until (dw.dataW/8)).foldRight("") { (elem, acc) => if (within(elem)) acc + "1" else acc + "0" }).asUInt /** Update address */ - if (burst != BurstEncodings.Fixed) { + if (ctrl.burst != BurstEncodings.Fixed) { if (aligned) { address += numBytes - if (burst == BurstEncodings.Wrap) { + if (ctrl.burst == BurstEncodings.Wrap) { if (address >= upperBoundary) { address = lowerBoundary } @@ -96,37 +79,20 @@ class WriteTransaction( count += 1 /** Return data to write */ - (data(count-1).U, strb, complete.B, user) + var lits = Seq((x: WD) => x.data -> data(count-1).U, (x: WD) => x.strb -> strb, + (x: WD) => x.last -> complete.B) + if (dw.userW > 0) lits = lits :+ ((x: WD) => x.user -> ctrl.user) + (new WD(dw.dataW, dw.userW)).Lit(lits :_*) } def complete = data.length == count } /** Read transaction * - * @param addr start read address - * @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 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 - * @param qos optional QoS, defaults to 0 - * @param region optional region, defaults to 0 - * @param user optional user, defaults to 0 + * @param ctrl an initialized RA object */ -class ReadTransaction( - val addr: BigInt, - val id: BigInt = 0, - val len: Int = 0, - val size: Int = 0, - val burst: UInt = BurstEncodings.Fixed, - val lock: Bool = LockEncodings.NormalAccess, - val cache: UInt = MemoryEncodings.DeviceNonbuf, - val prot: UInt = ProtectionEncodings.DataNsecUpriv, - val qos: UInt = 0.U, - val region: UInt = 0.U, - val user: UInt = 0.U) extends Transaction { +class ReadTransaction(val ctrl: RA) extends Transaction { + requireIsHardware(ctrl, "ctrl must be an initialized RA object") var data = Seq[BigInt]() private[this] var _addrSent = false @@ -144,7 +110,7 @@ class ReadTransaction( def add(v: BigInt) = { data = data :+ v } - def complete = data.length == (len + 1) + def complete = data.length == (ctrl.len.litValue + 1) } /** Transaction response diff --git a/axi4/src/test/scala/VivadoAXIMemoryTester.scala b/axi4/src/test/scala/VivadoAXIMemoryTester.scala index 9a09d16..6ab9e90 100644 --- a/axi4/src/test/scala/VivadoAXIMemoryTester.scala +++ b/axi4/src/test/scala/VivadoAXIMemoryTester.scala @@ -30,36 +30,36 @@ class VivadoAXIMemoryTester extends FlatSpec with ChiselScalatestTester with Mat val master = new FunctionalMaster(dut) def printCheck() = { - println("AWREADY = " + dut.io.aw.ready.peek.litToBoolean) - println("WREADY = " + dut.io.dw.ready.peek.litToBoolean) + println("AWREADY = " + dut.io.wa.ready.peek.litToBoolean) + println("WREADY = " + dut.io.wd.ready.peek.litToBoolean) println("BVALID = " + dut.io.wr.valid.peek.litToBoolean) - println("ARREADY = " + dut.io.ar.ready.peek.litToBoolean) - println("RVALID = " + dut.io.dr.valid.peek.litToBoolean) + println("ARREADY = " + dut.io.ra.ready.peek.litToBoolean) + println("RVALID = " + dut.io.rd.valid.peek.litToBoolean) } // Set some initial values on the necessary signals - dut.io.dw.bits.data.poke(42.U) - dut.io.dw.bits.strb.poke("b1111".U) - dut.io.dw.bits.last.poke(true.B) + dut.io.wd.bits.data.poke(42.U) + dut.io.wd.bits.strb.poke("b1111".U) + dut.io.wd.bits.last.poke(true.B) printCheck() // Write address - dut.io.aw.valid.poke(true.B) + dut.io.wa.valid.poke(true.B) do { dut.clock.step() - } while (!dut.io.aw.ready.peek.litToBoolean) + } while (!dut.io.wa.ready.peek.litToBoolean) printCheck() dut.clock.step() - dut.io.aw.valid.poke(false.B) + dut.io.wa.valid.poke(false.B) // Write some data - dut.io.dw.valid.poke(true.B) + dut.io.wd.valid.poke(true.B) do { dut.clock.step() - } while (!dut.io.dw.ready.peek.litToBoolean) + } while (!dut.io.wd.ready.peek.litToBoolean) printCheck() dut.clock.step() - dut.io.dw.valid.poke(false.B) + dut.io.wd.valid.poke(false.B) // Fetch response dut.io.wr.ready.poke(true.B) @@ -71,21 +71,21 @@ class VivadoAXIMemoryTester extends FlatSpec with ChiselScalatestTester with Mat println(s"Got response $r") // Read address - dut.io.ar.valid.poke(true.B) + dut.io.ra.valid.poke(true.B) do { dut.clock.step() - } while (!dut.io.ar.ready.peek.litToBoolean) + } while (!dut.io.ra.ready.peek.litToBoolean) printCheck() dut.clock.step() - dut.io.ar.valid.poke(false.B) + dut.io.ra.valid.poke(false.B) // Read some data - dut.io.dr.ready.poke(true.B) - while (!dut.io.dr.valid.peek.litToBoolean) { + dut.io.rd.ready.poke(true.B) + while (!dut.io.rd.valid.peek.litToBoolean) { dut.clock.step() } printCheck() - dut.io.dr.bits.data.expect(42.U) + dut.io.rd.bits.data.expect(42.U) } }