d0a085f04194cb8cdbc97ee8205b9ea912437d8d
[shakti-peripherals.git] / src / peripherals / dma / tb_DMA.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
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.
10
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package tb_DMA;
15 import DMA::*;
16 import Memory_AXI4 ::*;
17 import Semi_FIFOF :: *;
18 import AXI4_Types :: *;
19 import AXI4_Fabric :: *;
20 import Connectable :: *;
21 import ConfigReg :: *;
22 import RegFile::*;
23 import Clocks :: * ;
24 import DReg ::*;
25 import defined_types::*;
26 `include "defined_parameters.bsv"
27
28
29 `define Num_DMA_Channels 7
30 `define Num_Peripherals 12
31 `define Num_Masters 2
32 `define Num_Slaves TAdd#(`Num_Peripherals,2)
33
34 `define DMA_cfg_addr_start 64'h00000000
35 `define DMA_cfg_addr_end 64'h000000FF
36 `define Peripheral1_addr_start 64'h00001000
37 `define Peripheral1_addr_end 64'h00001FFF
38 `define Peripheral2_addr_start 64'h00002000
39 `define Peripheral2_addr_end 64'h00002FFF
40 `define Peripheral3_addr_start 64'h00003000
41 `define Peripheral3_addr_end 64'h00003FFF
42 `define MainMemory_addr_start 64'h80000000
43 `define MainMemory_addr_end 64'hFFFFFFFF
44
45 typedef enum{Send_req,Get_resp} Mem_state deriving(Bits,Eq);
46
47 /*function Tuple2#(t , Bit#(`Addr_space)) fn_slave_addr_range(Integer i) provisos(Literal#(t));
48 case (i) matches
49 0: return tuple2(`DMA_cfg_addr_start, `DMA_cfg_addr_end);
50 1: return tuple2(`MainMemory_addr_start, `MainMemory_addr_end);
51 2: return tuple2(`Peripheral1_addr_start, `Peripheral1_addr_end);
52 default: return tuple2(0,0);
53 endcase
54 endfunction*/
55
56 function Tuple2 #(Bool, Bit#(TLog#(`Num_Slaves))) fn_addr_to_slave_num (Bit #(`PADDR) addr);
57 if(addr>=`MainMemory_addr_start && addr<=`MainMemory_addr_end)
58 return tuple2(True,1); //Memory
59 else if(addr>=`Peripheral1_addr_start && addr<=`Peripheral1_addr_end)
60 return tuple2(True,2); //Peripherals
61 else if(addr>=`Peripheral2_addr_start && addr<=`Peripheral2_addr_end)
62 return tuple2(True,3); //Peripherals
63 else if(addr>=`Peripheral3_addr_start && addr<=`Peripheral3_addr_end)
64 return tuple2(True,4); //Peripherals
65 else if(addr>=`DMA_cfg_addr_start && addr<= `DMA_cfg_addr_end)
66 return tuple2(True,0); //DMA config registers
67 else
68 return tuple2(False,0);
69 endfunction
70
71 (*synthesize*)
72 //(*mutually_exclusive= "get_read_response,get_write_response"*)
73 module mkTb_DMA(Empty);
74 DmaC#(`Num_DMA_Channels, `Num_Peripherals) dma <-mkDMA();//check parameter as DmaC-data type of mkDMA input takes two inputs
75 AXI4_Master_Xactor_IFC #(`PADDR,`Reg_width,`USERSPACE) processor <- mkAXI4_Master_Xactor();
76 Memory_IFC#(`MainMemory_addr_start,`Addr_space) main_memory <- mkMemory("MainMemory_MSB","MainMemory_LSB","MainMemory");
77
78 Memory_IFC#(`Peripheral1_addr_start,`Addr_space) peripheral1 <- mkMemory("Peripheral1_MSB", "Peripheral1_LSB", "Peripheral[1]");
79 Memory_IFC#(`Peripheral2_addr_start,`Addr_space) peripheral2 <- mkMemory("Peripheral2_MSB", "Peripheral2_LSB", "Peripheral[2]");
80 Memory_IFC#(`Peripheral3_addr_start,`Addr_space) peripheral3 <- mkMemory("Peripheral3_MSB", "Peripheral3_LSB", "Peripheral[2]");
81 /*for(Integer i=0; i<`Num_Peripherals; i=i+1) begin
82 let lv_base_addr= fn_slave_addr_range(i).tpl_1;
83 peripheral[i] <- mkMemory("Peripheral" +integerToString(i)+ "_MSB", "Peripheral" +integerToString(i)+ "_LSB", "Peripheral[" +integerToString(i)+ "]");
84 end*/
85
86 // Fabric
87 AXI4_Fabric_IFC #(`Num_Masters, `Num_Slaves, `PADDR, `Reg_width,`USERSPACE)
88 fabric <- mkAXI4_Fabric(fn_addr_to_slave_num());
89
90 //Connect the masters to fabric
91 mkConnection (processor.axi_side, fabric.v_from_masters [0]); //MASTER0: Processor
92 mkConnection (dma.mmu, fabric.v_from_masters [1]); //MASTER1: DMA's MMU
93
94 mkConnection(fabric.v_to_slaves[0],dma.cfg); //SLAVE1: Main Memory
95 mkConnection(fabric.v_to_slaves[1],main_memory.axi_slave); //SLAVE1: Main Memory
96
97 mkConnection(fabric.v_to_slaves[2],peripheral1.axi_slave); //SLAVE2: Peripheral1
98 mkConnection(fabric.v_to_slaves[3],peripheral2.axi_slave); //SLAVE2: Peripheral1
99 mkConnection(fabric.v_to_slaves[4],peripheral3.axi_slave); //SLAVE2: Peripheral1
100 /*for(Integer i=0; i<`Num_Peripherals; i=i+1)
101 mkConnection(fabric.v_to_slaves[i+2],peripheral[i].axi_slave); //SLAVE2 onwards: Various Peripherals*/
102
103 //Registers for reading instructions from Dummy processor
104 Reg#(Bit#(6)) index<-mkConfigReg(0); // states 0..7
105 Reg#(Bool) rg_read_flag<-mkConfigReg(False);
106 Reg#(Bool) rg_write_flag<-mkConfigReg(False);
107 RegFile#(Bit#(6),Bit#(136)) input_instructions <-mkRegFileFullLoad("trial.hex");
108 Reg#(Bit#(32)) rg_count <-mkReg(0);
109 Reg#(Bool) rg_done <-mkReg(False);
110
111 rule rl_inc_count;
112 rg_count<= rg_count + 1;
113 $display("\n");
114 $display($time,"\tCount: %d",rg_count);
115 if(rg_count==500)
116 $finish(0);
117 endrule
118
119 rule proc_start_read(!rg_read_flag && !rg_done && input_instructions.sub(truncate(index))[65:64]==2'b00); //read operation
120 let x = input_instructions.sub(truncate(index));
121 let addr= x[31:0];
122 let wdata= x[63:32];
123 let stop= x[65];
124 let size= 2'd2;
125 $display($time,"\tTBMaster Processor: Sending Read Request to addr %h",addr);
126 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
127 arlock: 0, arcache: 0, arqos: 0,
128 arregion: 0, arid: 0 };
129 processor.i_rd_addr.enq(read_request);
130 //x[15:0]=fn_decr_cndtr(x[15:0],2,x[50:48]);//CHECK correct this code USE FUNCTION
131 rg_read_flag<= True;
132 rg_done<= unpack(stop);
133 endrule
134
135 rule proc_start_write(!rg_write_flag && !rg_done && input_instructions.sub(truncate(index))[65:64]==2'b01); //write operation
136 let x = input_instructions.sub(truncate(index));
137 let addr= x[31:0];
138 let wdata= x[63:32];
139 let stop= x[65];
140 let size= 2'd2;
141 $display($time,"\tTBMaster Processor: Sending Write Request");
142 let aw = AXI4_Wr_Addr { awaddr: zeroExtend(addr), awprot:0, awuser:0, awlen: 0, awsize: zeroExtend(size), awburst: 1,
143 awlock: 0, awcache: 0, awqos: 0,
144 awregion: 0, awid: 0 };
145 Bit#(8) lv_strb=0;
146 Bit#(64) lv_wdata=0;
147 if(addr[2:0]=='b000) begin
148 lv_strb= 'h0F;
149 lv_wdata= zeroExtend(wdata);
150 end
151 else if(addr[2:0]=='b100) begin
152 lv_strb= 'hF0;
153 lv_wdata= {wdata,32'd0};
154 end
155 else begin
156 $display($time,"ERROR: Write to a wrong address");
157 end
158 let w = AXI4_Wr_Data {wdata: lv_wdata, wstrb: lv_strb, wlast:True, wid: 0}; //TODO generate wstrb to be 2'b10 for all regs except cmar and cpar
159 processor.i_wr_addr.enq(aw);
160 processor.i_wr_data.enq(w);
161 rg_write_flag<= True;
162 rg_done<= unpack(stop);
163 index<= index+1;
164 endrule
165
166 rule get_read_response1(rg_read_flag);
167 let response <- pop_o (processor.o_rd_data);
168 $display($time,"\tTBMaster Processor: Received read response with data %h",response.rdata);
169 rg_read_flag<= False;
170 endrule
171
172 rule get_write_response1(rg_write_flag);
173 let response <- pop_o (processor.o_wr_resp);
174 $display($time,"\tTBMaster Processor: Received write response");
175 rg_write_flag<= False;
176 endrule
177
178 ///////////////////////// SEND INTERRUPT FROM PERIPHERAL //////////////////////////////
179 rule rl_send_interrupt;
180 dma.interrupt_from_peripherals('d-1);
181 endrule
182
183
184 rule rl_read_interrupt_status(rg_count>20 && rg_count<60);
185 let size= 2'd2;
186 $display($time,"\tTBMaster Processor: Sending Read Request to addr 0 to read interrupt status...");
187 let read_request = AXI4_Rd_Addr {araddr: 0, arprot: 0, aruser: 0, arsize: zeroExtend(size), arlen: 0 , arburst: 1, // arburst: 00-FIXED 01-INCR 10-WRAP
188 arlock: 0, arcache: 0, arqos: 0,
189 arregion: 0, arid: 0 };
190 processor.i_rd_addr.enq(read_request);
191 //x[15:0]=fn_decr_cndtr(x[15:0],2,x[50:48]);//CHECK correct this code USE FUNCTION
192 rg_read_flag<= True;
193
194 endrule
195 endmodule
196 endpackage