1 |
2 |
acastong |
//databuffer_l2_tb.cpp
|
2 |
|
|
|
3 |
|
|
/* ***** BEGIN LICENSE BLOCK *****
|
4 |
|
|
* Version: MPL 1.1
|
5 |
|
|
*
|
6 |
|
|
* The contents of this file are subject to the Mozilla Public License Version
|
7 |
|
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
8 |
|
|
* the License. You may obtain a copy of the License at
|
9 |
|
|
* http://www.mozilla.org/MPL/
|
10 |
|
|
*
|
11 |
|
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
12 |
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
13 |
|
|
* for the specific language governing rights and limitations under the
|
14 |
|
|
* License.
|
15 |
|
|
*
|
16 |
|
|
* The Original Code is HyperTransport Tunnel IP Core.
|
17 |
|
|
*
|
18 |
|
|
* The Initial Developer of the Original Code is
|
19 |
|
|
* Ecole Polytechnique de Montreal.
|
20 |
|
|
* Portions created by the Initial Developer are Copyright (C) 2005
|
21 |
|
|
* the Initial Developer. All Rights Reserved.
|
22 |
|
|
*
|
23 |
|
|
* Contributor(s):
|
24 |
|
|
* Ami Castonguay <acastong@grm.polymtl.ca>
|
25 |
|
|
*
|
26 |
|
|
* Alternatively, the contents of this file may be used under the terms
|
27 |
|
|
* of the Polytechnique HyperTransport Tunnel IP Core Source Code License
|
28 |
|
|
* (the "PHTICSCL License", see the file PHTICSCL.txt), in which case the
|
29 |
|
|
* provisions of PHTICSCL License are applicable instead of those
|
30 |
|
|
* above. If you wish to allow use of your version of this file only
|
31 |
|
|
* under the terms of the PHTICSCL License and not to allow others to use
|
32 |
|
|
* your version of this file under the MPL, indicate your decision by
|
33 |
|
|
* deleting the provisions above and replace them with the notice and
|
34 |
|
|
* other provisions required by the PHTICSCL License. If you do not delete
|
35 |
|
|
* the provisions above, a recipient may use your version of this file
|
36 |
|
|
* under either the MPL or the PHTICSCL License."
|
37 |
|
|
*
|
38 |
|
|
* ***** END LICENSE BLOCK ***** */
|
39 |
|
|
|
40 |
|
|
#include "databuffer_l2_tb.h"
|
41 |
|
|
#include <cstdlib>
|
42 |
|
|
|
43 |
|
|
databuffer_l2_tb::databuffer_l2_tb(sc_module_name name) : sc_module(name){
|
44 |
|
|
SC_THREAD(manage_memories);
|
45 |
|
|
sensitive_pos(clk);
|
46 |
|
|
|
47 |
|
|
SC_THREAD(store_data);
|
48 |
|
|
sensitive_pos(clk);
|
49 |
|
|
|
50 |
|
|
SC_THREAD(read_data);
|
51 |
|
|
sensitive_pos(clk);
|
52 |
|
|
|
53 |
|
|
SC_THREAD(manage_nops);
|
54 |
|
|
sensitive_pos(clk);
|
55 |
|
|
|
56 |
|
|
SC_THREAD(manage_reset);
|
57 |
|
|
sensitive_pos(clk);
|
58 |
|
|
|
59 |
|
|
SC_THREAD(convert_vcs);
|
60 |
|
|
sensitive << cd_vctype_db
|
61 |
|
|
<< eh_vctype_db
|
62 |
|
|
<< csr_vctype_db
|
63 |
|
|
<< ui_vctype_db
|
64 |
|
|
<< fwd_vctype_db;
|
65 |
|
|
|
66 |
|
|
|
67 |
|
|
//Flag testbench entries as free
|
68 |
|
|
for(int n = 3 * DATABUFFER_NB_BUFFERS - 1; n >= 0; n--)
|
69 |
|
|
((int*)data_packets_size)[n] = 0;
|
70 |
|
|
|
71 |
|
|
for(int n = 0; n < 3; n++){
|
72 |
|
|
data_packets_count[n] = 0;
|
73 |
|
|
data_packets_allowed[n] = 0;
|
74 |
|
|
}
|
75 |
|
|
|
76 |
|
|
allow_overflow = false;
|
77 |
|
|
srand(11843);
|
78 |
|
|
}
|
79 |
|
|
|
80 |
|
|
void databuffer_l2_tb::store_data(){
|
81 |
|
|
ldtstopx = true;
|
82 |
|
|
//The count of dwords to send to the databuffer
|
83 |
|
|
int data_left_to_send = 0;
|
84 |
|
|
//The total size of the packet being sent
|
85 |
|
|
int current_packet_size = 0;
|
86 |
|
|
//The count of data sent
|
87 |
|
|
int data_sent = 0;
|
88 |
|
|
//The address given by databuffer for packet currently being sent
|
89 |
|
|
int address;
|
90 |
|
|
//The virtual channel of the data packet
|
91 |
|
|
int vc;
|
92 |
|
|
//If we are allowed to drop the packet
|
93 |
|
|
bool droppable = false;
|
94 |
|
|
//This is synchrous process, so when get_addr is driven, the address given must be stored
|
95 |
|
|
//the next cycle. The cycle store_address_next_cycle is set, address should be read.
|
96 |
|
|
bool store_address_next_cycle = false;;
|
97 |
|
|
|
98 |
|
|
cd_write_db = false;
|
99 |
|
|
cd_getaddr_db = false;
|
100 |
|
|
cd_drop_db = false;
|
101 |
|
|
cd_initiate_retry_disconnect = false;
|
102 |
|
|
|
103 |
|
|
int clock_cycle = 0;
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
while(true){
|
107 |
|
|
//Wait until next clock cycle
|
108 |
|
|
wait();
|
109 |
|
|
clock_cycle++;
|
110 |
|
|
|
111 |
|
|
//Randomly drop packets
|
112 |
|
|
bool drop = (rand()/((float)RAND_MAX) ) < 0.02;
|
113 |
|
|
|
114 |
|
|
//Chance of writing data to the databuffer when packet is started
|
115 |
|
|
bool proceed = (rand()/((float)RAND_MAX) ) < 0.9 ;
|
116 |
|
|
//Chance of starting a packet
|
117 |
|
|
bool proceed2 = (rand()/((float)RAND_MAX) ) < 0.7;
|
118 |
|
|
|
119 |
|
|
cd_write_db = false;
|
120 |
|
|
cd_getaddr_db = false;
|
121 |
|
|
cd_drop_db = false;
|
122 |
|
|
cd_initiate_retry_disconnect = false;
|
123 |
|
|
|
124 |
|
|
//If the last cycle, we outputed a new packet, store the adress
|
125 |
|
|
//from the databuffer this cycle
|
126 |
|
|
if(store_address_next_cycle){
|
127 |
|
|
store_address_next_cycle = false;
|
128 |
|
|
address = db_address_cd.read();
|
129 |
|
|
//Check if there is already a packet at that address
|
130 |
|
|
if(data_packets_size[vc][address]){
|
131 |
|
|
cout << "Error, data packet stored where it is not allowed" << endl;
|
132 |
|
|
cout << "VC: " << vc << " address: " << address << " clock_cycle: " << clock_cycle << endl;
|
133 |
|
|
}
|
134 |
|
|
}
|
135 |
|
|
|
136 |
|
|
//The dropping the current packet
|
137 |
|
|
if(drop && droppable){
|
138 |
|
|
cd_drop_db = true;
|
139 |
|
|
droppable = false;
|
140 |
|
|
data_packets_size[vc][address] = 0;
|
141 |
|
|
data_packets_count[vc]--;
|
142 |
|
|
data_left_to_send = 0;
|
143 |
|
|
}
|
144 |
|
|
//If a new packet can be started
|
145 |
|
|
else if(proceed2 && !data_left_to_send){
|
146 |
|
|
|
147 |
|
|
cd_write_db = false;
|
148 |
|
|
cd_drop_db = false;
|
149 |
|
|
|
150 |
|
|
//Start by seing in which VC's packets can be sent
|
151 |
|
|
int vc_available[3];
|
152 |
|
|
int pos = 0;
|
153 |
|
|
int vc_count = 0;
|
154 |
|
|
//Iterate over the three vcs
|
155 |
|
|
for(int n = 0; n < 3; n++){
|
156 |
|
|
//If more data can be sent in that vc (or if overflow is allowed), add the
|
157 |
|
|
//vc to the list of available vcs!
|
158 |
|
|
if(data_packets_allowed[n] != 0 || allow_overflow){
|
159 |
|
|
vc_available[pos++] = n;
|
160 |
|
|
vc_count++;
|
161 |
|
|
}
|
162 |
|
|
}
|
163 |
|
|
|
164 |
|
|
//If we found a vc (count is not 0)
|
165 |
|
|
if( (bool)(vc_count)){
|
166 |
|
|
//Randomly select the size
|
167 |
|
|
data_left_to_send = (int)(rand() / (RAND_MAX + 1.0) * 16 + 1);
|
168 |
|
|
current_packet_size = data_left_to_send;
|
169 |
|
|
|
170 |
|
|
data_sent = 0;
|
171 |
|
|
|
172 |
|
|
//Randomly choose a vc from the list of available vc's
|
173 |
|
|
int vc_to_send = vc_available[(int)(rand() / (RAND_MAX + 1.0) * vc_count)];
|
174 |
|
|
|
175 |
|
|
vc = vc_to_send;
|
176 |
|
|
|
177 |
|
|
//Update the buffer counts
|
178 |
|
|
data_packets_allowed[vc_to_send]--;
|
179 |
|
|
data_packets_count[vc_to_send]++;
|
180 |
|
|
|
181 |
|
|
//Request an address for the packet from the databuffer
|
182 |
|
|
cd_datalen_db = data_left_to_send - 1;
|
183 |
|
|
cd_vctype_db = (VirtualChannel)vc_to_send;
|
184 |
|
|
cd_getaddr_db = true;
|
185 |
|
|
droppable = true;
|
186 |
|
|
store_address_next_cycle = true;
|
187 |
|
|
}
|
188 |
|
|
|
189 |
|
|
}
|
190 |
|
|
//Actually send the data
|
191 |
|
|
else if(proceed && data_left_to_send){
|
192 |
|
|
//start by generating a random 32-bit integer
|
193 |
|
|
|
194 |
|
|
//RAND_MAX may be as low as 32k in some librairies (VC++ for example),
|
195 |
|
|
//so to be uniform, mask the higher 17 bits
|
196 |
|
|
int r = rand() & 0x7FFF;
|
197 |
|
|
int r1 = rand() & 0x7FFF;
|
198 |
|
|
int r2 = rand() & 0x7FFF;
|
199 |
|
|
|
200 |
|
|
r = r | (r1 << 15) | (r2 << 30);
|
201 |
|
|
|
202 |
|
|
cd_data_db = sc_uint<32>(r);
|
203 |
|
|
data_packets[vc][address][data_sent] = r;
|
204 |
|
|
|
205 |
|
|
cd_write_db = true;
|
206 |
|
|
data_left_to_send--;
|
207 |
|
|
data_sent++;
|
208 |
|
|
if(!data_left_to_send)
|
209 |
|
|
data_packets_size[vc][address] = current_packet_size;
|
210 |
|
|
}
|
211 |
|
|
|
212 |
|
|
}
|
213 |
|
|
}
|
214 |
|
|
|
215 |
|
|
void databuffer_l2_tb::read_data(){
|
216 |
|
|
int fwd_read_left = 0;
|
217 |
|
|
int fwd_address = 0;
|
218 |
|
|
int fwd_vc = 0;
|
219 |
|
|
|
220 |
|
|
int accepted_read_left = 0;
|
221 |
|
|
int accepted_address = 0;
|
222 |
|
|
int accepted_vc = 0;
|
223 |
|
|
bool csr_access = false;
|
224 |
|
|
|
225 |
|
|
csr_read_db = false;
|
226 |
|
|
ui_read_db = false;
|
227 |
|
|
fwd_read_db = false;
|
228 |
|
|
eh_erase_db = false;
|
229 |
|
|
csr_erase_db = false;
|
230 |
|
|
ui_erase_db = false;
|
231 |
|
|
fwd_erase_db = false;
|
232 |
|
|
|
233 |
|
|
int debug_read_count = 0;
|
234 |
|
|
|
235 |
|
|
cout << "If there are no error message, test is successful!" << endl;
|
236 |
|
|
|
237 |
|
|
while(true){
|
238 |
|
|
wait();
|
239 |
|
|
|
240 |
|
|
|
241 |
|
|
csr_read_db = false;
|
242 |
|
|
ui_read_db = false;
|
243 |
|
|
fwd_read_db = false;
|
244 |
|
|
eh_erase_db = false;
|
245 |
|
|
csr_erase_db = false;
|
246 |
|
|
ui_erase_db = false;
|
247 |
|
|
fwd_erase_db = false;
|
248 |
|
|
|
249 |
|
|
//If the last packet sent from command decoder should be dropped
|
250 |
|
|
bool drop_proceed = (rand()/((float)RAND_MAX) ) < 0.01;
|
251 |
|
|
//If a read should be done from the accepted port
|
252 |
|
|
bool accepted_proceed = (rand()/((float)RAND_MAX) ) < 0.2 ;
|
253 |
|
|
//If a read should be done from the forward port
|
254 |
|
|
bool fwd_proceed = (rand()/((float)RAND_MAX) ) < 0.3;
|
255 |
|
|
|
256 |
|
|
//Fin some random packets to extract
|
257 |
|
|
int entries_address[3 * DATABUFFER_NB_BUFFERS];
|
258 |
|
|
int entries_vc[3 * DATABUFFER_NB_BUFFERS];
|
259 |
|
|
|
260 |
|
|
//Start by finding all valid entries
|
261 |
|
|
int entries_count = 0;
|
262 |
|
|
//for all 3 vc
|
263 |
|
|
for(int x = 0; x < 3; x++){
|
264 |
|
|
//for every packet in the vc
|
265 |
|
|
for(int y = 0 ; y < DATABUFFER_NB_BUFFERS; y++){
|
266 |
|
|
//Check if there is packet (size is non zero) and is not currently being
|
267 |
|
|
//read by the forward of the accepted read ports
|
268 |
|
|
if(data_packets_size[x][y] && !(
|
269 |
|
|
x == fwd_vc && y == fwd_address && (fwd_read_left || fwd_erase_db.read()) ||
|
270 |
|
|
x == accepted_vc && y == accepted_address && (accepted_read_left || csr_erase_db.read() || ui_erase_db.read())))
|
271 |
|
|
{
|
272 |
|
|
entries_address[entries_count] = y;
|
273 |
|
|
entries_vc[entries_count++] = x;
|
274 |
|
|
}
|
275 |
|
|
}
|
276 |
|
|
}
|
277 |
|
|
|
278 |
|
|
////////////////////////////////////////////////////////
|
279 |
|
|
// Test If output is correct
|
280 |
|
|
//
|
281 |
|
|
// Read signals were set by the randomly set "proceed"
|
282 |
|
|
// variables on the LAST cycle. Now we check if the
|
283 |
|
|
// output from those reads are correct.
|
284 |
|
|
////////////////////////////////////////////////////////
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
|
288 |
|
|
//Check if the dababuffer output on the Forward port is correct
|
289 |
|
|
if(fwd_read_db.read()){
|
290 |
|
|
//Check if db_data_fwd is correct
|
291 |
|
|
if( data_packets[fwd_vc][fwd_address]
|
292 |
|
|
[data_packets_size[fwd_vc][fwd_address]-fwd_read_left-1]
|
293 |
|
|
!= (int)((sc_uint<32>)db_data_fwd.read()))
|
294 |
|
|
{
|
295 |
|
|
cout << "Data signal has wrong value on Forward port" << endl;
|
296 |
|
|
cout << "Data VC: "<< (int)fwd_vc << " Address: " << fwd_address <<
|
297 |
|
|
" Pos: " << data_packets_size[fwd_vc][fwd_address]-fwd_read_left-1 << endl;
|
298 |
|
|
cout << "Data expected: " << ((sc_uint<32>)data_packets[fwd_vc][fwd_address]
|
299 |
|
|
[data_packets_size[fwd_vc][fwd_address]-fwd_read_left-1]).to_string(SC_HEX) << endl;
|
300 |
|
|
cout << "Data received: " << ((sc_uint<32>)db_data_fwd.read()).to_string(SC_HEX) << endl;
|
301 |
|
|
}
|
302 |
|
|
|
303 |
|
|
//On last read, clear the value
|
304 |
|
|
if(!fwd_read_left)
|
305 |
|
|
data_packets_size[fwd_vc][fwd_address] = 0;
|
306 |
|
|
}
|
307 |
|
|
|
308 |
|
|
//Check if the dababuffer output on the Forward port is correct
|
309 |
|
|
if(csr_read_db.read() || ui_read_db.read()){
|
310 |
|
|
//Check if db_data_fwd is correct
|
311 |
|
|
if( data_packets[accepted_vc][accepted_address]
|
312 |
|
|
[data_packets_size[accepted_vc][accepted_address]-accepted_read_left-1]
|
313 |
|
|
!= (int)((sc_uint<32>)db_data_accepted.read()))
|
314 |
|
|
{
|
315 |
|
|
cout << "Data signal has wrong value on Accepted port" << endl;
|
316 |
|
|
cout << "Data VC: "<< (int)accepted_vc << " Address: " << accepted_address <<
|
317 |
|
|
" Pos: " << data_packets_size[accepted_vc][accepted_address]-accepted_read_left-1 << endl;
|
318 |
|
|
cout << "Data expected: " << ((sc_uint<32>)data_packets[accepted_vc][accepted_address]
|
319 |
|
|
[data_packets_size[accepted_vc][accepted_address]-accepted_read_left-1]
|
320 |
|
|
).to_string(SC_HEX) << endl;
|
321 |
|
|
cout << "Data received: " << ((sc_uint<32>)db_data_accepted.read()).to_string(SC_HEX) << endl;
|
322 |
|
|
}
|
323 |
|
|
|
324 |
|
|
//On last read, clear the value
|
325 |
|
|
if(!accepted_read_left)
|
326 |
|
|
data_packets_size[accepted_vc][accepted_address] = 0;
|
327 |
|
|
}
|
328 |
|
|
|
329 |
|
|
////////////////////////////////////////////////////////
|
330 |
|
|
// Activate the correct read signals
|
331 |
|
|
////////////////////////////////////////////////////////
|
332 |
|
|
|
333 |
|
|
//Do the read on the Forward port
|
334 |
|
|
if(fwd_proceed){
|
335 |
|
|
//If no packet has been started
|
336 |
|
|
if(!fwd_read_left && entries_count > 0){
|
337 |
|
|
//Find one in the list of valid entries
|
338 |
|
|
int pos = (int)(rand() / (RAND_MAX + 1.0) * entries_count);
|
339 |
|
|
fwd_address_db = entries_address[pos];
|
340 |
|
|
fwd_vctype_db = (VirtualChannel)entries_vc[pos];
|
341 |
|
|
fwd_read_left = data_packets_size[entries_vc[pos]][entries_address[pos]];
|
342 |
|
|
fwd_address = entries_address[pos];
|
343 |
|
|
fwd_vc = entries_vc[pos];
|
344 |
|
|
|
345 |
|
|
//Remove that entry
|
346 |
|
|
entries_count--;
|
347 |
|
|
for(int n = pos; n < entries_count;n++){
|
348 |
|
|
entries_address[n] = entries_address[n+1];
|
349 |
|
|
entries_vc[n] = entries_vc[n+1];
|
350 |
|
|
}
|
351 |
|
|
}
|
352 |
|
|
else if(fwd_read_left > 0){
|
353 |
|
|
fwd_read_db = true;
|
354 |
|
|
fwd_read_left--;
|
355 |
|
|
fwd_erase_db = fwd_read_left == 0;
|
356 |
|
|
}
|
357 |
|
|
}
|
358 |
|
|
|
359 |
|
|
//Do the read on the Forward port
|
360 |
|
|
if(accepted_proceed){
|
361 |
|
|
//If no packet has been started
|
362 |
|
|
if(!accepted_read_left && entries_count > 0){
|
363 |
|
|
|
364 |
|
|
//Decide if it's the CSR or UI reading
|
365 |
|
|
csr_access = (rand()/((float)RAND_MAX) ) < 0.5;
|
366 |
|
|
|
367 |
|
|
//Find one in the list of valid entries
|
368 |
|
|
int pos = (int)(rand() / (RAND_MAX + 1.0) * entries_count);
|
369 |
|
|
accepted_read_left = data_packets_size[entries_vc[pos]][entries_address[pos]];
|
370 |
|
|
|
371 |
|
|
//Activate the correct address and vc signals depending on if it is the CSR or the
|
372 |
|
|
//UI accessing the data.
|
373 |
|
|
if(csr_access){
|
374 |
|
|
csr_address_db = entries_address[pos];
|
375 |
|
|
csr_vctype_db = (VirtualChannel)entries_vc[pos];
|
376 |
|
|
ui_address_db = 0;
|
377 |
|
|
ui_vctype_db = VC_NONE;
|
378 |
|
|
ui_grant_csr_access_db = true;
|
379 |
|
|
}
|
380 |
|
|
else{
|
381 |
|
|
csr_address_db = 0;
|
382 |
|
|
csr_vctype_db = VC_NONE;
|
383 |
|
|
ui_address_db = entries_address[pos];
|
384 |
|
|
ui_vctype_db = (VirtualChannel)entries_vc[pos];
|
385 |
|
|
ui_grant_csr_access_db = false;
|
386 |
|
|
}
|
387 |
|
|
accepted_address = entries_address[pos];
|
388 |
|
|
accepted_vc = entries_vc[pos];
|
389 |
|
|
|
390 |
|
|
|
391 |
|
|
//Remove that entry
|
392 |
|
|
entries_count--;
|
393 |
|
|
for(int n = pos; n < entries_count;n++){
|
394 |
|
|
entries_address[n] = entries_address[n+1];
|
395 |
|
|
entries_vc[n] = entries_vc[n+1];
|
396 |
|
|
}
|
397 |
|
|
}
|
398 |
|
|
else if(accepted_read_left > 0){
|
399 |
|
|
accepted_read_left--;
|
400 |
|
|
if(csr_access){
|
401 |
|
|
ui_read_db = false;
|
402 |
|
|
csr_read_db = true;
|
403 |
|
|
csr_erase_db = accepted_read_left == 0;
|
404 |
|
|
}
|
405 |
|
|
else{
|
406 |
|
|
ui_read_db = true;
|
407 |
|
|
csr_read_db = false;
|
408 |
|
|
ui_erase_db = accepted_read_left == 0;
|
409 |
|
|
}
|
410 |
|
|
}
|
411 |
|
|
}
|
412 |
|
|
|
413 |
|
|
////////////////////////////////////////////////////////
|
414 |
|
|
// Test the Error drop Port
|
415 |
|
|
////////////////////////////////////////////////////////
|
416 |
|
|
|
417 |
|
|
if(drop_proceed && entries_count != 0){
|
418 |
|
|
//Find one in the list of valid entries
|
419 |
|
|
int pos = (int)(rand() / (RAND_MAX + 1.0) * entries_count);
|
420 |
|
|
int address = entries_address[pos];
|
421 |
|
|
int vc = entries_vc[pos];
|
422 |
|
|
data_packets_size[vc][address] = 0;
|
423 |
|
|
|
424 |
|
|
eh_address_db = address;
|
425 |
|
|
eh_vctype_db = (VirtualChannel) vc;
|
426 |
|
|
eh_erase_db = true;
|
427 |
|
|
}
|
428 |
|
|
}
|
429 |
|
|
}
|
430 |
|
|
|
431 |
|
|
|
432 |
|
|
void databuffer_l2_tb::manage_nops(){
|
433 |
|
|
fc_nop_sent = false;
|
434 |
|
|
bool nop_requested = false;
|
435 |
|
|
error = false;
|
436 |
|
|
bool should_request = false;
|
437 |
|
|
|
438 |
|
|
while(true){
|
439 |
|
|
wait();
|
440 |
|
|
|
441 |
|
|
fc_nop_sent = false;
|
442 |
|
|
if(!resetx.read()){
|
443 |
|
|
for(int n = 0; n < 3; n++){
|
444 |
|
|
data_packets_count[n] = 0;
|
445 |
|
|
data_packets_allowed[n] = 0;
|
446 |
|
|
}
|
447 |
|
|
}
|
448 |
|
|
else{
|
449 |
|
|
//Add a tad bit of randomness, just for fun!
|
450 |
|
|
bool proceed = (rand()/((float)RAND_MAX) ) < 0.2 ;
|
451 |
|
|
bool dont_proceed = (rand()/((float)RAND_MAX) ) < 0.2 ;
|
452 |
|
|
|
453 |
|
|
//Remember when a nop is requested
|
454 |
|
|
if(db_nop_req_fc.read()){
|
455 |
|
|
nop_requested = true;
|
456 |
|
|
}
|
457 |
|
|
|
458 |
|
|
//When a nop is being sent out, update the free buffers
|
459 |
|
|
if(fc_nop_sent.read()){
|
460 |
|
|
sc_uint<2> nonposted_freed = (sc_bv<2>)db_buffer_cnt_fc.read().range(5,4);
|
461 |
|
|
sc_uint<2> posted_freed = (sc_bv<2>)db_buffer_cnt_fc.read().range(1,0);
|
462 |
|
|
sc_uint<2> response_freed = (sc_bv<2>)db_buffer_cnt_fc.read().range(3,2);
|
463 |
|
|
data_packets_allowed[VC_NON_POSTED] += nonposted_freed;
|
464 |
|
|
data_packets_allowed[VC_POSTED] += posted_freed;
|
465 |
|
|
data_packets_allowed[VC_RESPONSE] += response_freed;
|
466 |
|
|
}
|
467 |
|
|
|
468 |
|
|
|
469 |
|
|
if(should_request && !nop_requested && !fc_nop_sent.read()){
|
470 |
|
|
cout << "ERROR: Databuffer not correctly requesting nops to be sent" << endl;
|
471 |
|
|
error = true;
|
472 |
|
|
}
|
473 |
|
|
|
474 |
|
|
//When there is a request, send a nop
|
475 |
|
|
if(db_nop_req_fc.read() && !dont_proceed || proceed){
|
476 |
|
|
fc_nop_sent = true;
|
477 |
|
|
nop_requested = false;//Reset when sent
|
478 |
|
|
}
|
479 |
|
|
|
480 |
|
|
//Verify that the databuffer correctly requests sending nops when
|
481 |
|
|
//necessary. Do it at the end so that it has a delay of one cycle because
|
482 |
|
|
//the databuffer also takes a cycle to answer
|
483 |
|
|
should_request = false;
|
484 |
|
|
for(int n = 0; n < 3; n++){
|
485 |
|
|
if(data_packets_allowed[n] < (DATABUFFER_NB_BUFFERS - data_packets_count[n] - 2))
|
486 |
|
|
should_request = true;
|
487 |
|
|
}
|
488 |
|
|
}
|
489 |
|
|
|
490 |
|
|
}
|
491 |
|
|
}
|
492 |
|
|
|
493 |
|
|
|
494 |
|
|
void databuffer_l2_tb::manage_memories(){
|
495 |
|
|
//Initialise memory
|
496 |
|
|
for(int n = 3 * DATABUFFER_NB_BUFFERS * 16 - 1
|
497 |
|
|
; n >= 0; n--)
|
498 |
|
|
((int*)memory)[n] = 0;
|
499 |
|
|
|
500 |
|
|
while(true){
|
501 |
|
|
wait();
|
502 |
|
|
|
503 |
|
|
//Manage writing
|
504 |
|
|
if(memory_write.read()){
|
505 |
|
|
if(memory_write_address_vc.read() != 3)
|
506 |
|
|
memory[memory_write_address_vc.read()][memory_write_address_buffer.read()]
|
507 |
|
|
[memory_write_address_pos.read()] = (int)(sc_uint<32>)(memory_write_data.read());
|
508 |
|
|
else
|
509 |
|
|
cout << "Critical ERROR : writing to VC 3 in memory (doesn't exist)" << endl;
|
510 |
|
|
}
|
511 |
|
|
|
512 |
|
|
//Manage reading
|
513 |
|
|
for(int port = 0; port < 2; port++){
|
514 |
|
|
memory_output[port] = memory[memory_read_address_vc[port].read()]
|
515 |
|
|
[memory_read_address_buffer[port].read()][memory_read_address_pos[port].read()];
|
516 |
|
|
}
|
517 |
|
|
|
518 |
|
|
}
|
519 |
|
|
}
|
520 |
|
|
|
521 |
|
|
void databuffer_l2_tb::manage_reset(){
|
522 |
|
|
resetx = false;
|
523 |
|
|
int count = 0;
|
524 |
|
|
while(count++ < 5)wait();
|
525 |
|
|
resetx = true;
|
526 |
|
|
while(true) wait();
|
527 |
|
|
}
|
528 |
|
|
|
529 |
|
|
void databuffer_l2_tb::convert_vcs(){
|
530 |
|
|
while(true){
|
531 |
|
|
cd_vctype_db_trace = (int)cd_vctype_db.read();
|
532 |
|
|
eh_vctype_db_trace = (int)eh_vctype_db.read();
|
533 |
|
|
csr_vctype_db_trace = (int)csr_vctype_db.read();
|
534 |
|
|
ui_vctype_db_trace = (int)ui_vctype_db.read();
|
535 |
|
|
fwd_vctype_db_trace = (int)fwd_vctype_db.read();
|
536 |
|
|
wait();
|
537 |
|
|
}
|
538 |
|
|
}
|