AXI muckbucket
axi_sequential_reads_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 
33 class axi_sequential_reads_seq : public axi_seq { public:
34 
36 
37  new (string name="axi_sequential_reads_seq");
38  task body();
39 
40 };
41 
46  axi_sequential_reads_seq::new (string name="axi_sequential_reads_seq") {
47  super.new(name);
48 }
49 
50 
65 
66  bit <ADDR_WIDTH-1:0> addr_lo;
67  bit <ADDR_WIDTH-1:0> addr_hi;
68  bit <ID_WIDTH-1:0> xid;
69 
70  int max_beat_cnt;
71  int dtsize;
72  bit <ADDR_WIDTH-1:0> Lower_Wrap_Boundary;
73  bit <ADDR_WIDTH-1:0> Upper_Wrap_Boundary;
74  bit <ADDR_WIDTH-1:0> write_addr;
75 
76  axi_seq_item read_item;
77 
78  xfers_done=0;
79 
80 
81  if (!uvm_config_db <memory> ::get(null, "", "m_memory", m_memory)) {
82  uvm_fatal(this.get_type_name(),
83  "Unable to fetch m_memory from config db. Using defaults")
84  }
85 
86  // Clear memory
87  // backdoor write to memory
88  // AXI readback of memory
89 
90  for (int xfer_cnt=0;xfer_cnt <xfers_to_send;xfer_cnt++) {
91 
92  // clear memory
93  if (clearmemory==1) {
94  for (int i=0;i <window_size;i++) {
95  m_memory.write(i, 0x0);
96  }
97  }
98 
99 
100  read_item = axi_seq_item::type_id::create("read_item");
101 
102 
103  // Not sure why I have to define and set these and
104  // then use them in the randomize with {} but
105  // Riviera Pro works better like this.
106  addr_lo = xfer_cnt*window_size;
107  addr_hi = addr_lo+0x100;
108  xid = xfer_cnt[ID_WIDTH-1:0];
109 
110 
111  uvm_info(this.get_type_name(),
112  $sformatf("item %0d id:0x%0x addr_lo: 0x%0x addr_hi: 0x%0x",
113  xfer_cnt, xid, addr_lo,addr_hi),
114  UVM_INFO)
115 
116 
117  assert( read_item.randomize() with {
118  cmd == e_READ;
119  burst_size <= local::max_burst_size;
120  id == local::xid;
121  addr >= local::addr_lo;
122  addr < local::addr_hi;
123  })
124 
125  uvm_info("DATA", $sformatf("\n\n\nItem %0d: %s",
126  xfer_cnt, read_item.convert2string()),
127  UVM_INFO)
128 
129 
130  //backdoor fill memory
131  case (read_item.burst_type) {
132  e_FIXED : {
133 
134  Lower_Wrap_Boundary = read_item.addr;
135  Upper_Wrap_Boundary = Lower_Wrap_Boundary + (2**read_item.burst_size);
136 
137  }
138  e_INCR : {
139  Lower_Wrap_Boundary = read_item.addr;
140  Upper_Wrap_Boundary = Lower_Wrap_Boundary + read_item.len;
141 
142  }
143  e_WRAP : {
144  max_beat_cnt = axi_pkg::calculate_axlen(.addr(read_item.addr),
145  .burst_size(read_item.burst_size),
146  .burst_length(read_item.len)) + 1;
147 
148  dtsize = (2**read_item.burst_size) * max_beat_cnt;
149 
150  Lower_Wrap_Boundary = (int(read_item.addr/dtsize) * dtsize);
151  Upper_Wrap_Boundary = Lower_Wrap_Boundary + dtsize;
152 
153  }
154  }
155 
156  write_addr = read_item.addr;
157  for (int i=0;i <read_item.len;i++) {
158  m_memory.write(write_addr, i[8]);
159  write_addr++;
160  if (write_addr >= Upper_Wrap_Boundary) {
161  write_addr = Lower_Wrap_Boundary;
162  }
163  }
164 
165 
166  start_item (read_item);
167  finish_item (read_item);
168  get_response(read_item);
169 
170 
171 
172  assert(m_memory.seq_item_check(.item(read_item),
173  .lower_addr(addr_lo),
174  .upper_addr(addr_hi)));
175 
176 
177  } //for
178 
179  uvm_info(this.get_type_name(), "SEQ ALL DONE", UVM_INFO)
180 
181 }
182 
bit< C_AXI_LEN_WIDTH-1:0 > calculate_axlen(input bit< C_AXI_ADDR_WIDTH-1:0 > addr, input bit< 2:0 > burst_size, input shortint burst_length)
calculate awlen or arlen
Definition: axi_pkg.sv:320
rand int len
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
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
rand bit< ADDR_WIDTH-1:0 > addr
virtual void write(input bit< ADDR_WIDTH-1:0 > addr, input bit< 7:0 > data)
Writes into memory.
Definition: memory.svh:58
rand logic< 2:0 > burst_size
const int window_size
Definition: axi_seq.svh:39
Writes to memory over AXI, backdoor readback, then AXI readback.
uvm_object_utils(axi_sequential_reads_seq) new(string name
memory m_memory
Definition: axi_seq.svh:48
new(string name="axi_seq")
Constructor.
Definition: axi_seq.svh:62
task body()
Does all the work.
Writes to memory over AXI, backdoor readback, then AXI readback.
Definition: axi_seq.svh:33
rand logic< 1:0 > burst_type
contains all data and functions related to axi and usage
localparam ADDR_WIDTH
Definition: axi_uvm_pkg.sv:39