2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * 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.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 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.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 //1. Remove all userid and corresponding registers i.e. rg_memory_user and rg_peripheral_user.
16 package tb_DMA_AXI_Memory;
18 import Semi_FIFOF :: *;
19 import AXI4_Types :: *;
20 import AXI4_Fabric :: *;
21 import Connectable :: *;
22 import ConfigReg :: *;
26 `include "instance_defines.bsv"
27 typedef 2 Num_Masters;
31 typedef enum{Send_req,Get_resp} Mem_state deriving(Bits,Eq);
32 //check with table in pdf
34 function Bit#(8) write_strobe_generation(Bit#(3) transfer_size);
37 else if(transfer_size==1)
39 else if(transfer_size==2)
46 function Tuple2 #(Bool, Bit#(TLog#(Num_Slaves))) fn_addr_to_slave_num (Bit #(`PADDR) addr);
48 return tuple2(True,0); //DMA config registers
50 return tuple2(True,2); //Peripherals
52 return tuple2(True,1); //Memory
56 //(*mutually_exclusive="get_read_response,get_write_response"*)
57 module mkTb_DMA_AXI_Memory(Empty);
60 Clock curr_clk<-exposeCurrentClock;
61 Reset curr_reset<-exposeCurrentReset;
62 MakeResetIfc myrst1 <-mkReset(0,False,curr_clk);
63 Reset final_reset<-mkResetEither(myrst1.new_rst,curr_reset);
66 DmaC#(7,12) dma <-mkDMA();//check parameter as DmaC-data type of mkDMA input takes two inputs
67 AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) proc_xactor <- mkAXI4_Master_Xactor();
68 AXI4_Slave_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) slave_memory_xactor <- mkAXI4_Slave_Xactor();
69 AXI4_Slave_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) slave_peripheral_xactor <- mkAXI4_Slave_Xactor();
71 //master testbench to slave dma connection
72 //mkConnection (m_xactor.axi_side, dma.cfg);
74 //slave testbench to master dma connection
75 //mkConnection (dma.mmu,s_xactor.axi_side);
80 AXI4_Fabric_IFC #(Num_Masters, Num_Slaves, `PADDR, `Reg_width,`USERSPACE)
81 fabric <- mkAXI4_Fabric(fn_addr_to_slave_num);
83 // Connect traffic generators to fabric
84 mkConnection (proc_xactor.axi_side, fabric.v_from_masters [0]);
85 mkConnection (dma.mmu, fabric.v_from_masters [1]);
87 // Connect fabric to memory slaves
88 mkConnection(fabric.v_to_slaves[0],dma.cfg);
89 mkConnection(fabric.v_to_slaves[1],slave_memory_xactor.axi_side);
90 mkConnection(fabric.v_to_slaves[2],slave_peripheral_xactor.axi_side);
92 Reg#(Bit#(6)) index<-mkConfigReg(0); // states 0..7
93 Reg#(Bool) rg_read_flag<-mkConfigReg(False);
94 Reg#(Bool) rg_write_flag<-mkConfigReg(False);
95 RegFile#(Bit#(6),Bit#(136)) input_instructions <-mkRegFileLoad("trial.hex",0,`Max_index);
96 Reg#(Bit#(32)) rg_count <-mkReg(0);
97 //Reg#(Maybe#(AXI4_Rd_Data#(`Reg_width, `USERSPACE))) rg_slave_read_response <- mkReg(tagged Invalid);
99 Reg#(Mem_state) rg_memory_state <-mkDReg(Send_req);
100 Reg#(Bit#(8)) rg_memory_readburst_counter<-mkReg(0);
101 Reg#(Bit#(8)) rg_memory_readburst_value<-mkReg(0);
102 Reg#(Bit#(8)) rg_memory_writeburst_counter<-mkReg(0);
103 Reg#(Bit#(`USERSPACE)) rg_memory_user<-mkReg(0);
104 Reg#(Bit#(4)) rg_memory_id<-mkReg(0);
105 Reg#(Bit#(64)) rg_memory_address<-mkReg(0);
106 Reg#(Bit#(3)) rg_memory_transfer_size<-mkReg(0);
107 Reg#(Bit#(`Reg_width)) rg_memory_data <-mkReg(0);
109 Reg#(Mem_state) rg_peripheral_state <-mkDReg(Send_req);
110 Reg#(Bit#(8)) rg_peripheral_readburst_counter<-mkReg(0);
111 Reg#(Bit#(8)) rg_peripheral_readburst_value<-mkReg(0);
112 Reg#(Bit#(8)) rg_peripheral_writeburst_counter<-mkReg(0);
113 Reg#(Bit#(`USERSPACE)) rg_peripheral_user<-mkReg(0);
114 Reg#(Bit#(4)) rg_peripheral_id<-mkReg(0);
115 Reg#(Bit#(64)) rg_peripheral_address<-mkReg(0);
116 Reg#(Bit#(3)) rg_peripheral_transfer_size<-mkReg(0);
117 Reg#(Bit#(`Reg_width)) rg_peripheral_data <-mkReg(0);
120 rg_count<= rg_count + 1;
122 $display($time,"\tCount: %d",rg_count);
127 rule proc_start_read(!rg_read_flag && index<=`Max_index && input_instructions.sub(truncate(index))[64]==0); //read operation
128 let x = input_instructions.sub(truncate(index));
133 $display($time,"\tTBMaster_Processor: Sending Read Request to addr %h",addr);
134 let read_request = AXI4_Rd_Addr {araddr: zeroExtend(addr), arprot: 0, aruser: 0, arsize: zeroExtend(size), arlen: 0 , arburst: 1, // arburst: 00-FIXED 01-INCR 10-WRAP
135 arlock: 0, arcache: 0, arqos: 0,
136 arregion: 0, arid: 0 };
137 proc_xactor.i_rd_addr.enq(read_request);
138 //x[15:0]=fn_decr_cndtr(x[15:0],2,x[50:48]);//CHECK correct this code USE FUNCTION
142 rule proc_start_write(!rg_write_flag && index<=`Max_index && input_instructions.sub(truncate(index))[64]==1); //write operation
143 let x = input_instructions.sub(truncate(index));
148 $display($time,"\tTBMaster_Processor: Sending Write Request");
149 let aw = AXI4_Wr_Addr { awaddr: zeroExtend(addr), awprot:0, awuser:0, awlen: 0, awsize: zeroExtend(size), awburst: 1,
150 awlock: 0, awcache: 0, awqos: 0,
151 awregion: 0, awid: 0 };
152 let w = AXI4_Wr_Data {wdata: zeroExtend(wdata), wstrb: 0, wlast:True, wid: 0};
153 proc_xactor.i_wr_addr.enq(aw);
154 proc_xactor.i_wr_data.enq(w);
155 rg_write_flag<= True;
158 rule get_read_response1(rg_read_flag);
159 let response <- pop_o (proc_xactor.o_rd_data);
160 $display($time,"\tTBMaster_Processor: Received read response with data %h",response.rdata);
162 rg_read_flag<= False;
165 rule get_write_response1(rg_write_flag);
166 let response <- pop_o (proc_xactor.o_wr_resp);
167 $display($time,"\tTBMaster_Processor: Received write response");
169 rg_write_flag<= False;
172 ///////////////// ****************** SLAVE MEMORY **************//////////////////////
173 /////// SLAVE MEMORY READ ////////
174 rule rl_dummy_slave_memory_handle_read_request;
175 let ar<- pop_o(slave_memory_xactor.o_rd_addr);
176 Bit#(TSub#(mem_size,2)) index_address=(ar.araddr-fromInteger(valueOf(`Base_addr)))[valueOf(`Addr_space)-1:`byte_offset+1];
177 rg_memory_address<=ar.araddr;
178 rg_memory_transfer_size<=ar.arsize;
179 rg_memory_readburst_value<=ar.arlen;
180 rg_memory_user<=ar.aruser;
181 rg_memory_id<= ar.arid;
182 rg_memory_data<=zeroExtend({16'hbabe,rg_count[15:0]});
183 rg_memory_state<=Get_resp;
184 $display($time,"\tTbSlave_Memory: Recieved Read Request for Address: %h for id: %d",ar.araddr, ar.aruser);
187 rule rl_dummy_slave_memory_handle_read_response(rg_memory_state==Get_resp);
189 Bit#(`Reg_width) data0 = {dmemMSB.a.read(),dmemLSB.a.read()};
191 Bit#(`Reg_width) data0 = dmemLSB.a.read();
193 Bit#(`Reg_width) data0= rg_memory_data;
194 AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data { rresp: AXI4_OKAY, rdata: data0 ,
195 rlast: rg_memory_readburst_counter==rg_memory_readburst_value,
196 ruser: rg_memory_user, rid: rg_memory_id};
197 if(rg_memory_transfer_size==2)begin // 32 bit
198 if(rg_memory_address[`byte_offset:0]==0)
199 r.rdata={data0[31:0],data0[31:0]};
201 r.rdata={data0[63:32],data0[63:32]};
203 else if (rg_memory_transfer_size=='d1)begin // half_word
204 if(rg_memory_address[`byte_offset:0] ==0)
205 r.rdata = {data0[15:0],data0[15:0],data0[15:0],data0[15:0]};
206 else if(rg_memory_address[`byte_offset:0] ==2)
207 r.rdata = {data0[31:16],data0[31:16],data0[31:16],data0[31:16]};
209 else if(rg_memory_address[`byte_offset:0] ==4)
210 r.rdata = {data0[47:32],data0[47:32],data0[47:32],data0[47:32]};
211 else if(rg_memory_address[`byte_offset:0] ==6)
212 r.rdata = {data0[63:48],data0[63:48],data0[63:48],data0[63:48]};
215 else if (rg_memory_transfer_size=='d0) begin// one byte
216 if(rg_memory_address[`byte_offset:0] ==0)
217 r.rdata = {data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0]};
218 else if(rg_memory_address[`byte_offset:0] ==1)
219 r.rdata = {data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8]};
220 else if(rg_memory_address[`byte_offset:0] ==2)
221 r.rdata = {data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16]};
222 else if(rg_memory_address[`byte_offset:0] ==3)
223 r.rdata = {data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24]};
225 else if(rg_memory_address[`byte_offset:0] ==4)
226 r.rdata = {data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32]};
227 else if(rg_memory_address[`byte_offset:0] ==5)
228 r.rdata = {data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40]};
229 else if(rg_memory_address[`byte_offset:0] ==6)
230 r.rdata = {data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48]};
231 else if(rg_memory_address[`byte_offset:0] ==7)
232 r.rdata = {data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56]};
235 slave_memory_xactor.i_rd_data.enq(r);
236 if(rg_memory_readburst_counter==rg_memory_readburst_value)
237 rg_memory_readburst_counter<=0;
239 rg_memory_readburst_counter<=rg_memory_readburst_counter+1;
240 $display($time,"\tTBSlave: Responding Read Request with Data: %8h BurstCounter: %d BurstValue: %d for id: %d",r.rdata,rg_memory_readburst_counter,rg_memory_readburst_value,rg_memory_user);
243 /////// SLAVE MEMORY WRITE ////////
244 rule rl_wr_respond_memory;
245 // Get the wr request
246 let aw <- pop_o (slave_memory_xactor.o_wr_addr);
247 let w <- pop_o (slave_memory_xactor.o_wr_data);
248 //Bit#(TSub#(mem_size,2)) index_address=(aw.awaddr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:`byte_offset+1];
249 //dmemLSB.b.put(w.wstrb[3:0],index_address,truncate(w.wdata));
250 //`ifdef RV64 dmmMSB.b.put(w.wstrb[7:4],index_address,truncateLSB(w.wdata)); `endif
251 let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: aw.awuser, bid:aw.awid};
252 if(rg_memory_writeburst_counter==aw.awlen)begin
253 rg_memory_writeburst_counter<=0;
254 slave_memory_xactor.i_wr_resp.enq (b);
257 rg_memory_writeburst_counter<=rg_memory_writeburst_counter+1;
258 $display($time,"\tTBSlave_Memory: Recieved Write Request for Address: %h data: %h strb: %b awlen: %d rg_memory_writeburst_counter: %d",aw.awaddr,w.wdata,w.wstrb,aw.awlen,rg_memory_writeburst_counter);
264 ///////////////// ****************** SLAVE PERIPHERAL **************//////////////////////
265 /////// SLAVE PERIPHERAL READ ////////
266 rule rl_dummy_slave_peripheral_handle_read_request;
267 //let ar<- pop_o(slave_peripheral_xactor.o_rd_addr);
268 let ar<- pop_o(slave_peripheral_xactor.o_rd_addr);
269 Bit#(TSub#(mem_size,2)) index_address=(ar.araddr-fromInteger(valueOf(`Base_addr)))[valueOf(`Addr_space)-1:`byte_offset+1];
270 rg_peripheral_address<=ar.araddr;
271 rg_peripheral_transfer_size<=ar.arsize;
272 rg_peripheral_readburst_value<=ar.arlen;
273 rg_peripheral_user<=ar.aruser;
274 rg_peripheral_id<= ar.arid;
275 rg_peripheral_data<=zeroExtend({16'hbabe,rg_count[15:0]});
276 rg_peripheral_state<=Get_resp;
277 $display($time,"\tTbSlave_peripheral: Recieved Read Request for Address: %h for id: %d",ar.araddr, ar.aruser);
280 rule rl_dummy_slave_peripheral_handle_read_response(rg_peripheral_state==Get_resp);
282 Bit#(`Reg_width) data0 = {dmemMSB.a.read(),dmemLSB.a.read()};
284 Bit#(`Reg_width) data0 = dmemLSB.a.read();
286 Bit#(`Reg_width) data0= rg_peripheral_data;
287 AXI4_Rd_Data#(`Reg_width,`USERSPACE) r = AXI4_Rd_Data { rresp: AXI4_OKAY, rdata: data0 ,
288 rlast: rg_peripheral_readburst_counter==rg_peripheral_readburst_value,
289 ruser: rg_peripheral_user, rid: rg_peripheral_id};
290 if(rg_peripheral_transfer_size==2)begin // 32 bit
291 if(rg_peripheral_address[`byte_offset:0]==0)
292 r.rdata={data0[31:0],data0[31:0]};
294 r.rdata={data0[63:32],data0[63:32]};
296 else if (rg_peripheral_transfer_size=='d1)begin // half_word
297 if(rg_peripheral_address[`byte_offset:0] ==0)
298 r.rdata = {data0[15:0],data0[15:0],data0[15:0],data0[15:0]};
299 else if(rg_peripheral_address[`byte_offset:0] ==2)
300 r.rdata = {data0[31:16],data0[31:16],data0[31:16],data0[31:16]};
302 else if(rg_peripheral_address[`byte_offset:0] ==4)
303 r.rdata = {data0[47:32],data0[47:32],data0[47:32],data0[47:32]};
304 else if(rg_peripheral_address[`byte_offset:0] ==6)
305 r.rdata = {data0[63:48],data0[63:48],data0[63:48],data0[63:48]};
308 else if (rg_peripheral_transfer_size=='d0) begin// one byte
309 if(rg_peripheral_address[`byte_offset:0] ==0)
310 r.rdata = {data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0],data0[7:0]};
311 else if(rg_peripheral_address[`byte_offset:0] ==1)
312 r.rdata = {data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8],data0[15:8]};
313 else if(rg_peripheral_address[`byte_offset:0] ==2)
314 r.rdata = {data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16],data0[23:16]};
315 else if(rg_peripheral_address[`byte_offset:0] ==3)
316 r.rdata = {data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24],data0[31:24]};
318 else if(rg_peripheral_address[`byte_offset:0] ==4)
319 r.rdata = {data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32],data0[39:32]};
320 else if(rg_peripheral_address[`byte_offset:0] ==5)
321 r.rdata = {data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40],data0[47:40]};
322 else if(rg_peripheral_address[`byte_offset:0] ==6)
323 r.rdata = {data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48],data0[55:48]};
324 else if(rg_peripheral_address[`byte_offset:0] ==7)
325 r.rdata = {data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56],data0[63:56]};
328 slave_peripheral_xactor.i_rd_data.enq(r);
329 if(rg_peripheral_readburst_counter==rg_peripheral_readburst_value)
330 rg_peripheral_readburst_counter<=0;
332 rg_peripheral_readburst_counter<=rg_peripheral_readburst_counter+1;
333 $display($time,"\tTBSlave_Peripheral: Responding Read Request with Data: %8h BurstCounter: %d BurstValue: %d for id: %d",r.rdata,rg_peripheral_readburst_counter,rg_peripheral_readburst_value,rg_peripheral_user);
337 /////// SLAVE PERIPHERAL WRITE ////////
338 rule rl_wr_respond_peripheral;
339 // Get the wr request
340 let aw <- pop_o (slave_peripheral_xactor.o_wr_addr);
341 let w <- pop_o (slave_peripheral_xactor.o_wr_data);
342 //Bit#(TSub#(mem_size,2)) index_address=(aw.awaddr-fromInteger(valueOf(base_address)))[valueOf(mem_size)-1:`byte_offset+1];
343 //dmemLSB.b.put(w.wstrb[3:0],index_address,truncate(w.wdata));
344 //`ifdef RV64 dmmMSB.b.put(w.wstrb[7:4],index_address,truncateLSB(w.wdata)); `endif
345 let b = AXI4_Wr_Resp {bresp: AXI4_OKAY, buser: aw.awuser, bid:aw.awid};
346 if(rg_peripheral_writeburst_counter==aw.awlen)begin
347 rg_peripheral_writeburst_counter<=0;
348 slave_peripheral_xactor.i_wr_resp.enq (b);
351 rg_peripheral_writeburst_counter<=rg_peripheral_writeburst_counter+1;
352 $display($time,"\tTBSlave_Peripheral: Recieved Write Request for Address: %h data: %h strb: %b awlen: %d rg_peripheral_writeburst_counter: %d",aw.awaddr,w.wdata,w.wstrb,aw.awlen,rg_peripheral_writeburst_counter);
355 ///////////////////////// SEND INTERRUPT FROM PERIPHERAL //////////////////////////////
356 rule rl_send_interrupt;
357 dma.interrupt_from_peripherals('hA01);