From 2d6c0fb3ea8ae8df7c182eada6bc26439b01d7e5 Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Fri, 11 Oct 2024 16:46:11 +0200 Subject: [PATCH 1/6] Introduce combined modules --- src/AXI3.bsv | 176 ++++++++++++++++++ src/AXI3_Master.bsv | 63 ++----- src/AXI3_Slave.bsv | 21 +++ src/AXI4.bsv | 195 ++++++++++++++++++++ src/AXI4_Lite.bsv | 142 +++++++++++++++ src/AXI4_Lite_Master.bsv | 62 ++----- src/AXI4_Lite_Slave.bsv | 18 ++ src/AXI4_Master.bsv | 75 +------- src/AXI4_Slave.bsv | 20 +++ src/BlueAXI.bsv | 16 +- src/ClientServerS.bs | 369 ++++++++++++++++++++++++++++++++++++++ src/GenericAxi4Master.bsv | 3 +- 12 files changed, 978 insertions(+), 182 deletions(-) create mode 100644 src/AXI3.bsv create mode 100644 src/AXI4.bsv create mode 100644 src/AXI4_Lite.bsv create mode 100644 src/ClientServerS.bs diff --git a/src/AXI3.bsv b/src/AXI3.bsv new file mode 100644 index 0000000..54940af --- /dev/null +++ b/src/AXI3.bsv @@ -0,0 +1,176 @@ +package AXI3; + +import GetPut :: *; +import ClientServerS :: *; +import Connectable :: *; + +import AXI3_Types :: *; +import AXI3_Slave :: *; +import AXI3_Master :: *; + +export AXI3_Types :: *; +export AXI3_Slave :: *; +export AXI3_Master :: *; +export AXI3 :: *; + +/* +======================== + AXI 3 Master Combined +======================== +*/ + +interface AXI3_Master_Fab#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + (* prefix="" *) + interface AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width) rd; + (* prefix="" *) + interface AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) wr; +endinterface + +typedef ServerS#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width); +interface AXI3_Write_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + interface Put#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; + interface Put#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; + interface GetS#(AXI3_Write_Rs#(id_width)) response; +endinterface + +interface AXI3_Master#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + interface AXI3_Master_Fab#(addrwidth, datawidth, id_width) fab; + interface AXI3_Read_Server#(addrwidth, datawidth, id_width) read; + interface AXI3_Write_Server#(addrwidth, datawidth, id_width) write; +endinterface + + +module mkAXI3_Master#(Integer bufferInRead, Integer bufferOutRead, Bool bramRead, Integer bufferInAddrWrite, Integer bufferInDataWrite, Integer bufferOutWrite, Bool bramWrite)(AXI3_Master#(addrwidth, datawidth, id_width)); + AXI3_Master_Rd#(addrwidth, datawidth, id_width) rd_master <- mkAXI3_Master_Rd(bufferInRead, bufferOutRead, bramRead); + AXI3_Master_Wr#(addrwidth, datawidth, id_width) wr_master <- mkAXI3_Master_Wr(bufferInAddrWrite, bufferInDataWrite, bufferOutWrite, bramWrite); + + interface AXI3_Master_Fab fab; + interface rd = rd_master.fab; + interface wr = wr_master.fab; + endinterface + interface read = toGPServerS(rd_master.request, rd_master.response); + interface AXI3_Write_Server write; + interface request_addr = wr_master.request_addr; + interface request_data = wr_master.request_data; + interface GetS response; + method first = wr_master.snoop; + method Action deq(); + let r <- wr_master.response.get; + endmethod + endinterface + endinterface +endmodule + +/* +======================== + AXI 3 Slave Combined +======================== +*/ + +interface AXI3_Slave_Fab#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + (* prefix="" *) + interface AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) rd; + (* prefix="" *) + interface AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) wr; +endinterface + + +typedef ClientS#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width); +interface AXI3_Write_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + interface GetS#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; + interface GetS#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; + interface Put#(AXI3_Write_Rs#(id_width)) response; +endinterface + +interface AXI3_Slave#(numeric type addrwidth, numeric type datawidth, numeric type id_width); + interface AXI3_Slave_Fab#(addrwidth, datawidth, id_width) fab; + interface AXI3_Read_Client#(addrwidth, datawidth, id_width) read; + interface AXI3_Write_Client#(addrwidth, datawidth, id_width) write; +endinterface + + +module mkAXI3_Slave#(Integer bufferInRead, Integer bufferOutRead, Integer bufferSizeAddrWrite, Integer bufferSizeDataWrite, Integer bufferSizeOutWrite)(AXI3_Slave#(addrwidth, datawidth, id_width)); + AXI3_Slave_Rd#(addrwidth, datawidth, id_width) rd_slave <- mkAXI3_Slave_Rd(bufferInRead, bufferOutRead); + AXI3_Slave_Wr#(addrwidth, datawidth, id_width) wr_slave <- mkAXI3_Slave_Wr(bufferSizeAddrWrite, bufferSizeDataWrite, bufferSizeOutWrite); + + interface AXI3_Slave_Fab fab; + interface rd = rd_slave.fab; + interface wr = wr_slave.fab; + endinterface + interface read = toGPClientS(rd_slave.request, rd_slave.response); + interface AXI3_Write_Client write; + interface GetS request_addr; + method first = wr_slave.snoop_addr; + method Action deq(); + let r <- wr_slave.request_addr.get; + endmethod + endinterface + interface GetS request_data; + method first = wr_slave.snoop_data; + method Action deq(); + let r <- wr_slave.request_data.get; + endmethod + endinterface + interface response = wr_slave.response; + endinterface +endmodule + +/* +======================== + Connectable +======================== +*/ +instance Connectable#(AXI3_Master_Fab#(addrwidth, datawidth, id_width), AXI3_Slave_Fab#(addrwidth, datawidth, id_width)); + module mkConnection#(AXI3_Master_Fab#(addrwidth, datawidth, id_width) master, AXI3_Slave_Fab#(addrwidth, datawidth, id_width) slave)(Empty); + mkConnection(master.rd, slave.rd); + mkConnection(master.wr, slave.wr); + endmodule +endinstance + +instance Connectable#(AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width), AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width)); + module mkConnection#(AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width) master, AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) slave)(Empty); + rule forward1; master.parready(slave.arready); endrule + rule forward2; slave.parvalid(master.arvalid); endrule + rule forward3; + slave.parchannel(master.arid, master.araddr, master.arlen, master.arsize, master.arburst, + master.arlock, master.arcache, master.arprot); + endrule + + rule forward4; master.prvalid(slave.rvalid); endrule + rule forward5; slave.prready(master.rready); endrule + + rule forward6; + master.prchannel(slave.rid, slave.rdata, slave.rresp, slave.rlast); + endrule + endmodule +endinstance + +instance Connectable#(AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width), AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width)); + module mkConnection#(AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) slave, AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + +instance Connectable#(AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width), AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width)); + module mkConnection#(AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) master, AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) slave)(Empty); + rule forward1; master.pawready(slave.awready); endrule + rule forward2; slave.pawvalid(master.awvalid); endrule + rule forward3; slave.pawchannel(master.awid, master.awaddr, master.awlen, master.awsize, master.awburst, master.awlock, master.awcache, master.awprot); endrule + + rule forward4; master.pwready(slave.wready); endrule + rule forward5; slave.pwvalid(master.wvalid); endrule + rule forward6; slave.pwchannel(master.wid, master.wdata, master.wstrb, master.wlast); endrule + + rule forward7; master.pbvalid(slave.bvalid); endrule + rule forward8; slave.pbready(master.bready); endrule + rule forward9; master.bin(slave.bresp, slave.bid); endrule + endmodule +endinstance + +instance Connectable#(AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width), AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width)); + module mkConnection#(AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) slave, AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + +endpackage \ No newline at end of file diff --git a/src/AXI3_Master.bsv b/src/AXI3_Master.bsv index 6e12127..e3ba8de 100644 --- a/src/AXI3_Master.bsv +++ b/src/AXI3_Master.bsv @@ -15,7 +15,7 @@ import AXI3_Slave :: *; /* ======================== - AXI 4 Master Read + AXI 3 Master Read ======================== */ @@ -136,7 +136,7 @@ endmodule /* ======================== - AXI 4 Lite Master Write + AXI 3 Master Write ======================== */ (* always_ready, always_enabled *) @@ -317,56 +317,7 @@ endinterface // //interface s_rd = slave_rd.fab; //endmodule // -/* -======================== - Connectable -======================== -*/ -instance Connectable#(AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width), AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width)); - module mkConnection#(AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width) master, AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) slave)(Empty); - rule forward1; master.parready(slave.arready); endrule - rule forward2; slave.parvalid(master.arvalid); endrule - rule forward3; - slave.parchannel(master.arid, master.araddr, master.arlen, master.arsize, master.arburst, - master.arlock, master.arcache, master.arprot); - endrule - - rule forward4; master.prvalid(slave.rvalid); endrule - rule forward5; slave.prready(master.rready); endrule - - rule forward6; - master.prchannel(slave.rid, slave.rdata, slave.rresp, slave.rlast); - endrule - endmodule -endinstance - -instance Connectable#(AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width), AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width)); - module mkConnection#(AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) slave, AXI3_Master_Rd_Fab#(addrwidth, datawidth, id_width) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance - -instance Connectable#(AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width), AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width)); - module mkConnection#(AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) master, AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) slave)(Empty); - rule forward1; master.pawready(slave.awready); endrule - rule forward2; slave.pawvalid(master.awvalid); endrule - rule forward3; slave.pawchannel(master.awid, master.awaddr, master.awlen, master.awsize, master.awburst, master.awlock, master.awcache, master.awprot); endrule - - rule forward4; master.pwready(slave.wready); endrule - rule forward5; slave.pwvalid(master.wvalid); endrule - rule forward6; slave.pwchannel(master.wid, master.wdata, master.wstrb, master.wlast); endrule - - rule forward7; master.pbvalid(slave.bvalid); endrule - rule forward8; slave.pbready(master.bready); endrule - rule forward9; master.bin(slave.bresp, slave.bid); endrule - endmodule -endinstance - -instance Connectable#(AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width), AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width)); - module mkConnection#(AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) slave, AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance + module mkAXI3_Master_Rd_Dummy(AXI3_Master_Rd#(addrwidth, datawidth, id_width)); interface AXI3_Master_Rd_Fab fab; @@ -393,6 +344,9 @@ module mkAXI3_Master_Rd_Dummy(AXI3_Master_Rd#(addrwidth, datawidth, id_width)); method Action parready(Bool a); endmethod endinterface + interface snoop = ?; + interface response = ?; + interface request = ?; endmodule module mkAXI3_Master_Wr_Dummy(AXI3_Master_Wr#(addrwidth, datawidth, id_width)); @@ -422,7 +376,12 @@ module mkAXI3_Master_Wr_Dummy(AXI3_Master_Wr#(addrwidth, datawidth, id_width)); endmethod method Action bin(AXI3_Response r, Bit#(id_width) bid); endmethod + interface wid = ?; endinterface + interface snoop = ?; + interface response = ?; + interface request_data = ?; + interface request_addr = ?; endmodule // Helper functions to simplify usage of the above modules diff --git a/src/AXI3_Slave.bsv b/src/AXI3_Slave.bsv index b12ae0d..f1deb75 100644 --- a/src/AXI3_Slave.bsv +++ b/src/AXI3_Slave.bsv @@ -130,7 +130,13 @@ module mkAXI3_Slave_Rd_Dummy(AXI3_Slave_Rd#(addrwidth, datawidth, id_width)); interface rdata = unpack(0); interface rresp = unpack(0); interface rlast = unpack(0); + + interface prready = ?; + interface parchannel = ?; + interface parvalid = ?; endinterface + interface response = ?; + interface request = ?; endmodule /* @@ -171,7 +177,9 @@ interface AXI3_Slave_Wr#(numeric type addrwidth, numeric type datawidth, numeric interface AXI3_Slave_Wr_Fab#(addrwidth, datawidth, id_width) fab; interface Get#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; + method AXI3_Write_Rq_Addr#(addrwidth, id_width) snoop_addr(); interface Get#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; + method AXI3_Write_Rq_Data#(datawidth, id_width) snoop_data(); interface Put#(AXI3_Write_Rs#(id_width)) response; endinterface @@ -259,6 +267,9 @@ module mkAXI3_Slave_Wr#(Integer bufferSizeAddr, Integer bufferSizeData, Integer wbresp <= out.first().resp(); endrule + method snoop_addr = in_addr.first; + method snoop_data = in_data.first; + interface Get request_addr = toGet(in_addr); interface Get request_data = toGet(in_data); interface Put response = toPut(out); @@ -288,7 +299,17 @@ module mkAXI3_Slave_Wr_Dummy(AXI3_Slave_Wr#(addrwidth, datawidth, id_width)); interface bvalid = False; interface bresp = unpack(0); interface bid = unpack(0); + interface pawvalid = ?; + interface pawchannel = ?; + interface pwvalid = ?; + interface pwchannel = ?; + interface pbready = ?; endinterface + interface response = ?; + interface request_addr = ?; + interface snoop_addr = ?; + interface request_data = ?; + interface snoop_data = ?; endmodule endpackage diff --git a/src/AXI4.bsv b/src/AXI4.bsv new file mode 100644 index 0000000..fec57c2 --- /dev/null +++ b/src/AXI4.bsv @@ -0,0 +1,195 @@ +package AXI4; + +import AXI4_Master :: *; +import AXI4_Slave :: *; +import AXI4_Types :: *; + +export AXI4_Master :: *; +export AXI4_Slave :: *; +export AXI4_Types :: *; +export AXI4 :: *; + +import GetPut :: *; +import ClientServerS :: *; +import Connectable :: *; + +/* +======================== + AXI 3 Master Combined +======================== +*/ + +interface AXI4_Master_Fab#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + (* prefix="" *) + interface AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width) rd; + (* prefix="" *) + interface AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) wr; +endinterface + +typedef ServerS#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width ,user_width)) AXI4_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); +interface AXI4_Write_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + interface Put#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; + interface Put#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; + interface GetS#(AXI4_Write_Rs#(id_width, user_width)) response; +endinterface + +interface AXI4_Master#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + interface AXI4_Master_Fab#(addrwidth, datawidth, id_width, user_width) fab; + interface AXI4_Read_Server#(addrwidth, datawidth, id_width, user_width) read; + interface AXI4_Write_Server#(addrwidth, datawidth, id_width, user_width) write; +endinterface + + +module mkAXI4_Master#(Integer bufferInRead, Integer bufferOutRead, Bool bramRead, Integer bufferInAddrWrite, Integer bufferInDataWrite, Integer bufferOutWrite, Bool bramWrite)(AXI4_Master#(addrwidth, datawidth, id_width, user_width)); + AXI4_Master_Rd#(addrwidth, datawidth, id_width, user_width) rd_master <- mkAXI4_Master_Rd(bufferInRead, bufferOutRead, bramRead); + AXI4_Master_Wr#(addrwidth, datawidth, id_width, user_width) wr_master <- mkAXI4_Master_Wr(bufferInAddrWrite, bufferInDataWrite, bufferOutWrite, bramWrite); + + interface AXI4_Master_Fab fab; + interface rd = rd_master.fab; + interface wr = wr_master.fab; + endinterface + interface read = toGPServerS(rd_master.request, rd_master.response); + interface AXI4_Write_Server write; + interface request_addr = wr_master.request_addr; + interface request_data = wr_master.request_data; + interface GetS response; + method first = wr_master.snoop; + method Action deq(); + let r <- wr_master.response.get; + endmethod + endinterface + endinterface +endmodule + +/* +======================== + AXI 3 Slave Combined +======================== +*/ + +interface AXI4_Slave_Fab#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + (* prefix="" *) + interface AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) rd; + (* prefix="" *) + interface AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) wr; +endinterface + + +typedef ClientS#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width, user_width)) AXI4_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); +interface AXI4_Write_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + interface GetS#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; + interface GetS#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; + interface Put#(AXI4_Write_Rs#(id_width, user_width)) response; +endinterface + +interface AXI4_Slave#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); + interface AXI4_Slave_Fab#(addrwidth, datawidth, id_width, user_width) fab; + interface AXI4_Read_Client#(addrwidth, datawidth, id_width, user_width) read; + interface AXI4_Write_Client#(addrwidth, datawidth, id_width, user_width) write; +endinterface + + +module mkAXI4_Slave#(Integer bufferInRead, Integer bufferOutRead, Integer bufferSizeAddrWrite, Integer bufferSizeDataWrite, Integer bufferSizeOutWrite)(AXI4_Slave#(addrwidth, datawidth, id_width, user_width)); + AXI4_Slave_Rd#(addrwidth, datawidth, id_width, user_width) rd_slave <- mkAXI4_Slave_Rd(bufferInRead, bufferOutRead); + AXI4_Slave_Wr#(addrwidth, datawidth, id_width, user_width) wr_slave <- mkAXI4_Slave_Wr(bufferSizeAddrWrite, bufferSizeDataWrite, bufferSizeOutWrite); + + interface AXI4_Slave_Fab fab; + interface rd = rd_slave.fab; + interface wr = wr_slave.fab; + endinterface + interface read = toGPClientS(rd_slave.request, rd_slave.response); + interface AXI4_Write_Client write; + interface GetS request_addr; + method first = wr_slave.snoop_addr; + method Action deq(); + let r <- wr_slave.request_addr.get; + endmethod + endinterface + interface GetS request_data; + method first = wr_slave.snoop_data; + method Action deq(); + let r <- wr_slave.request_data.get; + endmethod + endinterface + interface response = wr_slave.response; + endinterface +endmodule + +/* +======================== + Connectable +======================== +*/ + +instance Connectable#(AXI4_Master_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Slave_Fab#(addrwidth, datawidth, id_width, user_width)); + module mkConnection#(AXI4_Master_Fab#(addrwidth, datawidth, id_width, user_width) master, AXI4_Slave_Fab#(addrwidth, datawidth, id_width, user_width) slave)(Empty); + mkConnection(master.rd, slave.rd); + mkConnection(master.wr, slave.wr); + endmodule +endinstance + +instance Connectable#(AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width)); + module mkConnection#(AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width) master, AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) slave)(Empty); + rule forward1; master.parready(slave.arready); endrule + rule forward2; slave.parvalid(master.arvalid); endrule + rule forward3; + slave.parchannel(master.arid, master.araddr, master.arlen, master.arsize, master.arburst, + master.arlock, master.arcache, master.arprot, master.arqos, master.arregion, master.aruser); + endrule + + rule forward4; master.prvalid(slave.rvalid); endrule + rule forward5; slave.prready(master.rready); endrule + + rule forward6; + master.prchannel(slave.rid, slave.rdata, slave.rresp, slave.rlast, slave.ruser); + endrule + endmodule +endinstance + +instance Connectable#(AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width)); + module mkConnection#(AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) slave, AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + +instance Connectable#(AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width)); + module mkConnection#(AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) master, AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) slave)(Empty); + rule forward1; master.pawready(slave.awready); endrule + rule forward2; slave.pawvalid(master.awvalid); endrule + rule forward3; slave.pawchannel(master.awid, master.awaddr, master.awlen, master.awsize, master.awburst, master.awlock, master.awcache, master.awprot, master.awqos, master.awregion, master.awuser); endrule + + rule forward4; master.pwready(slave.wready); endrule + rule forward5; slave.pwvalid(master.wvalid); endrule + rule forward6; slave.pwchannel(master.wdata, master.wstrb, master.wlast, master.wuser); endrule + + rule forward7; master.pbvalid(slave.bvalid); endrule + rule forward8; slave.pbready(master.bready); endrule + rule forward9; master.bin(slave.bresp, slave.bid, slave.buser); endrule + endmodule +endinstance + +instance Connectable#(AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width)); + module mkConnection#(AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) slave, AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + + +module mkTestIfc(TestIfc); + AXI4_Master_Wr#(32, 32, 1, 1) master_wr <- mkAXI4_Master_Wr(2, 2, 2, True); + AXI4_Master_Rd#(32, 32, 1, 1) master_rd <- mkAXI4_Master_Rd(2, 2, True); + + AXI4_Slave_Wr#(32, 32, 1, 1) slave_wr <- mkAXI4_Slave_Wr(2, 2, 2); + AXI4_Slave_Rd#(32, 32, 1, 1) slave_rd <- mkAXI4_Slave_Rd(2, 2); + + mkConnection(master_rd.fab, slave_rd.fab); + mkConnection(master_wr.fab, slave_wr.fab); + + //interface m_wr = master_wr.fab; + //interface m_rd = master_rd.fab; + + //interface s_wr = slave_wr.fab; + //interface s_rd = slave_rd.fab; +endmodule + +endpackage \ No newline at end of file diff --git a/src/AXI4_Lite.bsv b/src/AXI4_Lite.bsv new file mode 100644 index 0000000..9e2cc5d --- /dev/null +++ b/src/AXI4_Lite.bsv @@ -0,0 +1,142 @@ +package AXI4_Lite; + +import AXI4_Lite_Master :: *; +import AXI4_Lite_Slave :: *; +import AXI4_Lite_Types :: *; +import ClientServer :: *; +import ClientServerS :: *; +import GetPut :: *; +import Connectable :: *; + +export AXI4_Lite :: *; +export AXI4_Lite_Master :: *; +export AXI4_Lite_Slave :: *; +export AXI4_Lite_Types :: *; + +/* +======================== + AXI 4 Lite Master Combined +======================== +*/ + +interface AXI4_Lite_Master_Fab#(numeric type addrwidth, numeric type datawidth); + (* prefix="" *) + interface AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth) rd; + (* prefix="" *) + interface AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth) wr; +endinterface + +typedef Server#(AXI4_Lite_Read_Rq_Pkg#(addrwidth), AXI4_Lite_Read_Rs_Pkg#(datawidth)) AXI4_Lite_Read_Server#(numeric type addrwidth, numeric type datawidth); +typedef Server#(AXI4_Lite_Write_Rq_Pkg#(addrwidth, datawidth), AXI4_Lite_Write_Rs_Pkg) AXI4_Lite_Write_Server#(numeric type addrwidth, numeric type datawidth); + +interface AXI4_Lite_Master#(numeric type addrwidth, numeric type datawidth); + interface AXI4_Lite_Master_Fab#(addrwidth, datawidth) fab; + interface AXI4_Lite_Read_Server#(addrwidth, datawidth) read; + interface AXI4_Lite_Write_Server#(addrwidth, datawidth) write; +endinterface + + +module mkAXI4_Lite_Master#(Integer bufferSizeRead, Integer bufferSizeWrite)(AXI4_Lite_Master#(addrwidth, datawidth)); + AXI4_Lite_Master_Rd#(addrwidth, datawidth) rd_master <- mkAXI4_Lite_Master_Rd(bufferSizeRead); + AXI4_Lite_Master_Wr#(addrwidth, datawidth) wr_master <- mkAXI4_Lite_Master_Wr(bufferSizeWrite); + + interface AXI4_Lite_Master_Fab fab; + interface rd = rd_master.fab; + interface wr = wr_master.fab; + endinterface + interface read = toGPServer(rd_master.request, rd_master.response); + interface write = toGPServer(wr_master.request, wr_master.response); +endmodule + +/* +======================== + AXI 4 Lite Slave Combined +======================== +*/ + +interface AXI4_Lite_Slave_Fab#(numeric type addrwidth, numeric type datawidth); + (* prefix="" *) + interface AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth) rd; + (* prefix="" *) + interface AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth) wr; +endinterface + + +typedef ClientS#(AXI4_Lite_Read_Rq_Pkg#(addrwidth), AXI4_Lite_Read_Rs_Pkg#(datawidth)) AXI4_Lite_Read_Client#(numeric type addrwidth, numeric type datawidth); +typedef ClientS#(AXI4_Lite_Write_Rq_Pkg#(addrwidth, datawidth), AXI4_Lite_Write_Rs_Pkg) AXI4_Lite_Write_Client#(numeric type addrwidth, numeric type datawidth); + +interface AXI4_Lite_Slave#(numeric type addrwidth, numeric type datawidth); + interface AXI4_Lite_Slave_Fab#(addrwidth, datawidth) fab; + interface AXI4_Lite_Read_Client#(addrwidth, datawidth) read; + interface AXI4_Lite_Write_Client#(addrwidth, datawidth) write; +endinterface + + +module mkAXI4_Lite_Slave#(Integer bufferSizeRead, Integer bufferSizeWrite)(AXI4_Lite_Slave#(addrwidth, datawidth)); + AXI4_Lite_Slave_Rd#(addrwidth, datawidth) rd_slave <- mkAXI4_Lite_Slave_Rd(bufferSizeRead); + AXI4_Lite_Slave_Wr#(addrwidth, datawidth) wr_slave <- mkAXI4_Lite_Slave_Wr(bufferSizeWrite); + + interface AXI4_Lite_Slave_Fab fab; + interface rd = rd_slave.fab; + interface wr = wr_slave.fab; + endinterface + interface read = toGPClientS(rd_slave.request, rd_slave.response); + interface write = toGPClientS(wr_slave.request, wr_slave.response); +endmodule + +/* +======================== + Connectable +======================== +*/ + +instance Connectable#(AXI4_Lite_Master_Fab#(addrwidth, datawidth), AXI4_Lite_Slave_Fab#(addrwidth, datawidth)); + module mkConnection#(AXI4_Lite_Master_Fab#(addrwidth, datawidth) master, AXI4_Lite_Slave_Fab#(addrwidth, datawidth) slave)(Empty); + mkConnection(master.rd, slave.rd); + mkConnection(master.wr, slave.wr); + endmodule +endinstance + +instance Connectable#(AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth), AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth)); + module mkConnection#(AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth) master, AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth) slave)(Empty); + rule forward1; master.pawready(slave.awready); endrule + rule forward2; slave.pawvalid(master.awvalid); endrule + rule forward3; slave.pawaddr(master.awaddr); endrule + rule forward4; slave.pawprot(master.awprot); endrule + rule forward5; master.pwready(slave.wready); endrule + rule forward6; slave.pwvalid(master.wvalid); endrule + rule forward7; slave.pwdata(master.wdata); endrule + rule forward8; slave.pwstrb(master.wstrb); endrule + rule forward9; master.pbvalid(slave.bvalid); endrule + rule forward10; slave.pbready(master.bready); endrule + rule forward11; master.pbresp(slave.bresp); endrule + endmodule +endinstance + +instance Connectable#(AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth), AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth)); + module mkConnection#(AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth) slave, AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + +instance Connectable#(AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth), AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth)); + module mkConnection#(AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth) master, AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth) slave)(Empty); + rule forward1; slave.parvalid(master.arvalid); endrule + rule forward2; master.parready(slave.arready); endrule + rule forward3; slave.paraddr(master.araddr); endrule + rule forward4; slave.parprot(master.arprot); endrule + + rule forward5; slave.prready(master.rready); endrule + rule forward6; master.prvalid(slave.rvalid); endrule + rule forward7; master.prdata(slave.rdata); endrule + rule forward8; master.prresp(slave.rresp); endrule + endmodule +endinstance + +instance Connectable#(AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth), AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth)); + module mkConnection#(AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth) slave, AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth) master)(Empty); + mkConnection(master, slave); + endmodule +endinstance + +endpackage \ No newline at end of file diff --git a/src/AXI4_Lite_Master.bsv b/src/AXI4_Lite_Master.bsv index 991d61e..b418dbf 100644 --- a/src/AXI4_Lite_Master.bsv +++ b/src/AXI4_Lite_Master.bsv @@ -213,54 +213,6 @@ module mkAXI4_Lite_Master_Wr#(Integer bufferSize)(AXI4_Lite_Master_Wr#(addrwidth endinterface endmodule -/* -======================== - Connectable -======================== -*/ - -instance Connectable#(AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth), AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth)); - module mkConnection#(AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth) master, AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth) slave)(Empty); - rule forward1; master.pawready(slave.awready); endrule - rule forward2; slave.pawvalid(master.awvalid); endrule - rule forward3; slave.pawaddr(master.awaddr); endrule - rule forward4; slave.pawprot(master.awprot); endrule - rule forward5; master.pwready(slave.wready); endrule - rule forward6; slave.pwvalid(master.wvalid); endrule - rule forward7; slave.pwdata(master.wdata); endrule - rule forward8; slave.pwstrb(master.wstrb); endrule - rule forward9; master.pbvalid(slave.bvalid); endrule - rule forward10; slave.pbready(master.bready); endrule - rule forward11; master.pbresp(slave.bresp); endrule - endmodule -endinstance - -instance Connectable#(AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth), AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth)); - module mkConnection#(AXI4_Lite_Slave_Wr_Fab#(addrwidth, datawidth) slave, AXI4_Lite_Master_Wr_Fab#(addrwidth, datawidth) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance - -instance Connectable#(AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth), AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth)); - module mkConnection#(AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth) master, AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth) slave)(Empty); - rule forward1; slave.parvalid(master.arvalid); endrule - rule forward2; master.parready(slave.arready); endrule - rule forward3; slave.paraddr(master.araddr); endrule - rule forward4; slave.parprot(master.arprot); endrule - - rule forward5; slave.prready(master.rready); endrule - rule forward6; master.prvalid(slave.rvalid); endrule - rule forward7; master.prdata(slave.rdata); endrule - rule forward8; master.prresp(slave.rresp); endrule - endmodule -endinstance - -instance Connectable#(AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth), AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth)); - module mkConnection#(AXI4_Lite_Slave_Rd_Fab#(addrwidth, datawidth) slave, AXI4_Lite_Master_Rd_Fab#(addrwidth, datawidth) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance - module mkAXI4_Lite_Master_Rd_Dummy(AXI4_Lite_Master_Rd#(addrwidth, datawidth)); interface AXI4_Lite_Master_Rd_Fab fab; interface arvalid = False; @@ -268,7 +220,14 @@ module mkAXI4_Lite_Master_Rd_Dummy(AXI4_Lite_Master_Rd#(addrwidth, datawidth)); interface arprot = unpack(0); interface rready = False; + + interface prresp = ?; + interface prdata = ?; + interface prvalid = ?; + interface parready = ?; endinterface + interface response = ?; + interface request = ?; endmodule module mkAXI4_Lite_Master_Wr_Dummy(AXI4_Lite_Master_Wr#(addrwidth, datawidth)); @@ -282,7 +241,14 @@ module mkAXI4_Lite_Master_Wr_Dummy(AXI4_Lite_Master_Wr#(addrwidth, datawidth)); interface wstrb = unpack(0); interface bready = False; + + interface pawready = ?; + interface pbresp = ?; + interface pbvalid = ?; + interface pwready = ?; endinterface + interface response = ?; + interface request = ?; endmodule function Action axi4_lite_write(AXI4_Lite_Master_Wr#(a, d) m, diff --git a/src/AXI4_Lite_Slave.bsv b/src/AXI4_Lite_Slave.bsv index 8ee80fe..2dc4e95 100644 --- a/src/AXI4_Lite_Slave.bsv +++ b/src/AXI4_Lite_Slave.bsv @@ -223,7 +223,15 @@ module mkAXI4_Lite_Slave_Rd_Dummy(AXI4_Lite_Slave_Rd#(addrwidth, datawidth)); interface rvalid = False; interface rdata = unpack(0); interface rresp = unpack(0); + + interface prready = ?; + interface parprot = ?; + interface paraddr = ?; + interface parvalid = ?; endinterface + interface response = ?; + interface first = ?; + interface request = ?; endmodule module mkAXI4_Lite_Slave_Wr_Dummy(AXI4_Lite_Slave_Wr#(addrwidth, datawidth)); @@ -234,7 +242,17 @@ module mkAXI4_Lite_Slave_Wr_Dummy(AXI4_Lite_Slave_Wr#(addrwidth, datawidth)); interface bvalid = False; interface bresp = unpack(0); + interface pbready = ?; + interface pwstrb = ?; + interface pwdata = ?; + interface pwvalid = ?; + interface pawprot = ?; + interface pawaddr = ?; + interface pawvalid = ?; endinterface + interface response = ?; + interface first = ?; + interface request = ?; endmodule endpackage diff --git a/src/AXI4_Master.bsv b/src/AXI4_Master.bsv index 600c103..d41b3dd 100644 --- a/src/AXI4_Master.bsv +++ b/src/AXI4_Master.bsv @@ -326,74 +326,6 @@ interface TestIfc; // (*prefix="S_AXI"*)interface AXI4_Slave_Rd_Fab#(32, 32, 1, 1) s_rd; endinterface -module mkTestIfc(TestIfc); - AXI4_Master_Wr#(32, 32, 1, 1) master_wr <- mkAXI4_Master_Wr(2, 2, 2, True); - AXI4_Master_Rd#(32, 32, 1, 1) master_rd <- mkAXI4_Master_Rd(2, 2, True); - - AXI4_Slave_Wr#(32, 32, 1, 1) slave_wr <- mkAXI4_Slave_Wr(2, 2, 2); - AXI4_Slave_Rd#(32, 32, 1, 1) slave_rd <- mkAXI4_Slave_Rd(2, 2); - - mkConnection(master_rd.fab, slave_rd.fab); - mkConnection(master_wr.fab, slave_wr.fab); - - //interface m_wr = master_wr.fab; - //interface m_rd = master_rd.fab; - - //interface s_wr = slave_wr.fab; - //interface s_rd = slave_rd.fab; -endmodule - -/* -======================== - Connectable -======================== -*/ -instance Connectable#(AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width)); - module mkConnection#(AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width) master, AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) slave)(Empty); - rule forward1; master.parready(slave.arready); endrule - rule forward2; slave.parvalid(master.arvalid); endrule - rule forward3; - slave.parchannel(master.arid, master.araddr, master.arlen, master.arsize, master.arburst, - master.arlock, master.arcache, master.arprot, master.arqos, master.arregion, master.aruser); - endrule - - rule forward4; master.prvalid(slave.rvalid); endrule - rule forward5; slave.prready(master.rready); endrule - - rule forward6; - master.prchannel(slave.rid, slave.rdata, slave.rresp, slave.rlast, slave.ruser); - endrule - endmodule -endinstance - -instance Connectable#(AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width)); - module mkConnection#(AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) slave, AXI4_Master_Rd_Fab#(addrwidth, datawidth, id_width, user_width) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance - -instance Connectable#(AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width)); - module mkConnection#(AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) master, AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) slave)(Empty); - rule forward1; master.pawready(slave.awready); endrule - rule forward2; slave.pawvalid(master.awvalid); endrule - rule forward3; slave.pawchannel(master.awid, master.awaddr, master.awlen, master.awsize, master.awburst, master.awlock, master.awcache, master.awprot, master.awqos, master.awregion, master.awuser); endrule - - rule forward4; master.pwready(slave.wready); endrule - rule forward5; slave.pwvalid(master.wvalid); endrule - rule forward6; slave.pwchannel(master.wdata, master.wstrb, master.wlast, master.wuser); endrule - - rule forward7; master.pbvalid(slave.bvalid); endrule - rule forward8; slave.pbready(master.bready); endrule - rule forward9; master.bin(slave.bresp, slave.bid, slave.buser); endrule - endmodule -endinstance - -instance Connectable#(AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width), AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width)); - module mkConnection#(AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) slave, AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) master)(Empty); - mkConnection(master, slave); - endmodule -endinstance - module mkAXI4_Master_Rd_Dummy(AXI4_Master_Rd#(addrwidth, datawidth, id_width, user_width)); interface AXI4_Master_Rd_Fab fab; interface arvalid = False; @@ -423,6 +355,9 @@ module mkAXI4_Master_Rd_Dummy(AXI4_Master_Rd#(addrwidth, datawidth, id_width, us method Action parready(Bool a); endmethod endinterface + interface response = ?; + interface snoop = ?; + interface request = ?; endmodule module mkAXI4_Master_Wr_Dummy(AXI4_Master_Wr#(addrwidth, datawidth, id_width, user_width)); @@ -457,6 +392,10 @@ module mkAXI4_Master_Wr_Dummy(AXI4_Master_Wr#(addrwidth, datawidth, id_width, us method Action bin(AXI4_Response r, Bit#(id_width) bid, Bit#(user_width) buser); endmethod endinterface + interface response = ?; + interface snoop = ?; + interface request_data = ?; + interface request_addr = ?; endmodule // Helper functions to simplify usage of the above modules diff --git a/src/AXI4_Slave.bsv b/src/AXI4_Slave.bsv index 084e354..3cc42f6 100644 --- a/src/AXI4_Slave.bsv +++ b/src/AXI4_Slave.bsv @@ -141,7 +141,12 @@ module mkAXI4_Slave_Rd_Dummy(AXI4_Slave_Rd#(addrwidth, datawidth, id_width, user interface rresp = unpack(0); interface rlast = unpack(0); interface ruser = unpack(0); + interface prready = ?; + interface parchannel = ?; + interface parvalid = ?; endinterface + interface response = ?; + interface request = ?; endmodule /* @@ -186,7 +191,9 @@ interface AXI4_Slave_Wr#(numeric type addrwidth, numeric type datawidth, numeric interface AXI4_Slave_Wr_Fab#(addrwidth, datawidth, id_width, user_width) fab; interface Get#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; + method AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width) snoop_addr; interface Get#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; + method AXI4_Write_Rq_Data#(datawidth, user_width) snoop_data; interface Put#(AXI4_Write_Rs#(id_width, user_width)) response; endinterface @@ -279,6 +286,9 @@ module mkAXI4_Slave_Wr#(Integer bufferSizeAddr, Integer bufferSizeData, Integer wbuser <= out.first().user(); endrule + method snoop_addr = in_addr.first; + method snoop_data = in_data.first; + interface Get request_addr = toGet(in_addr); interface Get request_data = toGet(in_data); interface Put response = toPut(out); @@ -310,7 +320,17 @@ module mkAXI4_Slave_Wr_Dummy(AXI4_Slave_Wr#(addrwidth, datawidth, id_width, user interface bresp = unpack(0); interface bid = unpack(0); interface buser = unpack(0); + interface pbready = ?; + interface pwchannel = ?; + interface pwvalid = ?; + interface pawchannel = ?; + interface pawvalid = ?; endinterface + interface response = ?; + interface request_data = ?; + interface request_addr = ?; + interface snoop_data = ?; + interface snoop_addr = ?; endmodule endpackage diff --git a/src/BlueAXI.bsv b/src/BlueAXI.bsv index da7b132..47a3a1b 100644 --- a/src/BlueAXI.bsv +++ b/src/BlueAXI.bsv @@ -1,13 +1,9 @@ package BlueAXI; -import AXI4_Lite_Types :: *; -import AXI4_Lite_Master :: *; -import AXI4_Lite_Slave :: *; +import AXI4_Lite :: *; import GenericAxi4LiteSlave :: *; -import AXI4_Types :: *; -import AXI4_Master :: *; -import AXI4_Slave :: *; +import AXI4 :: *; import AXI4_Stream :: *; import GenericAxi4Master :: *; @@ -16,13 +12,9 @@ import BlueAXIBRAM :: *; import AXI4_Monitor :: *; -import AXI3_Types :: *; -import AXI3_Master :: *; -import AXI3_Slave :: *; +import AXI3 :: *; -export AXI4_Lite_Types :: *; -export AXI4_Lite_Master :: *; -export AXI4_Lite_Slave :: *; +export AXI4_Lite :: *; export GenericAxi4LiteSlave :: *; export AXI4_Types :: *; diff --git a/src/ClientServerS.bs b/src/ClientServerS.bs new file mode 100644 index 0000000..a79f6c1 --- /dev/null +++ b/src/ClientServerS.bs @@ -0,0 +1,369 @@ +--@ Copyright (c) 2020 Bluespec, Inc. All rights reserved. +--@ +--@ Redistribution and use in source and binary forms, with or without +--@ modification, are permitted provided that the following conditions are +--@ met: +--@ +--@ 1. Redistributions of source code must retain the above copyright +--@ notice, this list of conditions and the following disclaimer. +--@ +--@ 2. Redistributions in binary form must reproduce the above copyright +--@ notice, this list of conditions and the following disclaimer in the +--@ documentation and/or other materials provided with the +--@ distribution. +--@ +--@ 3. Neither the name of the copyright holder nor the names of its +--@ contributors may be used to endorse or promote products derived +--@ from this software without specific prior written permission. +--@ +--@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +--@ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +--@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +--@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +--@ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +--@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +--@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +--@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +--@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +--@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +--@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +package ClientServerS( + ClientS(..), ServerS(..), ClientServerS(..), mkRequestResponseBufferS, + mkSizedRequestResponseBufferS, mkResponseBufferS, mkRequestBufferS, + mkRequestResponseBufferS1S, joinServerSsBC, joinServerSs, splitServerS, + fifosToServerS, fifosToClientS, fifosToClientServerS, + toGPClientS, toGPServerS) + where +import qualified Vector +import List +import FIFO +import Counter +import Connectable +import GetPut +import Clocks + +--@ \subsubsection{ClientServerS} +--@ \index{ClientServerS@\te{ClientServerS} (package)|textbf} +--@ +--@ The interfaces \te{ClientS} and \te{ServerS} can be used for +--@ modules that have a request-response type of interface +--@ (e.g. a RAM). +--@ The ServerS accepts requests and generates responses, and +--@ vice versa for the ClientS. +--@ There are no assumptions about how many (if any) responses +--@ a request will generate. + +--@ \index{ClientS@\te{ClientS} (interface)|textbf} +--@ \begin{libverbatim} +--@ interface ClientS #(type a, type b); +--@ interface Get#(a) request(); +--@ interface Put#(b) response(); +--@ endinterface: ClientS +--@ \end{libverbatim} +interface ClientS a b = + request :: Get a + response :: Put b + +--@ \index{ServerS@\te{ServerS} (interface)|textbf} +--@ \begin{libverbatim} +--@ interface ServerS #(type a, type b); +--@ interface Put#(a) request(); +--@ interface Get#(b) response(); +--@ endinterface: ServerS +--@ \end{libverbatim} +interface ServerS a b = + request :: Put a + response :: Get b + +--@ A \te{ClientS} can be connected to a \te{ServerS} +--@ and vice versa. +--@ \begin{libverbatim} +--@ instance Connectable #(ClientS#(a, b), ServerS#(a, b)); +--@ instance Connectable #(ServerS#(a, b), ClientS#(a, b)); +--@ \end{libverbatim} +instance Connectable (ClientS a b) (ServerS a b) + where + mkConnection :: (IsModule m c ) => ClientS a b -> ServerS a b -> m Empty + mkConnection c s = + module + rules + "ClientServerSRequest":when True + ==> action + x :: a <- c.request.get + s.request.put x + "ClientServerSResponse":when True + ==> action + x :: b <- s.response.get + c.response.put x + +instance Connectable (ServerS a b) (ClientS a b) + where + mkConnection s c = mkConnection c s + +instance (Bits a sa, Bits b sb) => ClockConv (ClientS a b) where + mkConverter :: (Prelude.IsModule m c) => Integer -> ClientS a b -> m (ClientS a b) + mkConverter d cluses = + module + req <- mkConverter d cluses.request + resp <- mkConverter d cluses.response + + interface + request = req + response = resp + +instance (Bits a sa, Bits b sb) => ClockConv (ServerS a b) where + mkConverter :: (Prelude.IsModule m c) => Integer -> ServerS a b -> m (ServerS a b) + mkConverter d cluses = + module + req <- mkConverter d cluses.request + resp <- mkConverter d cluses.response + + interface + request = req + response = resp + +--@ \lineup +--@ \begin{libverbatim} +--@ typedef Tuple2 #(ClientS#(a, b), ServerS#(a, b)) ClientServerS #(type a, type b); +--@ \end{libverbatim} +type ClientServerS a b = (ClientS a b, ServerS a b) + +--@ Create a buffer that just passes requests and responses between the +--@ two generated interfaces. +--@ \index{mkRequestResponseBufferS@\te{mkRequestResponseBufferS} (function)|textbf} +--@ \begin{libverbatim} +--@ module mkRequestResponseBufferS(ClientServerS#(a, b)) +--@ provisos (Bits#(a, sa), Bits#(b, sb)); +--@ \end{libverbatim} +mkRequestResponseBufferS :: (IsModule m c , Bits a sa, Bits b sb) => m (ClientServerS a b) +mkRequestResponseBufferS = + module + (qget, qput) :: (Get a, Put a) <- mkGetPut + (sget, sput) :: (Get b, Put b) <- mkGetPut + let c = interface ClientS + request = qget + response = sput + s = interface ServerS + request = qput + response = sget + interface (c, s) + +--@ Create a buffer that just passes requests and responses between the +--@ two generated interfaces. Uses half the flops of +--@ \te{mkRequestResponseBufferS}, but also has half the throughput. +--@ \index{mkRequestResponseBufferS1S@\te{mkRequestResponseBufferS1S} (function)|textbf} +--@ \begin{libverbatim} +--@ module mkRequestResponseBufferS1S(ClientServerS#(a, b)) +--@ provisos (Bits#(a, sa), Bits#(b, sb)); +--@ \end{libverbatim} +mkRequestResponseBufferS1S :: (IsModule m c , Bits a sa, Bits b sb) => m (ClientServerS a b) +mkRequestResponseBufferS1S = + module + (qget, qput) :: (Get a, Put a) <- mkGPFIFO1 + (sget, sput) :: (Get b, Put b) <- mkGPFIFO1 + let c = interface ClientS + request = qget + response = sput + s = interface ServerS + request = qput + response = sget + interface (c, s) + +--@ The same, using sized FIFOs. +--@ \index{mkSizedRequestResponseBufferS@\te{mkSizedRequestResponseBufferS} (function)|textbf} +--@ \begin{libverbatim} +--@ module mkSizedRequestResponseBufferS#(Integer sz)(ClientServerS#(a, b)) +--@ provisos (Bits#(a, sa), Bits#(b, sb)); +--@ \end{libverbatim} +mkSizedRequestResponseBufferS :: (IsModule m c , Bits a sa, Bits b sb) => Integer -> m (ClientServerS a b) +mkSizedRequestResponseBufferS sz = + module + (qget, qput) :: (Get a, Put a) <- mkGPSizedFIFO sz + (sget, sput) :: (Get b, Put b) <- mkGPSizedFIFO sz + let c = interface ClientS + request = qget + response = sput + s = interface ServerS + request = qput + response = sget + interface (c, s) + + +--@ Create a new ServerS with buffered requests. +--@ \index{mkRequestBufferS@\te{mkRequestBufferS} (function)|textbf} +--@ \begin{libverbatim} +--@ module mkRequestBufferS#(ServerS#(a, b) s)(ServerS#(a, b)) +--@ provisos (Bits#(a, sa)); +--@ \end{libverbatim} +mkRequestBufferS :: (IsModule m c , Bits a sa) => ServerS a b -> m (ServerS a b) +mkRequestBufferS s = + module + (qget, qput) :: (Get a, Put a) <- mkGetPut + rules + "mkRequestBufferS" : when True ==> + action + x :: a <- qget.get + s.request.put x + + interface -- ServerS + request = qput + response = s.response + + +--@ Create a new ServerS with buffered responses. +--@ \index{mkResponseBufferS@\te{mkResponseBufferS} (function)|textbf} +--@ \begin{libverbatim} +--@ module mkResponseBufferS#(ServerS#(a, b) s)(ServerS#(a, b)) +--@ provisos (Bits#(b, sb)); +--@ \end{libverbatim} +mkResponseBufferS :: (IsModule m c , Bits b sb) => ServerS a b -> m (ServerS a b) +mkResponseBufferS s = + module + (sget, sput) :: (Get b, Put b) <- mkGetPut + rules + "mkResponseBufferS" : when True ==> + action + x :: b <- s.response.get + sput.put x + + interface -- ServerS + request = s.request + response = sget + +--@ Join a list of ServerS's to one ServerS. All incoming requests are broadcasted +--@ all the ServerS's and all responses are merged. +--@ The function introduces a one cycle latency on the response. +--@ \index{joinServerSsSBC@\te{joinServerSsSBC} (function)|textbf} +--@ \begin{libverbatim} +--@ module joinServerSsSBC#(List#(ServerS#(a, b)) ifs)(ServerS#(a, b)) +--@ provisos (Bits#(b, sb)); +--@ \end{libverbatim} +joinServerSsBC :: (IsModule m c , Bits b sb) => List (ServerS a b) -> m (ServerS a b) +joinServerSsBC ifs = + module + (sget, sput) :: (Get b, Put b) <- mkGetPut + let rl s = + rules + "joinServerSsSBC": + when True ==> + action + x <- (s :: ServerS a b).response.get + sput.put x + addRules $ foldr (<+>) (rules {}) (map rl ifs) + interface -- ServerS + request = + interface Put + put req = joinActions (map (\ i -> (i :: ServerS a b).request.put req) ifs) + response = sget + +--@ Join a list of ServerSs to one ServerS. All incoming requests are sent to +--@ a selected subset of the ServerSs and all responses are merged. +--@ The selection is my a function that can transform the request type +--@ while testing if it should be sent on. +--@ The function introduces a one cycle latency on the response. +--@ \index{joinServerSs@\te{joinServerSs} (function)|textbf} +--@ \begin{libverbatim} +--@ module joinServerSs#( List#(Tuple2 #(a -> Maybe#(a'), +--@ ServerS#(a', b))) ifs)(ServerS#(a, b)) +--@ provisos (Bits#(b, sb)); +--@ \end{libverbatim} +joinServerSs :: (IsModule m c , Bits b sb) => List (a -> Maybe a', ServerS a' b) -> m (ServerS a b) +joinServerSs ifs = + module + (sget, sput) :: (Get b, Put b) <- mkGetPut + let rl (_, s) = + rules + "joinServerSs": + when True ==> + action + x <- (s :: ServerS a' b).response.get + sput.put x + send req (f, s) = + case f req of + Nothing -> noAction + Just req' -> (s :: ServerS a' b).request.put req' + addRules $ foldr (<+>) (rules {}) (map rl ifs) + interface -- ServerS + request = + interface Put + put req = joinActions (map (send req) ifs) + response = sget + +type MaxLat = 8 -- XXX This is just wrong +--@ Split a ServerS into a number of identical ServerSs. +--@ The integer argument specifies how many outstanding requests +--@ a returned ServerS may have. This number should be +--@ the latency of the argument ServerS to sustain full bandwidth. +--@ (A small number still works, as does a larger number.) +--@ \index{splitServerS@\te{splitServerS} (function)|textbf} +--@ \begin{libverbatim} +--@ module splitServerS#(Integer lat, ServerS#(a, b) serv)(Vector#(n, ServerS#(a, b))) +--@ provisos (Bits#(b, sb), Log#(n, ln)); +--@ \end{libverbatim} +splitServerS :: (IsModule m c , Bits b sb, Log n ln) => + Integer -> ServerS a b -> m (Vector.Vector n (ServerS a b)) +splitServerS lat serv = + module + tags :: FIFO (Bit ln) <- mkSizedFIFO lat + let mkServ :: (Bit ln) -> m (ServerS a b) + mkServ i = + module + out :: FIFO b <- mkSizedFIFO lat + cnt :: Counter MaxLat <- mkCounter (fromInteger lat) + rules + when tags.first == i + ==> action + tags.deq + x <- serv.response.get + out.enq x + interface ServerS + request = + interface Put + put req = + action + serv.request.put req + tags.enq i + cnt.down + when cnt.value > 0 + response = + interface Get + get = do + out.deq + cnt.up + return out.first + Vector.mapM (mkServ ∘ fromInteger) Vector.genList + +--@ fifosToServerS + +fifosToServerS :: FIFO rq -> FIFO rs -> ServerS rq rs +fifosToServerS rqf rsf = + interface ServerS + request = fifoToPut rqf + response = fifoToGet rsf + +fifosToClientS :: FIFO rq -> FIFO rs -> ClientS rq rs +fifosToClientS rqf rsf = + interface ClientS + request = fifoToGet rqf + response = fifoToPut rsf + +fifosToClientServerS :: FIFO rq -> FIFO rs -> ClientServerS rq rs +fifosToClientServerS rqf rsf = (fifosToClientS rqf rsf, fifosToServerS rqf rsf) + +-- toGPClientS, toGPServerS + +toGPClientS :: (ToGet rq_ifc rq, ToPut rs_ifc rs) => + rq_ifc -> rs_ifc -> ClientS rq rs +toGPClientS rqi rsi = + interface ClientS + request = toGet rqi + response = toPut rsi + +toGPServerS :: (ToPut rq_ifc rq, ToGet rs_ifc rs) => + rq_ifc -> rs_ifc -> ServerS rq rs +toGPServerS rqi rsi = + interface ServerS + request = toPut rqi + response = toGet rsi + diff --git a/src/GenericAxi4Master.bsv b/src/GenericAxi4Master.bsv index 47572c9..4670aaa 100644 --- a/src/GenericAxi4Master.bsv +++ b/src/GenericAxi4Master.bsv @@ -9,8 +9,7 @@ import SpecialFIFOs :: *; import Vector :: *; import BUtils :: *; -import AXI4_Types :: *; -import AXI4_Master :: *; +import AXI4 :: *; typedef struct { Bit#(addr_width) address; From 7fc7c6126c8e2161b1e8a62001f77f0a1320361f Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Fri, 11 Oct 2024 17:40:33 +0200 Subject: [PATCH 2/6] Replace function composition to prevent weird (encoding?) bug --- src/ClientServerS.bs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ClientServerS.bs b/src/ClientServerS.bs index a79f6c1..49fd192 100644 --- a/src/ClientServerS.bs +++ b/src/ClientServerS.bs @@ -332,7 +332,7 @@ splitServerS lat serv = out.deq cnt.up return out.first - Vector.mapM (mkServ ∘ fromInteger) Vector.genList + Vector.mapM (\ x -> mkServ (fromInteger x)) Vector.genList --@ fifosToServerS From bd3d5caea6bdaa9f01843e3aa54f66a5bfc93102 Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Sun, 13 Oct 2024 16:49:30 +0200 Subject: [PATCH 3/6] Remove snooping in combined modules for now --- src/AXI3.bsv | 37 ++--- src/AXI3_Slave.bsv | 4 + src/AXI4.bsv | 41 ++--- src/AXI4_Lite.bsv | 10 +- src/AXI4_Slave.bsv | 4 + src/ClientServerS.bs | 369 ------------------------------------------- 6 files changed, 36 insertions(+), 429 deletions(-) delete mode 100644 src/ClientServerS.bs diff --git a/src/AXI3.bsv b/src/AXI3.bsv index 54940af..abdc826 100644 --- a/src/AXI3.bsv +++ b/src/AXI3.bsv @@ -1,8 +1,8 @@ package AXI3; import GetPut :: *; -import ClientServerS :: *; import Connectable :: *; +import ClientServer :: *; import AXI3_Types :: *; import AXI3_Slave :: *; @@ -26,11 +26,11 @@ interface AXI3_Master_Fab#(numeric type addrwidth, numeric type datawidth, numer interface AXI3_Master_Wr_Fab#(addrwidth, datawidth, id_width) wr; endinterface -typedef ServerS#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width); +typedef Server#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width); interface AXI3_Write_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width); interface Put#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; interface Put#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; - interface GetS#(AXI3_Write_Rs#(id_width)) response; + interface Get#(AXI3_Write_Rs#(id_width)) response; endinterface interface AXI3_Master#(numeric type addrwidth, numeric type datawidth, numeric type id_width); @@ -48,16 +48,11 @@ module mkAXI3_Master#(Integer bufferInRead, Integer bufferOutRead, Bool bramRead interface rd = rd_master.fab; interface wr = wr_master.fab; endinterface - interface read = toGPServerS(rd_master.request, rd_master.response); + interface read = toGPServer(rd_master.request, rd_master.response); interface AXI3_Write_Server write; interface request_addr = wr_master.request_addr; interface request_data = wr_master.request_data; - interface GetS response; - method first = wr_master.snoop; - method Action deq(); - let r <- wr_master.response.get; - endmethod - endinterface + interface response = wr_master.response; endinterface endmodule @@ -75,10 +70,10 @@ interface AXI3_Slave_Fab#(numeric type addrwidth, numeric type datawidth, numeri endinterface -typedef ClientS#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width); +typedef Client#(AXI3_Read_Rq#(addrwidth, id_width), AXI3_Read_Rs#(datawidth, id_width)) AXI3_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width); interface AXI3_Write_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width); - interface GetS#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; - interface GetS#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; + interface Get#(AXI3_Write_Rq_Addr#(addrwidth, id_width)) request_addr; + interface Get#(AXI3_Write_Rq_Data#(datawidth, id_width)) request_data; interface Put#(AXI3_Write_Rs#(id_width)) response; endinterface @@ -97,20 +92,10 @@ module mkAXI3_Slave#(Integer bufferInRead, Integer bufferOutRead, Integer buffer interface rd = rd_slave.fab; interface wr = wr_slave.fab; endinterface - interface read = toGPClientS(rd_slave.request, rd_slave.response); + interface read = toGPClient(rd_slave.request, rd_slave.response); interface AXI3_Write_Client write; - interface GetS request_addr; - method first = wr_slave.snoop_addr; - method Action deq(); - let r <- wr_slave.request_addr.get; - endmethod - endinterface - interface GetS request_data; - method first = wr_slave.snoop_data; - method Action deq(); - let r <- wr_slave.request_data.get; - endmethod - endinterface + interface request_addr = wr_slave.request_addr; + interface request_data = wr_slave.request_data; interface response = wr_slave.response; endinterface endmodule diff --git a/src/AXI3_Slave.bsv b/src/AXI3_Slave.bsv index f1deb75..549a026 100644 --- a/src/AXI3_Slave.bsv +++ b/src/AXI3_Slave.bsv @@ -42,6 +42,7 @@ interface AXI3_Slave_Rd#(numeric type addrwidth, numeric type datawidth, numeric interface AXI3_Slave_Rd_Fab#(addrwidth, datawidth, id_width) fab; interface Get#(AXI3_Read_Rq#(addrwidth, id_width)) request; + method AXI3_Read_Rq#(addrwidth, id_width) snoop; interface Put#(AXI3_Read_Rs#(datawidth, id_width)) response; endinterface @@ -105,6 +106,8 @@ module mkAXI3_Slave_Rd#(Integer bufferIn, Integer bufferOut)(AXI3_Slave_Rd#(addr wrlast <= out.first().last(); endrule + method snoop = in.first; + interface Get request = toGet(in); interface Put response = toPut(out); @@ -137,6 +140,7 @@ module mkAXI3_Slave_Rd_Dummy(AXI3_Slave_Rd#(addrwidth, datawidth, id_width)); endinterface interface response = ?; interface request = ?; + interface snoop = ?; endmodule /* diff --git a/src/AXI4.bsv b/src/AXI4.bsv index fec57c2..2e89155 100644 --- a/src/AXI4.bsv +++ b/src/AXI4.bsv @@ -10,12 +10,12 @@ export AXI4_Types :: *; export AXI4 :: *; import GetPut :: *; -import ClientServerS :: *; +import ClientServer :: *; import Connectable :: *; /* ======================== - AXI 3 Master Combined + AXI 4 Master Combined ======================== */ @@ -26,11 +26,11 @@ interface AXI4_Master_Fab#(numeric type addrwidth, numeric type datawidth, numer interface AXI4_Master_Wr_Fab#(addrwidth, datawidth, id_width, user_width) wr; endinterface -typedef ServerS#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width ,user_width)) AXI4_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); +typedef Server#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width ,user_width)) AXI4_Read_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); interface AXI4_Write_Server#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); interface Put#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; interface Put#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; - interface GetS#(AXI4_Write_Rs#(id_width, user_width)) response; + interface Get#(AXI4_Write_Rs#(id_width, user_width)) response; endinterface interface AXI4_Master#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); @@ -48,22 +48,17 @@ module mkAXI4_Master#(Integer bufferInRead, Integer bufferOutRead, Bool bramRead interface rd = rd_master.fab; interface wr = wr_master.fab; endinterface - interface read = toGPServerS(rd_master.request, rd_master.response); + interface read = toGPServer(rd_master.request, rd_master.response); interface AXI4_Write_Server write; interface request_addr = wr_master.request_addr; interface request_data = wr_master.request_data; - interface GetS response; - method first = wr_master.snoop; - method Action deq(); - let r <- wr_master.response.get; - endmethod - endinterface + interface response = wr_master.response; endinterface endmodule /* ======================== - AXI 3 Slave Combined + AXI 4 Slave Combined ======================== */ @@ -75,10 +70,10 @@ interface AXI4_Slave_Fab#(numeric type addrwidth, numeric type datawidth, numeri endinterface -typedef ClientS#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width, user_width)) AXI4_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); +typedef Client#(AXI4_Read_Rq#(addrwidth, id_width, user_width), AXI4_Read_Rs#(datawidth, id_width, user_width)) AXI4_Read_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); interface AXI4_Write_Client#(numeric type addrwidth, numeric type datawidth, numeric type id_width, numeric type user_width); - interface GetS#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; - interface GetS#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; + interface Get#(AXI4_Write_Rq_Addr#(addrwidth, id_width, user_width)) request_addr; + interface Get#(AXI4_Write_Rq_Data#(datawidth, user_width)) request_data; interface Put#(AXI4_Write_Rs#(id_width, user_width)) response; endinterface @@ -97,20 +92,10 @@ module mkAXI4_Slave#(Integer bufferInRead, Integer bufferOutRead, Integer buffer interface rd = rd_slave.fab; interface wr = wr_slave.fab; endinterface - interface read = toGPClientS(rd_slave.request, rd_slave.response); + interface read = toGPClient(rd_slave.request, rd_slave.response); interface AXI4_Write_Client write; - interface GetS request_addr; - method first = wr_slave.snoop_addr; - method Action deq(); - let r <- wr_slave.request_addr.get; - endmethod - endinterface - interface GetS request_data; - method first = wr_slave.snoop_data; - method Action deq(); - let r <- wr_slave.request_data.get; - endmethod - endinterface + interface request_addr = wr_slave.request_addr; + interface request_data = wr_slave.request_data; interface response = wr_slave.response; endinterface endmodule diff --git a/src/AXI4_Lite.bsv b/src/AXI4_Lite.bsv index 9e2cc5d..ff86c45 100644 --- a/src/AXI4_Lite.bsv +++ b/src/AXI4_Lite.bsv @@ -4,7 +4,6 @@ import AXI4_Lite_Master :: *; import AXI4_Lite_Slave :: *; import AXI4_Lite_Types :: *; import ClientServer :: *; -import ClientServerS :: *; import GetPut :: *; import Connectable :: *; @@ -62,8 +61,8 @@ interface AXI4_Lite_Slave_Fab#(numeric type addrwidth, numeric type datawidth); endinterface -typedef ClientS#(AXI4_Lite_Read_Rq_Pkg#(addrwidth), AXI4_Lite_Read_Rs_Pkg#(datawidth)) AXI4_Lite_Read_Client#(numeric type addrwidth, numeric type datawidth); -typedef ClientS#(AXI4_Lite_Write_Rq_Pkg#(addrwidth, datawidth), AXI4_Lite_Write_Rs_Pkg) AXI4_Lite_Write_Client#(numeric type addrwidth, numeric type datawidth); +typedef Client#(AXI4_Lite_Read_Rq_Pkg#(addrwidth), AXI4_Lite_Read_Rs_Pkg#(datawidth)) AXI4_Lite_Read_Client#(numeric type addrwidth, numeric type datawidth); +typedef Client#(AXI4_Lite_Write_Rq_Pkg#(addrwidth, datawidth), AXI4_Lite_Write_Rs_Pkg) AXI4_Lite_Write_Client#(numeric type addrwidth, numeric type datawidth); interface AXI4_Lite_Slave#(numeric type addrwidth, numeric type datawidth); interface AXI4_Lite_Slave_Fab#(addrwidth, datawidth) fab; @@ -71,7 +70,6 @@ interface AXI4_Lite_Slave#(numeric type addrwidth, numeric type datawidth); interface AXI4_Lite_Write_Client#(addrwidth, datawidth) write; endinterface - module mkAXI4_Lite_Slave#(Integer bufferSizeRead, Integer bufferSizeWrite)(AXI4_Lite_Slave#(addrwidth, datawidth)); AXI4_Lite_Slave_Rd#(addrwidth, datawidth) rd_slave <- mkAXI4_Lite_Slave_Rd(bufferSizeRead); AXI4_Lite_Slave_Wr#(addrwidth, datawidth) wr_slave <- mkAXI4_Lite_Slave_Wr(bufferSizeWrite); @@ -80,8 +78,8 @@ module mkAXI4_Lite_Slave#(Integer bufferSizeRead, Integer bufferSizeWrite)(AXI4_ interface rd = rd_slave.fab; interface wr = wr_slave.fab; endinterface - interface read = toGPClientS(rd_slave.request, rd_slave.response); - interface write = toGPClientS(wr_slave.request, wr_slave.response); + interface read = toGPClient(rd_slave.request, rd_slave.response); + interface write = toGPClient(wr_slave.request, wr_slave.response); endmodule /* diff --git a/src/AXI4_Slave.bsv b/src/AXI4_Slave.bsv index 3cc42f6..c30ec62 100644 --- a/src/AXI4_Slave.bsv +++ b/src/AXI4_Slave.bsv @@ -46,6 +46,7 @@ interface AXI4_Slave_Rd#(numeric type addrwidth, numeric type datawidth, numeric interface AXI4_Slave_Rd_Fab#(addrwidth, datawidth, id_width, user_width) fab; interface Get#(AXI4_Read_Rq#(addrwidth, id_width, user_width)) request; + method AXI4_Read_Rq#(addrwidth, id_width, user_width) snoop; interface Put#(AXI4_Read_Rs#(datawidth, id_width, user_width)) response; endinterface @@ -114,6 +115,8 @@ module mkAXI4_Slave_Rd#(Integer bufferIn, Integer bufferOut)(AXI4_Slave_Rd#(addr wruser <= out.first().user(); endrule + method snoop = in.first; + interface Get request = toGet(in); interface Put response = toPut(out); @@ -147,6 +150,7 @@ module mkAXI4_Slave_Rd_Dummy(AXI4_Slave_Rd#(addrwidth, datawidth, id_width, user endinterface interface response = ?; interface request = ?; + interface snoop = ?; endmodule /* diff --git a/src/ClientServerS.bs b/src/ClientServerS.bs deleted file mode 100644 index 49fd192..0000000 --- a/src/ClientServerS.bs +++ /dev/null @@ -1,369 +0,0 @@ ---@ Copyright (c) 2020 Bluespec, Inc. All rights reserved. ---@ ---@ Redistribution and use in source and binary forms, with or without ---@ modification, are permitted provided that the following conditions are ---@ met: ---@ ---@ 1. Redistributions of source code must retain the above copyright ---@ notice, this list of conditions and the following disclaimer. ---@ ---@ 2. Redistributions in binary form must reproduce the above copyright ---@ notice, this list of conditions and the following disclaimer in the ---@ documentation and/or other materials provided with the ---@ distribution. ---@ ---@ 3. Neither the name of the copyright holder nor the names of its ---@ contributors may be used to endorse or promote products derived ---@ from this software without specific prior written permission. ---@ ---@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ---@ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT ---@ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR ---@ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT ---@ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ---@ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT ---@ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, ---@ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY ---@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ---@ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ---@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -package ClientServerS( - ClientS(..), ServerS(..), ClientServerS(..), mkRequestResponseBufferS, - mkSizedRequestResponseBufferS, mkResponseBufferS, mkRequestBufferS, - mkRequestResponseBufferS1S, joinServerSsBC, joinServerSs, splitServerS, - fifosToServerS, fifosToClientS, fifosToClientServerS, - toGPClientS, toGPServerS) - where -import qualified Vector -import List -import FIFO -import Counter -import Connectable -import GetPut -import Clocks - ---@ \subsubsection{ClientServerS} ---@ \index{ClientServerS@\te{ClientServerS} (package)|textbf} ---@ ---@ The interfaces \te{ClientS} and \te{ServerS} can be used for ---@ modules that have a request-response type of interface ---@ (e.g. a RAM). ---@ The ServerS accepts requests and generates responses, and ---@ vice versa for the ClientS. ---@ There are no assumptions about how many (if any) responses ---@ a request will generate. - ---@ \index{ClientS@\te{ClientS} (interface)|textbf} ---@ \begin{libverbatim} ---@ interface ClientS #(type a, type b); ---@ interface Get#(a) request(); ---@ interface Put#(b) response(); ---@ endinterface: ClientS ---@ \end{libverbatim} -interface ClientS a b = - request :: Get a - response :: Put b - ---@ \index{ServerS@\te{ServerS} (interface)|textbf} ---@ \begin{libverbatim} ---@ interface ServerS #(type a, type b); ---@ interface Put#(a) request(); ---@ interface Get#(b) response(); ---@ endinterface: ServerS ---@ \end{libverbatim} -interface ServerS a b = - request :: Put a - response :: Get b - ---@ A \te{ClientS} can be connected to a \te{ServerS} ---@ and vice versa. ---@ \begin{libverbatim} ---@ instance Connectable #(ClientS#(a, b), ServerS#(a, b)); ---@ instance Connectable #(ServerS#(a, b), ClientS#(a, b)); ---@ \end{libverbatim} -instance Connectable (ClientS a b) (ServerS a b) - where - mkConnection :: (IsModule m c ) => ClientS a b -> ServerS a b -> m Empty - mkConnection c s = - module - rules - "ClientServerSRequest":when True - ==> action - x :: a <- c.request.get - s.request.put x - "ClientServerSResponse":when True - ==> action - x :: b <- s.response.get - c.response.put x - -instance Connectable (ServerS a b) (ClientS a b) - where - mkConnection s c = mkConnection c s - -instance (Bits a sa, Bits b sb) => ClockConv (ClientS a b) where - mkConverter :: (Prelude.IsModule m c) => Integer -> ClientS a b -> m (ClientS a b) - mkConverter d cluses = - module - req <- mkConverter d cluses.request - resp <- mkConverter d cluses.response - - interface - request = req - response = resp - -instance (Bits a sa, Bits b sb) => ClockConv (ServerS a b) where - mkConverter :: (Prelude.IsModule m c) => Integer -> ServerS a b -> m (ServerS a b) - mkConverter d cluses = - module - req <- mkConverter d cluses.request - resp <- mkConverter d cluses.response - - interface - request = req - response = resp - ---@ \lineup ---@ \begin{libverbatim} ---@ typedef Tuple2 #(ClientS#(a, b), ServerS#(a, b)) ClientServerS #(type a, type b); ---@ \end{libverbatim} -type ClientServerS a b = (ClientS a b, ServerS a b) - ---@ Create a buffer that just passes requests and responses between the ---@ two generated interfaces. ---@ \index{mkRequestResponseBufferS@\te{mkRequestResponseBufferS} (function)|textbf} ---@ \begin{libverbatim} ---@ module mkRequestResponseBufferS(ClientServerS#(a, b)) ---@ provisos (Bits#(a, sa), Bits#(b, sb)); ---@ \end{libverbatim} -mkRequestResponseBufferS :: (IsModule m c , Bits a sa, Bits b sb) => m (ClientServerS a b) -mkRequestResponseBufferS = - module - (qget, qput) :: (Get a, Put a) <- mkGetPut - (sget, sput) :: (Get b, Put b) <- mkGetPut - let c = interface ClientS - request = qget - response = sput - s = interface ServerS - request = qput - response = sget - interface (c, s) - ---@ Create a buffer that just passes requests and responses between the ---@ two generated interfaces. Uses half the flops of ---@ \te{mkRequestResponseBufferS}, but also has half the throughput. ---@ \index{mkRequestResponseBufferS1S@\te{mkRequestResponseBufferS1S} (function)|textbf} ---@ \begin{libverbatim} ---@ module mkRequestResponseBufferS1S(ClientServerS#(a, b)) ---@ provisos (Bits#(a, sa), Bits#(b, sb)); ---@ \end{libverbatim} -mkRequestResponseBufferS1S :: (IsModule m c , Bits a sa, Bits b sb) => m (ClientServerS a b) -mkRequestResponseBufferS1S = - module - (qget, qput) :: (Get a, Put a) <- mkGPFIFO1 - (sget, sput) :: (Get b, Put b) <- mkGPFIFO1 - let c = interface ClientS - request = qget - response = sput - s = interface ServerS - request = qput - response = sget - interface (c, s) - ---@ The same, using sized FIFOs. ---@ \index{mkSizedRequestResponseBufferS@\te{mkSizedRequestResponseBufferS} (function)|textbf} ---@ \begin{libverbatim} ---@ module mkSizedRequestResponseBufferS#(Integer sz)(ClientServerS#(a, b)) ---@ provisos (Bits#(a, sa), Bits#(b, sb)); ---@ \end{libverbatim} -mkSizedRequestResponseBufferS :: (IsModule m c , Bits a sa, Bits b sb) => Integer -> m (ClientServerS a b) -mkSizedRequestResponseBufferS sz = - module - (qget, qput) :: (Get a, Put a) <- mkGPSizedFIFO sz - (sget, sput) :: (Get b, Put b) <- mkGPSizedFIFO sz - let c = interface ClientS - request = qget - response = sput - s = interface ServerS - request = qput - response = sget - interface (c, s) - - ---@ Create a new ServerS with buffered requests. ---@ \index{mkRequestBufferS@\te{mkRequestBufferS} (function)|textbf} ---@ \begin{libverbatim} ---@ module mkRequestBufferS#(ServerS#(a, b) s)(ServerS#(a, b)) ---@ provisos (Bits#(a, sa)); ---@ \end{libverbatim} -mkRequestBufferS :: (IsModule m c , Bits a sa) => ServerS a b -> m (ServerS a b) -mkRequestBufferS s = - module - (qget, qput) :: (Get a, Put a) <- mkGetPut - rules - "mkRequestBufferS" : when True ==> - action - x :: a <- qget.get - s.request.put x - - interface -- ServerS - request = qput - response = s.response - - ---@ Create a new ServerS with buffered responses. ---@ \index{mkResponseBufferS@\te{mkResponseBufferS} (function)|textbf} ---@ \begin{libverbatim} ---@ module mkResponseBufferS#(ServerS#(a, b) s)(ServerS#(a, b)) ---@ provisos (Bits#(b, sb)); ---@ \end{libverbatim} -mkResponseBufferS :: (IsModule m c , Bits b sb) => ServerS a b -> m (ServerS a b) -mkResponseBufferS s = - module - (sget, sput) :: (Get b, Put b) <- mkGetPut - rules - "mkResponseBufferS" : when True ==> - action - x :: b <- s.response.get - sput.put x - - interface -- ServerS - request = s.request - response = sget - ---@ Join a list of ServerS's to one ServerS. All incoming requests are broadcasted ---@ all the ServerS's and all responses are merged. ---@ The function introduces a one cycle latency on the response. ---@ \index{joinServerSsSBC@\te{joinServerSsSBC} (function)|textbf} ---@ \begin{libverbatim} ---@ module joinServerSsSBC#(List#(ServerS#(a, b)) ifs)(ServerS#(a, b)) ---@ provisos (Bits#(b, sb)); ---@ \end{libverbatim} -joinServerSsBC :: (IsModule m c , Bits b sb) => List (ServerS a b) -> m (ServerS a b) -joinServerSsBC ifs = - module - (sget, sput) :: (Get b, Put b) <- mkGetPut - let rl s = - rules - "joinServerSsSBC": - when True ==> - action - x <- (s :: ServerS a b).response.get - sput.put x - addRules $ foldr (<+>) (rules {}) (map rl ifs) - interface -- ServerS - request = - interface Put - put req = joinActions (map (\ i -> (i :: ServerS a b).request.put req) ifs) - response = sget - ---@ Join a list of ServerSs to one ServerS. All incoming requests are sent to ---@ a selected subset of the ServerSs and all responses are merged. ---@ The selection is my a function that can transform the request type ---@ while testing if it should be sent on. ---@ The function introduces a one cycle latency on the response. ---@ \index{joinServerSs@\te{joinServerSs} (function)|textbf} ---@ \begin{libverbatim} ---@ module joinServerSs#( List#(Tuple2 #(a -> Maybe#(a'), ---@ ServerS#(a', b))) ifs)(ServerS#(a, b)) ---@ provisos (Bits#(b, sb)); ---@ \end{libverbatim} -joinServerSs :: (IsModule m c , Bits b sb) => List (a -> Maybe a', ServerS a' b) -> m (ServerS a b) -joinServerSs ifs = - module - (sget, sput) :: (Get b, Put b) <- mkGetPut - let rl (_, s) = - rules - "joinServerSs": - when True ==> - action - x <- (s :: ServerS a' b).response.get - sput.put x - send req (f, s) = - case f req of - Nothing -> noAction - Just req' -> (s :: ServerS a' b).request.put req' - addRules $ foldr (<+>) (rules {}) (map rl ifs) - interface -- ServerS - request = - interface Put - put req = joinActions (map (send req) ifs) - response = sget - -type MaxLat = 8 -- XXX This is just wrong ---@ Split a ServerS into a number of identical ServerSs. ---@ The integer argument specifies how many outstanding requests ---@ a returned ServerS may have. This number should be ---@ the latency of the argument ServerS to sustain full bandwidth. ---@ (A small number still works, as does a larger number.) ---@ \index{splitServerS@\te{splitServerS} (function)|textbf} ---@ \begin{libverbatim} ---@ module splitServerS#(Integer lat, ServerS#(a, b) serv)(Vector#(n, ServerS#(a, b))) ---@ provisos (Bits#(b, sb), Log#(n, ln)); ---@ \end{libverbatim} -splitServerS :: (IsModule m c , Bits b sb, Log n ln) => - Integer -> ServerS a b -> m (Vector.Vector n (ServerS a b)) -splitServerS lat serv = - module - tags :: FIFO (Bit ln) <- mkSizedFIFO lat - let mkServ :: (Bit ln) -> m (ServerS a b) - mkServ i = - module - out :: FIFO b <- mkSizedFIFO lat - cnt :: Counter MaxLat <- mkCounter (fromInteger lat) - rules - when tags.first == i - ==> action - tags.deq - x <- serv.response.get - out.enq x - interface ServerS - request = - interface Put - put req = - action - serv.request.put req - tags.enq i - cnt.down - when cnt.value > 0 - response = - interface Get - get = do - out.deq - cnt.up - return out.first - Vector.mapM (\ x -> mkServ (fromInteger x)) Vector.genList - ---@ fifosToServerS - -fifosToServerS :: FIFO rq -> FIFO rs -> ServerS rq rs -fifosToServerS rqf rsf = - interface ServerS - request = fifoToPut rqf - response = fifoToGet rsf - -fifosToClientS :: FIFO rq -> FIFO rs -> ClientS rq rs -fifosToClientS rqf rsf = - interface ClientS - request = fifoToGet rqf - response = fifoToPut rsf - -fifosToClientServerS :: FIFO rq -> FIFO rs -> ClientServerS rq rs -fifosToClientServerS rqf rsf = (fifosToClientS rqf rsf, fifosToServerS rqf rsf) - --- toGPClientS, toGPServerS - -toGPClientS :: (ToGet rq_ifc rq, ToPut rs_ifc rs) => - rq_ifc -> rs_ifc -> ClientS rq rs -toGPClientS rqi rsi = - interface ClientS - request = toGet rqi - response = toPut rsi - -toGPServerS :: (ToPut rq_ifc rq, ToGet rs_ifc rs) => - rq_ifc -> rs_ifc -> ServerS rq rs -toGPServerS rqi rsi = - interface ServerS - request = toPut rqi - response = toGet rsi - From d8baabb7c8a5d063ddbfaae0d9b1f0eb29074ddd Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Sun, 13 Oct 2024 16:49:39 +0200 Subject: [PATCH 4/6] Fix exports --- src/BlueAXI.bsv | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/BlueAXI.bsv b/src/BlueAXI.bsv index 47a3a1b..a75f952 100644 --- a/src/BlueAXI.bsv +++ b/src/BlueAXI.bsv @@ -17,10 +17,7 @@ import AXI3 :: *; export AXI4_Lite :: *; export GenericAxi4LiteSlave :: *; -export AXI4_Types :: *; -export AXI4_Master :: *; -export AXI4_Slave :: *; -export AXI4_Stream :: *; +export AXI4 :: *; export GenericAxi4Master :: *; export BlueAXITests :: *; @@ -28,8 +25,6 @@ export BlueAXIBRAM :: *; export AXI4_Monitor :: *; -export AXI3_Types :: *; -export AXI3_Master :: *; -export AXI3_Slave :: *; +export AXI3 :: *; endpackage \ No newline at end of file From 0b2c23df9b678ca865e66feb719374d90c43a0bb Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Sun, 12 Jan 2025 23:28:51 +0100 Subject: [PATCH 5/6] Add access to separate masters --- src/AXI4_Lite.bsv | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/AXI4_Lite.bsv b/src/AXI4_Lite.bsv index ff86c45..1015c73 100644 --- a/src/AXI4_Lite.bsv +++ b/src/AXI4_Lite.bsv @@ -32,19 +32,23 @@ interface AXI4_Lite_Master#(numeric type addrwidth, numeric type datawidth); interface AXI4_Lite_Master_Fab#(addrwidth, datawidth) fab; interface AXI4_Lite_Read_Server#(addrwidth, datawidth) read; interface AXI4_Lite_Write_Server#(addrwidth, datawidth) write; + interface AXI4_Lite_Master_Rd#(addrwidth, datawidth) rd_master; + interface AXI4_Lite_Master_Wr#(addrwidth, datawidth) wr_master; endinterface module mkAXI4_Lite_Master#(Integer bufferSizeRead, Integer bufferSizeWrite)(AXI4_Lite_Master#(addrwidth, datawidth)); - AXI4_Lite_Master_Rd#(addrwidth, datawidth) rd_master <- mkAXI4_Lite_Master_Rd(bufferSizeRead); - AXI4_Lite_Master_Wr#(addrwidth, datawidth) wr_master <- mkAXI4_Lite_Master_Wr(bufferSizeWrite); + AXI4_Lite_Master_Rd#(addrwidth, datawidth) rd_master_i <- mkAXI4_Lite_Master_Rd(bufferSizeRead); + AXI4_Lite_Master_Wr#(addrwidth, datawidth) wr_master_i <- mkAXI4_Lite_Master_Wr(bufferSizeWrite); interface AXI4_Lite_Master_Fab fab; - interface rd = rd_master.fab; - interface wr = wr_master.fab; + interface rd = rd_master_i.fab; + interface wr = wr_master_i.fab; endinterface - interface read = toGPServer(rd_master.request, rd_master.response); - interface write = toGPServer(wr_master.request, wr_master.response); + interface read = toGPServer(rd_master_i.request, rd_master_i.response); + interface write = toGPServer(wr_master_i.request, wr_master_i.response); + interface rd_master = rd_master_i; + interface wr_master = wr_master_i; endmodule /* From 84da1f62b44d2999ad48c6e9a6e560371aebc61b Mon Sep 17 00:00:00 2001 From: Johannes Wirth Date: Wed, 15 Jan 2025 13:21:52 +0100 Subject: [PATCH 6/6] Add regfile handler for generic axilite slave --- src/GenericAxi4LiteSlave.bsv | 45 ++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/src/GenericAxi4LiteSlave.bsv b/src/GenericAxi4LiteSlave.bsv index 1aa9ac7..59fb6bf 100644 --- a/src/GenericAxi4LiteSlave.bsv +++ b/src/GenericAxi4LiteSlave.bsv @@ -7,10 +7,55 @@ import Vector :: *; import List :: *; import BUtils :: *; import BRAM :: *; +import RegFile :: *; import AXI4_Lite_Types :: *; import AXI4_Lite_Slave :: *; +function List#(RegisterOperator#(axiAddrWidth, axiDataWidth)) regfileHandler(Integer start, Integer elements, RegFile#(a, d) r, List#(RegisterOperator#(axiAddrWidth, axiDataWidth)) op) + provisos( + Bits#(a, a_sz), + Bits#(d, axiDataWidth), + Div#(axiDataWidth, 8, n), + Mul#(TDiv#(axiDataWidth, 8), 8, axiDataWidth) + ); + let length = elements * valueOf(n); + op = List::cons(tagged ReadRange ReadOperationRange { index_min: fromInteger(start), + index_max: fromInteger((start + length) - 1), + fun: regFileReader(start, r)}, op); + + op = List::cons(tagged WriteRange WriteOperationRange { index_min: fromInteger(start), + index_max: fromInteger((start + length) - 1), + fun: regFileWriter(start, r) }, op); + return op; +endfunction + +function ActionValue#(Bit#(data_width)) regFileReader(Integer start, RegFile#(a,d) r, Bit#(addr_w) addr, AXI4_Lite_Prot p) + provisos(Bits#(a, a_sz),Bits#(d,data_width)); + actionvalue + addr = addr - fromInteger(start); + Bit#(a_sz) regNum = zExtend(addr >> valueOf(TLog#(TDiv#(data_width, 8)))); + return pack(r.sub(unpack(regNum))); + endactionvalue +endfunction + +function Action regFileWriter(Integer start, RegFile#(a,d) r, Bit#(addr_w) addr, + Bit#(data_width) d, Bit#(TDiv#(data_width, 8)) s, AXI4_Lite_Prot p) + provisos(Bits#(a, a_sz),Bits#(d,data_width),Mul#(TDiv#(data_width, 8), 8, data_width)); + action + addr = addr - fromInteger(start); + Bit#(a_sz) regNum = zExtend(addr >> valueOf(TLog#(TDiv#(data_width, 8)))); + Vector#(TDiv#(data_width, 8), Bit#(8)) tr = cExtend(r.sub(unpack(regNum))); + Vector#(TDiv#(data_width, 8), Bit#(8)) td = unpack(d); + for(Integer i = 0; i < valueOf(TDiv#(data_width, 8)); i = i + 1) begin + if(unpack(s[i])) begin + tr[i] = td[i]; + end + end + r.upd(unpack(regNum), unpack(pack(tr))); + endaction +endfunction + function List#(RegisterOperator#(axiAddrWidth, axiDataWidth)) bramHandler(Integer start, Integer elements, BRAMServerBE#(a, t, n) r, List#(RegisterOperator#(axiAddrWidth, axiDataWidth)) op) provisos(Bits#(a, a_sz), Bits#(t, axiDataWidth),