From 048d063cae4a140e14705e7976713b818fbb453e Mon Sep 17 00:00:00 2001 From: qinjun-li Date: Fri, 19 Jul 2024 13:03:00 +0800 Subject: [PATCH] [ipemu] pipe request in WriteManager --- ipemu/src/AXI4SlaveAgent.scala | 66 +++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 29 deletions(-) diff --git a/ipemu/src/AXI4SlaveAgent.scala b/ipemu/src/AXI4SlaveAgent.scala index 9a993f0deb..93714bf030 100644 --- a/ipemu/src/AXI4SlaveAgent.scala +++ b/ipemu/src/AXI4SlaveAgent.scala @@ -51,12 +51,10 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) private class WriteManager( channel: AWChannel with AWFlowControl with WChannel with WFlowControl with BChannel with BFlowControl) { withClockAndReset(io.clock, io.reset) { - /** indicate AW is issued. */ - val awIssued = RegInit(0.U.asTypeOf(Bool())) - /** indicate W is finished, used to wake up B channel. */ - val last = RegInit(0.U.asTypeOf(Bool())) - /** indicate there is an ongoing write transaction. */ - val busy = RegInit(0.U.asTypeOf(Bool())) + /** There is an aw in the register. */ + val awIssued = RegInit(false.B) + /** There is a w in the register. */ + val last = RegInit(false.B) /** memory to store the write payload * @todo limit the payload size based on the RTL configuration. @@ -73,15 +71,19 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) val awprot = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWPROT))) val awqos = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWQOS))) val awregion = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWREGION))) + val awuser = RegInit(0.U.asTypeOf(chiselTypeOf(channel.AWUSER))) /** index the payload, used to write [[writePayload]] */ val writeIdx = RegInit(0.U.asTypeOf(UInt(8.W))) + val bFire = channel.BREADY && channel.BVALID + val awFire = channel.AWREADY && channel.AWVALID + val wLastFire = channel.WVALID && channel.WREADY && channel.WLAST + val awExist = channel.AWVALID || awIssued + val wExist = channel.WVALID && channel.WLAST || last // AW - channel.AWREADY := !busy || (busy && !awIssued) + channel.AWREADY := !awIssued || (wExist && channel.BREADY) when(channel.AWREADY && channel.AWVALID) { - awIssued := true.B - busy := true.B awid := channel.AWID awaddr := channel.AWADDR awlen := channel.AWLEN @@ -92,46 +94,52 @@ class AXI4SlaveAgent(parameter: AXI4SlaveAgentParameter) awprot := channel.AWPROT awqos := channel.AWQOS awregion := channel.AWREGION + awuser := channel.AWUSER + } + when(awFire ^ bFire) { + awIssued := awFire } // W - channel.WREADY := !busy || (busy && !last) + val writePayloadUpdate = WireDefault(writePayload) + channel.WREADY := !last || (awExist && channel.BREADY) when(channel.WVALID && channel.WREADY) { - busy := true.B writePayload.data(writeIdx) := channel.WDATA + writePayloadUpdate.data(writeIdx) := channel.WDATA writePayload.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) + writePayloadUpdate.strb(writeIdx) := channel.WSTRB.pad(writePayload.strb.getWidth) writeIdx := writeIdx + 1.U when(channel.WLAST) { - last := true.B + writeIdx := 0.U } } + when(wLastFire ^ bFire) { + last := wLastFire + } // B - channel.BVALID := last && awIssued - channel.BID := awid + channel.BVALID := awExist && wExist + channel.BID := Mux(awFire, channel.AWID, awid) channel.BRESP := 0.U(2.W) // OK - channel.BUSER := DontCare + channel.BUSER := Mux(awFire, channel.AWUSER, awuser) when(channel.BVALID && channel.BREADY) { RawClockedVoidFunctionCall(s"axi_write_${parameter.name}")( io.clock, when.cond && !io.gateWrite, io.channelId, // handle AW and W at same beat. - Mux(channel.AWREADY && channel.AWVALID, channel.AWID, awid.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWADDR, awaddr.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWLEN, awlen.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWSIZE, awsize.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWBURST, awburst.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWLOCK, awlock.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWCACHE, awcache.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWPROT, awprot.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWQOS, awqos.asTypeOf(UInt(64.W))), - Mux(channel.AWREADY && channel.AWVALID, channel.AWREGION, awregion.asTypeOf(UInt(64.W))), - WireDefault(writePayload) + Mux(awFire, channel.AWID, awid.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWADDR, awaddr.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWLEN, awlen.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWSIZE, awsize.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWBURST, awburst.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWLOCK, awlock.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWCACHE, awcache.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWPROT, awprot.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWQOS, awqos.asTypeOf(UInt(64.W))), + Mux(awFire, channel.AWREGION, awregion.asTypeOf(UInt(64.W))), + writePayloadUpdate ) - awIssued := false.B - last := false.B - writeIdx := 0.U } } }