OpenCores
URL https://opencores.org/ocsvn/ht_tunnel/ht_tunnel/trunk

Subversion Repositories ht_tunnel

[/] [ht_tunnel/] [trunk/] [bench/] [databuffer_l2/] [databuffer_l2_tb.cpp] - Blame information for rev 19

Details | Compare with Previous | View Log

Line No. Rev Author Line
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
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.