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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [ao486_tool/] [src/] [ao486/] [module/] [memory/] [test/] [TestWriteCacheLRU.java] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 alfik
/*
2
 * Copyright (c) 2014, Aleksander Osman
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * * Redistributions of source code must retain the above copyright notice, this
9
 *   list of conditions and the following disclaimer.
10
 *
11
 * * Redistributions in binary form must reproduce the above copyright notice,
12
 *   this list of conditions and the following disclaimer in the documentation
13
 *   and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
 
27
package ao486.module.memory.test;
28
 
29
import ao486.module.memory.AvalonListener;
30
import ao486.module.memory.GlobalListener;
31
import ao486.module.memory.Input;
32
import ao486.module.memory.InvalidateListener;
33
import ao486.module.memory.Listener;
34
import ao486.module.memory.Output;
35
import ao486.module.memory.ReadListener;
36
import ao486.module.memory.Test;
37
import ao486.module.memory.WriteListener;
38
import java.util.HashMap;
39
import java.util.LinkedList;
40
import java.util.Random;
41
 
42
class TestWriteCacheLRUState {
43
 
44
    TestWriteCacheLRUState(Random random) {
45
        this.random = random;
46
 
47
        address_middle_base = random.nextLong();
48
        address_middle_base &= 0x00000FF0L;
49
 
50
        next_writeback = new LinkedList<>();
51
    }
52
 
53
    boolean select_0() {
54
        if(active_0 == false) return false;
55
 
56
        next_address_base = address_middle_base | address_0_base;
57
 
58
        plru_0 = true;
59
        plru_1 = true;
60
 
61
        return true;
62
    }
63
    boolean select_1() {
64
        if(active_1 == false || active_0 == false) return false;
65
 
66
        next_address_base = address_middle_base | address_1_base;
67
 
68
        plru_0 = true;
69
        plru_1 = false;
70
 
71
        return true;
72
    }
73
    boolean select_2() {
74
        if(active_2 == false || active_0 == false || active_1 == false) return false;
75
 
76
        next_address_base = address_middle_base | address_2_base;
77
 
78
        plru_0 = false;
79
        plru_2 = true;
80
 
81
        return true;
82
    }
83
    boolean select_3() {
84
        if(active_3 == false || active_0 == false || active_1 == false || active_2 == false) return false;
85
 
86
        next_address_base = address_middle_base | address_3_base;
87
 
88
        plru_0 = false;
89
        plru_2 = false;
90
 
91
        return true;
92
    }
93
    void select_new() {
94
        if(active_0 == false) {
95
            active_0 = true;
96
 
97
            plru_0 = true;
98
            plru_1 = true;
99
 
100
            do {
101
                address_0_base = random.nextLong();
102
                address_0_base &= 0xFFFFF000L;
103
            } while(Test.address_not_in_cache(address_0_base) || address_0_base == address_1_base || address_0_base == address_2_base || address_0_base == address_3_base);
104
 
105
            next_address_base = address_middle_base | address_0_base;
106
        }
107
        else if(active_1 == false) {
108
            active_1 = true;
109
 
110
            plru_0 = true;
111
            plru_1 = false;
112
 
113
            do {
114
                address_1_base = random.nextLong();
115
                address_1_base &= 0xFFFFF000L;
116
            } while(Test.address_not_in_cache(address_1_base) || address_1_base == address_0_base || address_1_base == address_2_base || address_1_base == address_3_base);
117
 
118
            next_address_base = address_middle_base | address_1_base;
119
        }
120
        else if(active_2 == false) {
121
            active_2 = true;
122
 
123
            plru_0 = false;
124
            plru_2 = true;
125
 
126
            do {
127
                address_2_base = random.nextLong();
128
                address_2_base &= 0xFFFFF000L;
129
            } while(Test.address_not_in_cache(address_2_base) || address_2_base == address_0_base || address_2_base == address_1_base || address_2_base == address_3_base);
130
 
131
            next_address_base = address_middle_base | address_2_base;
132
        }
133
        else if(active_3 == false) {
134
            active_3 = true;
135
 
136
            plru_0 = false;
137
            plru_2 = false;
138
 
139
            do {
140
                address_3_base = random.nextLong();
141
                address_3_base &= 0xFFFFF000L;
142
            } while(Test.address_not_in_cache(address_3_base) || address_3_base == address_0_base || address_3_base == address_1_base || address_3_base == address_2_base);
143
 
144
            next_address_base = address_middle_base | address_3_base;
145
        }
146
        else {
147
            if(plru_0 == false && plru_1 == false) { //0
148
                plru_0 = true;
149
                plru_1 = true;
150
 
151
                next_writeback.add(address_middle_base | address_0_base);
152
 
153
                do {
154
                    address_0_base = random.nextLong();
155
                    address_0_base &= 0xFFFFF000L;
156
                } while(Test.address_not_in_cache(address_0_base) || address_0_base == address_1_base || address_0_base == address_2_base || address_0_base == address_3_base);
157
 
158
                next_address_base = address_middle_base | address_0_base;
159
            }
160
            else if(plru_0 == false && plru_1 == true) { //1
161
                plru_0 = true;
162
                plru_1 = false;
163
 
164
                next_writeback.add(address_middle_base | address_1_base);
165
 
166
                do {
167
                    address_1_base = random.nextLong();
168
                    address_1_base &= 0xFFFFF000L;
169
                } while(Test.address_not_in_cache(address_1_base) || address_1_base == address_0_base || address_1_base == address_2_base || address_1_base == address_3_base);
170
 
171
                next_address_base = address_middle_base | address_1_base;
172
            }
173
            else if(plru_0 == true && plru_2 == false) { //2
174
                plru_0 = false;
175
                plru_2 = true;
176
 
177
                next_writeback.add(address_middle_base | address_2_base);
178
 
179
                do {
180
                    address_2_base = random.nextLong();
181
                    address_2_base &= 0xFFFFF000L;
182
                } while(Test.address_not_in_cache(address_2_base) || address_2_base == address_0_base || address_2_base == address_1_base || address_2_base == address_3_base);
183
 
184
                next_address_base = address_middle_base | address_2_base;
185
            }
186
            else if(plru_0 == true && plru_2 == true) { //3
187
                plru_0 = false;
188
                plru_2 = false;
189
 
190
                next_writeback.add(address_middle_base | address_3_base);
191
 
192
                do {
193
                    address_3_base = random.nextLong();
194
                    address_3_base &= 0xFFFFF000L;
195
                } while(Test.address_not_in_cache(address_3_base) || address_3_base == address_0_base || address_3_base == address_1_base || address_3_base == address_2_base);
196
 
197
                next_address_base = address_middle_base | address_3_base;
198
            }
199
        }
200
    }
201
 
202
    void select() {
203
 
204
        while(true) {
205
            int val = random.nextInt(5);
206
 
207
            if(val >= 0 && val <= 3)    next_write_to_cache = true;
208
            else                        next_write_to_cache = false;
209
 
210
            if(val == 0) {
211
                boolean accepted = select_0();
212
                if(accepted == false) continue;
213
                break;
214
            }
215
            else if(val == 1) {
216
                boolean accepted = select_1();
217
                if(accepted == false) continue;
218
                break;
219
            }
220
            else if(val == 2) {
221
                boolean accepted = select_2();
222
                if(accepted == false) continue;
223
                break;
224
            }
225
            else if(val == 3) {
226
                boolean accepted = select_3();
227
                if(accepted == false) continue;
228
                break;
229
            }
230
            else {
231
                select_new();
232
                break;
233
            }
234
        }
235
 
236
        //print pLRU
237
        //int plru = ((plru_0)? 1 : 0) + ((plru_1)? 2 : 0) + ((plru_2)? 4 : 0);
238
        //System.out.println("pLRU: " + plru);
239
    }
240
 
241
    private Random random;
242
 
243
    private long address_middle_base;
244
 
245
    private long address_0_base;
246
    private long address_1_base;
247
    private long address_2_base;
248
    private long address_3_base;
249
 
250
    private boolean active_0;
251
    private boolean active_1;
252
    private boolean active_2;
253
    private boolean active_3;
254
 
255
    private boolean plru_0;
256
    private boolean plru_1;
257
    private boolean plru_2;
258
 
259
    long next_address_base;
260
 
261
    LinkedList<Long> next_writeback;
262
 
263
    boolean next_write_to_cache;
264
}
265
 
266
public class TestWriteCacheLRU extends Test implements Listener, ReadListener.ReadInterface, WriteListener.WriteInterface, InvalidateListener.InvalidateInterface {
267
 
268
    void go(long seed) throws Exception {
269
        random = new Random(seed);
270
        state  = new TestWriteCacheLRUState(random);
271
        expected_values = new HashMap<>();
272
 
273
        avalon      = new AvalonListener(random, this);
274
        read        = new ReadListener();
275
        write       = new WriteListener();
276
        invalidate  = new InvalidateListener();
277
        global      = new GlobalListener();
278
 
279
        global.set(false, false, false, false, random.nextBoolean(), false, 0xABCDE000, false, false, false, false);
280
 
281
        finish_cycle = 0;
282
        counter = 1;
283
 
284
        state.select();
285
 
286
        length  = 1 + random.nextInt(4);
287
        address = state.next_address_base + random.nextInt(16 - length + 1);
288
 
289
        value   = random.nextLong();
290
        value &= 0xFFFFFFFF;
291
 
292
        write_cycle = 257;
293
        write.write(write_cycle, 0, address, length, false, false, value, this);
294
 
295
        //----------
296
 
297
        LinkedList<Listener> listeners = new LinkedList<>();
298
        listeners.add(avalon);
299
        listeners.add(read);
300
        listeners.add(global);
301
        listeners.add(write);
302
        listeners.add(invalidate);
303
        listeners.add(this);
304
 
305
        run_simulation(listeners);
306
    }
307
 
308
    @Override
309
    public void written(int cycle) throws Exception {
310
 
311
        for(int i=0; i<length; i++) {
312
            expected_values.put(address+i, value & 0xFF);
313
            value >>= 8;
314
        }
315
 
316
        //time of write
317
        //if((cycle - write_cycle) >= 5 && state.next_write_to_cache)         throw new Exception("Expected cache read.");
318
        //if((cycle - write_cycle) < 5 && state.next_write_to_cache == false) throw new Exception("Expected not cache read.");
319
 
320
 
321
        counter++;
322
 
323
        if(counter >= 1000) {
324
            //System.out.println("wbinvd in 20 cycles: " + cycle);
325
            invalidate.wbinvddata(cycle+20, this);
326
            return;
327
        }
328
 
329
        state.select();
330
 
331
        length  = 1 + random.nextInt(4);
332
        address = state.next_address_base + random.nextInt(16 - length + 1);
333
 
334
        value   = random.nextLong();
335
        value &= 0xFFFFFFFF;
336
 
337
        write_cycle = cycle+1;
338
        write.write(write_cycle, 0, address, length, false, false, value, this);
339
    }
340
 
341
    @Override
342
    public void read(int cycle, long data) throws Exception {
343
    }
344
 
345
    @Override
346
    public void read_page_fault(int cycle, long cr2, long error_code) throws Exception {
347
        throw new Exception("read_page_fault: cr2: " + cr2 + ", error_code: " + error_code);
348
    }
349
 
350
    @Override
351
    public void read_ac_fault(int cycle) throws Exception {
352
        throw new Exception("read_ac_fault.");
353
    }
354
    @Override
355
    public void write_page_fault(int cycle, long cr2, long error_code) throws Exception {
356
        throw new Exception("write_page_fault: cr2: " + cr2 + ", error_code: " + error_code);
357
    }
358
    @Override
359
    public void write_ac_fault(int cycle) throws Exception {
360
        throw new Exception("write_ac_fault.");
361
    }
362
 
363
    @Override
364
    public void avalon_write(int cycle, long write_address) throws Exception {
365
        //System.out.printf("avalon_write(): cycle: %d, address: %x\n", cycle, write_address);
366
 
367
        //if writethrough -- ignore avalon write tests
368
        if(global.cr0_nw) return;
369
 
370
        if(invalidate.wbinvddata_active || finish_cycle > 0) {
371
            return;
372
        }
373
 
374
        if(state.next_writeback.isEmpty()) throw new Exception("avalon_write not expected.");
375
 
376
        long writeback_address = state.next_writeback.pop();
377
 
378
        if(writeback_address != write_address) {
379
            throw new Exception(String.format("avalon_write address invalid: state: %x != %x", writeback_address, write_address));
380
        }
381
    }
382
 
383
    @Override
384
    public void set_input(int cycle, Input input) throws Exception {
385
        if(cycle >= finish_cycle && finish_cycle > 0) {
386
            input.finished = true;
387
 
388
            //check writeback empty
389
            if(state.next_writeback.isEmpty() == false && global.cr0_nw == false) throw new Exception("writeback not empty.");
390
 
391
            //check written values
392
            for(long local_address : expected_values.keySet()) {
393
                long memory_data = avalon.get_memory(local_address);
394
                long local_data = expected_values.get(local_address);
395
 
396
                if((local_data & 0xFF) != (memory_data & 0xFF)) {
397
                    throw new Exception(String.format("Value mismatch: local_address: %x, memory_data: %x, local_data: %x\n", local_address, memory_data, local_data));
398
                }
399
            }
400
        }
401
    }
402
 
403
    @Override
404
    public void get_output(int cycle, Output output) throws Exception {
405
    }
406
 
407
    @Override
408
    public void invdcode_finished(int cycle) throws Exception {
409
        throw new Exception("invdcode_finished not expected.");
410
    }
411
    @Override
412
    public void invddata_finished(int cycle) throws Exception {
413
        throw new Exception("invddata_finished not expected.");
414
    }
415
    @Override
416
    public void wbinvddata_finished(int cycle) throws Exception {
417
        finish_cycle = cycle + 20;
418
    }
419
 
420
    int  length;
421
    long address;
422
    long value;
423
 
424
    TestWriteCacheLRUState state;
425
 
426
    Random random;
427
 
428
    int counter;
429
    int write_cycle;
430
 
431
    int finish_cycle;
432
 
433
    HashMap<Long, Long> expected_values; //map address -> value
434
 
435
    AvalonListener      avalon;
436
    ReadListener        read;
437
    WriteListener       write;
438
    InvalidateListener  invalidate;
439
    GlobalListener      global;
440
 
441
    //-------------
442
 
443
    public static void main(String args[]) throws Exception {
444
        TestWriteCacheLRU test1 = new TestWriteCacheLRU();
445
 
446
        for(int i=0; i<10; i++) {
447
            test1.go(i);
448
 
449
            System.out.println("Run " + i + " complete.");
450
        }
451
 
452
        System.out.println("[Main] thread end.");
453
    }
454
}

powered by: WebSVN 2.1.0

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