AXI muckbucket
axi_pipelined_writes_seq.svh
Go to the documentation of this file.
1 //
3 // Copyright (C) 2017, Matt Dew @ Dew Technologies, LLC
4 //
5 // This program is free software (logic verification): you can redistribute it
6 // and/or modify it under the terms of the GNU Lesser General Public License (LGPL)
7 // as published by the Free Software Foundation, either version 3 of the License,
8 // or (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful, but WITHOUT
11 // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
12 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13 // for more details.
14 //
15 // License: LGPL, v3, as defined and found on www.gnu.org,
16 // http://www.gnu.org/licenses/lgpl.html
17 //
18 //
19 // Author's intent: If you use this AXI verification code and find or fix bugs
20 // or make improvements, then share those fixes or improvements.
21 // If you use this in a bigger project, I don't care about,
22 // or want, any changes or code outside this block.
23 // Example: If you use this in an SoC simulation/testbench
24 // I don't want, or care about, your SoC or other blocks.
25 // I just care about the enhancements to these AXI files.
26 // That's why I have choosen the LGPL instead of the GPL.
28 
35 class axi_pipelined_writes_seq : public axi_seq { public:
36 
38 
39  axi_seq_item write_item [];
40 
42 
43  // all write responses have been received
44  // Reads can go ahead
45  event writes_done;
46 
47 
48  typedef struct {
49  bit <ADDR_WIDTH-1:0> laddr;
50  bit <ADDR_WIDTH-1:0> uaddr;
51  } mem_chk_s;
52 
54 
55 
56  new (string name="axi_pipelined_writes_seq");
57  task body();
58  void response_handler(uvm_sequence_item response);
59 
60 };
61 
62 
63 // This response_handler function is enabled to keep the sequence response FIFO empty
67  automatic void axi_pipelined_writes_seq::response_handler(uvm_sequence_item response) {
68 
69  axi_seq_item item;
70  int xfer_cnt;
71  int id;
72 
73  bit <ADDR_WIDTH-1:0> lower_addr;
74  bit <ADDR_WIDTH-1:0> upper_addr;
75  $cast(item,response);
76 
77  xfer_cnt=item.id;
78  if (item.cmd== e_WRITE_RESPONSE) {
79  xfers_done++;
80 
81  id=item.get_transaction_id();
82 
83  lower_addr = mem_chk_array[id].laddr;
84  upper_addr = mem_chk_array[id].uaddr;
85 
86  if (!m_memory.seq_item_check(.item (item),
87  .lower_addr (lower_addr),
88  .upper_addr (upper_addr))) {
89  uvm_info("MISCOMPARE","Miscompare error", UVM_INFO)
90  }
91 
92  if (xfers_done >= xfers_to_send) {
93  uvm_info("axi_seq::response_handler::sending event ",
94  $sformatf("xfers_done:%0d xfers_to_send: %0d sending event",
96  UVM_INFO)
97  ->writes_done;
98  }
99 
100 }
101  uvm_info(this.get_type_name(),
102  $sformatf("SEQ_response_handler xfers_done=%0d/%0d. Item: %s",
104  UVM_INFO)
105 
106 
107 }
108 
113  axi_pipelined_writes_seq::new (string name="axi_pipelined_writes_seq") {
114  super.new(name);
115 }
116 
117 
132 
133  string s;
134 
135  bit <ADDR_WIDTH-1:0> addr_lo;
136  bit <ADDR_WIDTH-1:0> addr_hi;
137  bit <ID_WIDTH-1:0> xid;
138 
139  xfers_done=0;
140 
141  write_item = new [xfers_to_send];
142 
143  use_response_handler(1); // Enable Response Handler
144 
145  if (!uvm_config_db <memory> ::get(null, "", "m_memory", m_memory)) {
146  uvm_fatal(this.get_type_name, "Unable to fetch m_memory from config db. Using defaults")
147  }
148 
149 
150 
151  // Clear memory
152  // AXI write
153  // direct readback of memory
154  // check that addresses before Axi start address are still 0
155  // chck expected data
156  // check that addresses after axi start_addres+length are still 0
157 
158  for (int xfer_cnt=0;xfer_cnt <xfers_to_send;xfer_cnt++) {
159 
160  // clear memory
161  if (clearmemory==1) {
162  for (int i=0;i <window_size;i++) {
163  m_memory.write(i, 0x0);
164  }
165  }
166 
167  write_item[xfer_cnt] = axi_seq_item::type_id::create("write_item");
168  write_item[xfer_cnt].set_transaction_id(transaction_id++);
169 
170  // Not sure why I have to define and set these and
171  // then use them in the randomize with {} but
172  // Riviera Pro works better like this.
173  addr_lo=xfer_cnt*window_size;
174  addr_hi=addr_lo+0x100;
175  xid =xfer_cnt[ID_WIDTH-1:0];
176 
177 
178  mem_chk_array[write_item[xfer_cnt].get_transaction_id()].laddr =addr_lo;
179  mem_chk_array[write_item[xfer_cnt].get_transaction_id()].uaddr =addr_lo+window_size;
180 
181 
182  start_item(write_item[xfer_cnt]);
183 
184  uvm_info(this.get_type_name(),
185  $sformatf("item %0d id:0x%0x addr_lo: 0x%0x addr_hi: 0x%0x",
186  xfer_cnt, xid, addr_lo,addr_hi),
187  UVM_INFO)
188 
189 
190  assert( write_item[xfer_cnt].randomize() with {
191  cmd == e_WRITE;
192  burst_size <= local::max_burst_size;
193  id == local::xid;
194  addr >= local::addr_lo;
195  addr < local::addr_hi;
196  })
197  // If valid specified, then pass it to seq item.
198  if (valid.size() > 0) {
199  write_item[xfer_cnt].valid = new[valid.size()](valid);
200  }
201 
202  uvm_info("DATA", $sformatf("\n\n\nItem %0d: %s", xfer_cnt, write_item[xfer_cnt].convert2string()), UVM_INFO)
203  finish_item(write_item[xfer_cnt]);
204 
205 
206  } //for
207 
208 
209  uvm_info("READBACK", "writes done. waiting for event trigger", UVM_INFO)
210  wait (writes_done.triggered);
211  uvm_info("READBACK", "event trigger detected1111", UVM_INFO)
212 
213  uvm_info(this.get_type_name(), "SEQ ALL DONE", UVM_INFO)
214 
215 }
216 
rand cmd_t cmd
string convert2string()
Convert item&#39;s variable into one printable string.
int xfers_to_send
Definition: axi_seq.svh:40
int xfers_done
Definition: axi_seq.svh:46
uvm_object_utils(axi_pipelined_writes_seq) axi_seq_item write_item[]
Writes to memory over AXI, backdoor readback.
rand bit< ID_WIDTH-1:0 > id
localparam ID_WIDTH
Definition: axi_uvm_pkg.sv:40
bit seq_item_check(ref axi_seq_item item, input bit< ADDR_WIDTH-1:0 > lower_addr, input bit< ADDR_WIDTH-1:0 > upper_addr)
Compares an axi_seq_item&#39;s data and burst_type against expected matching memory contents.
Definition: memory.svh:85
virtual void write(input bit< ADDR_WIDTH-1:0 > addr, input bit< 7:0 > data)
Writes into memory.
Definition: memory.svh:58
const int window_size
Definition: axi_seq.svh:39
void response_handler(uvm_sequence_item response)
Handles write responses, including verifying memory via backdoor reads.
memory m_memory
Definition: axi_seq.svh:48
bit valid[]
Definition: axi_seq.svh:42
task body()
Does all the work.
Writes to memory over AXI, backdoor readback, then AXI readback.
Definition: axi_seq.svh:33
contains all data and functions related to axi and usage
new(string name="axi_pipelined_writes_seq")
Constructor.
localparam ADDR_WIDTH
Definition: axi_uvm_pkg.sv:39