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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [ao486_tool/] [src/] [ao486/] [module/] [memory/] [test/] [TestTLBReadWriteAccess.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.Listener;
33
import ao486.module.memory.Output;
34
import ao486.module.memory.ReadListener;
35
import ao486.module.memory.Test;
36
import ao486.module.memory.WriteListener;
37
import java.util.HashSet;
38
import java.util.LinkedList;
39
import java.util.Random;
40
 
41
class TestTLBReadWriteAccessState {
42
 
43
    TestTLBReadWriteAccessState(Random random) {
44
        this.random = random;
45
 
46
        do {
47
            cr3_base = random.nextLong();
48
            cr3_base &= 0xFFFFF000L;
49
        } while(Test.address_not_in_cache(cr3_base) || Test.address_not_in_cache(cr3_base + 0x1000L));
50
 
51
        cr3_pwt = true;
52
        cr3_pcd = true;
53
 
54
        linear_set = new HashSet<>();
55
    }
56
 
57
    boolean overlap(long a1, long a2, long b1, long b2) {
58
        if(b2 <= a2 && b2 >= a1) return true;
59
        if(b1 <= a2 && b1 >= a1) return true;
60
        return false;
61
    }
62
 
63
    void prepare(AvalonListener avalon) {
64
 
65
        //pde
66
        do {
67
            pde = random.nextLong();
68
            pde &= 0xFFFFF000L;
69
        } while(Test.address_not_in_cache(pde) || Test.address_not_in_cache(pde + 0x1000L) || overlap(cr3_base, cr3_base+ 0x1000L, pde, pde + 0x1000L));
70
 
71
        pde_pwt     = true;
72
        pde_pcd     = true;
73
        pde_present = random.nextInt(3) != 0;
74
        pde_rw      = random.nextBoolean();
75
        pde_su      = random.nextBoolean();
76
        pde_accessed= random.nextBoolean();
77
 
78
        //pte
79
        do {
80
            pte = random.nextLong();
81
            pte &= 0xFFFFF000L;
82
        } while(Test.address_not_in_cache(pte) || Test.address_not_in_cache(pte + 0x1000L) ||
83
                overlap(cr3_base, cr3_base+ 0x1000L, pte, pte + 0x1000L) || overlap(pde, pde+ 0x1000L, pte, pte + 0x1000L));
84
 
85
        pte_pwt     = true;
86
        pte_pcd     = true;
87
        pte_present = random.nextInt(3) != 0;
88
        pte_rw      = random.nextBoolean();
89
        pte_su      = random.nextBoolean();
90
        pte_accessed= random.nextBoolean();
91
        pte_dirty   = random.nextBoolean();
92
 
93
        //linear
94
        do {
95
            linear = random.nextLong();
96
            linear &= 0xFFFFFFFFL;
97
        } while(linear_set.contains(linear & 0xFFFFF000L));
98
 
99
        linear_set.add(linear & 0xFFFFF000L);
100
 
101
        linear_pde = (linear >> 22) & 0x3FFL;
102
        linear_pte = (linear >> 12) & 0x3FFL;
103
 
104
        length = (int)(16 - (linear & 0xFL));
105
        if(length > 4) length = 4;
106
        length = 1 + random.nextInt(length);
107
 
108
        physical = pte | (linear & 0xFFFL);
109
 
110
        //----------
111
 
112
        long pde_value = pde;
113
        if(pde_present) pde_value |= 0x1L;
114
        if(pde_rw)      pde_value |= 0x2L;
115
        if(pde_su)      pde_value |= 0x4L;
116
        if(pde_pwt)     pde_value |= 0x8L;
117
        if(pde_pcd)     pde_value |= 0x10L;
118
        if(pde_accessed)pde_value |= 0x20L;
119
 
120
        avalon.set_memory(cr3_base | (linear_pde << 2), pde_value, 4);
121
 
122
        long pte_value = pte;
123
        if(pte_present) pte_value |= 0x1L;
124
        if(pte_rw)      pte_value |= 0x2L;
125
        if(pte_su)      pte_value |= 0x4L;
126
        if(pte_pwt)     pte_value |= 0x8L;
127
        if(pte_pcd)     pte_value |= 0x10L;
128
        if(pte_accessed)pte_value |= 0x20L;
129
        if(pte_dirty)   pte_value |= 0x40L;
130
 
131
        avalon.set_memory(pde | (linear_pte << 2), pte_value, 4);
132
    }
133
 
134
    boolean should_page_fault(int cpl, boolean is_write, boolean cr0_wp) {
135
 
136
        boolean tlb_rw = pde_rw && pte_rw;
137
        boolean tlb_su = pde_su && pte_su;
138
 
139
        //System.out.println("tlb_rw: " + tlb_rw + ", tlb_su: " + tlb_su + ", cpl: " + cpl + ", is_write: " + is_write +
140
        //                   ", pde_present: " + pde_present + ", pte_present: " + pte_present);
141
 
142
        if(pde_present == false) return true;
143
        if(pte_present == false) return true;
144
 
145
        if(cpl == 3 && tlb_su == false) return true;
146
 
147
        if(cpl == 3 && tlb_su && tlb_rw == false && is_write) return true;
148
 
149
        if(cr0_wp && cpl != 3 && tlb_rw == false && is_write) return true;
150
 
151
        return false;
152
    }
153
 
154
    Random random;
155
 
156
    long cr3_base;
157
    boolean cr3_pwt;
158
    boolean cr3_pcd;
159
 
160
    long pde;
161
    boolean pde_pwt;
162
    boolean pde_pcd;
163
    boolean pde_present;
164
    boolean pde_rw;
165
    boolean pde_su;
166
    boolean pde_accessed;
167
 
168
    long pte;
169
    boolean pte_pwt;
170
    boolean pte_pcd;
171
    boolean pte_present;
172
    boolean pte_rw;
173
    boolean pte_su;
174
    boolean pte_accessed;
175
    boolean pte_dirty;
176
 
177
    long linear;
178
    long linear_pde;
179
    long linear_pte;
180
 
181
    long physical;
182
 
183
    int length;
184
 
185
    HashSet<Long> linear_set;
186
}
187
 
188
public class TestTLBReadWriteAccess extends Test implements Listener, ReadListener.ReadInterface, WriteListener.WriteInterface {
189
 
190
    void go(long seed) throws Exception {
191
        random = new Random(seed);
192
 
193
        avalon = new AvalonListener(random, this);
194
        read   = new ReadListener();
195
        write  = new WriteListener();
196
        global = new GlobalListener();
197
 
198
        finish_cycle = 0;
199
        counter = 1;
200
 
201
        state = new TestTLBReadWriteAccessState(random);
202
 
203
        global.set(true, random.nextBoolean(), false, true, true, false, state.cr3_base, state.cr3_pcd, state.cr3_pwt, true, false);
204
 
205
//System.out.printf("addr: %x\n", pde | (linear_pde << 2));
206
 
207
        state.prepare(avalon);
208
 
209
        is_write = random.nextBoolean();
210
        cpl = random.nextInt(4);
211
 
212
        if(is_write) {
213
            write.write(4, cpl, state.linear, state.length, false, false, random.nextLong() & 0xFFFFFFFFL, this);
214
        }
215
        else {
216
            read.read(4, cpl, state.linear, state.length, false, false, this);
217
        }
218
        //----------
219
 
220
        LinkedList<Listener> listeners = new LinkedList<>();
221
        listeners.add(avalon);
222
        listeners.add(read);
223
        listeners.add(write);
224
        listeners.add(global);
225
        listeners.add(this);
226
 
227
        run_simulation(listeners);
228
    }
229
    @Override
230
    public void read(int cycle, long data) throws Exception {
231
        //System.out.printf("Read value: %x from linear/physical %x/%x size %d\n", data, state.linear, state.physical, state.length);
232
 
233
        boolean should_pf = state.should_page_fault(cpl, is_write, global.cr0_wp);
234
        if(should_pf) throw new Exception("read() but should page fault.");
235
 
236
        counter++;
237
 
238
        if(counter >= 1000) {
239
            finish_cycle = cycle+1;
240
            return;
241
        }
242
 
243
        state.prepare(avalon);
244
 
245
        is_write = random.nextBoolean();
246
        cpl = random.nextInt(4);
247
 
248
        if(is_write) {
249
            write.write(cycle+1, cpl, state.linear, state.length, false, false, random.nextLong() & 0xFFFFFFFFL, this);
250
        }
251
        else {
252
            read.read(cycle+1, cpl, state.linear, state.length, false, false, this);
253
        }
254
    }
255
 
256
    @Override
257
    public void read_page_fault(int cycle, long cr2, long error_code) throws Exception {
258
        boolean should_pf = state.should_page_fault(cpl, is_write, global.cr0_wp);
259
        if(should_pf == false) throw new Exception("read_page_fault() but should not page fault.");
260
 
261
        counter++;
262
 
263
        if(counter >= 1000) {
264
            finish_cycle = cycle+1;
265
            return;
266
        }
267
 
268
        finish_reset_cycle = cycle+1;
269
        global.set_reset(false, true, false, false);
270
 
271
        state.prepare(avalon);
272
 
273
        is_write = random.nextBoolean();
274
        cpl = random.nextInt(4);
275
 
276
        if(is_write) {
277
            write.write(cycle+3, cpl, state.linear, state.length, false, false, random.nextLong() & 0xFFFFFFFFL, this);
278
        }
279
        else {
280
            read.read(cycle+3, cpl, state.linear, state.length, false, false, this);
281
        }
282
    }
283
    @Override
284
    public void read_ac_fault(int cycle) throws Exception {
285
        throw new Exception("read_ac_fault.");
286
    }
287
 
288
    @Override
289
    public void written(int cycle) throws Exception {
290
        boolean should_pf = state.should_page_fault(cpl, is_write, global.cr0_wp);
291
        if(should_pf) throw new Exception("written() but should page fault.");
292
 
293
        counter++;
294
 
295
        if(counter >= 1000) {
296
            finish_cycle = cycle+1;
297
            return;
298
        }
299
 
300
        state.prepare(avalon);
301
 
302
        is_write = random.nextBoolean();
303
        cpl = random.nextInt(4);
304
 
305
        if(is_write) {
306
            write.write(cycle+1, cpl, state.linear, state.length, false, false, random.nextLong() & 0xFFFFFFFFL, this);
307
        }
308
        else {
309
            read.read(cycle+1, cpl, state.linear, state.length, false, false, this);
310
        }
311
    }
312
    @Override
313
    public void write_page_fault(int cycle, long cr2, long error_code) throws Exception {
314
        boolean should_pf = state.should_page_fault(cpl, is_write, global.cr0_wp);
315
        if(should_pf == false) throw new Exception("write_page_fault() but should not page fault: cpl: " + cpl + ", is_write: " + is_write + ", cr0_wp: " + global.cr0_wp );
316
 
317
        counter++;
318
 
319
        if(counter >= 1000) {
320
            finish_cycle = cycle+1;
321
            return;
322
        }
323
 
324
        finish_reset_cycle = cycle+1;
325
        global.set_reset(false, false, false, true);
326
 
327
        state.prepare(avalon);
328
 
329
        is_write = random.nextBoolean();
330
        cpl = random.nextInt(4);
331
 
332
        if(is_write) {
333
            write.write(cycle+3, cpl, state.linear, state.length, false, false, random.nextLong() & 0xFFFFFFFFL, this);
334
        }
335
        else {
336
            read.read(cycle+3, cpl, state.linear, state.length, false, false, this);
337
        }
338
    }
339
    @Override
340
    public void write_ac_fault(int cycle) throws Exception {
341
        throw new Exception("write_ac_fault.");
342
    }
343
 
344
    @Override
345
    public void set_input(int cycle, Input input) throws Exception {
346
        if(cycle >= finish_cycle && finish_cycle > 0) {
347
            input.finished = true;
348
        }
349
 
350
        if(cycle >= finish_reset_cycle && finish_reset_cycle > 0) {
351
            global.set_reset(false, false, false, false);
352
            finish_reset_cycle = 0;
353
        }
354
    }
355
 
356
    @Override
357
    public void get_output(int cycle, Output output) throws Exception {
358
    }
359
 
360
    @Override
361
    public void avalon_read(int cycle, long read_address) throws Exception {
362
    }
363
 
364
    int counter;
365
    Random random;
366
 
367
    int finish_cycle;
368
 
369
    TestTLBReadWriteAccessState state;
370
 
371
    int finish_reset_cycle;
372
    boolean is_write;
373
    int cpl;
374
 
375
    AvalonListener avalon;
376
    ReadListener   read;
377
    WriteListener  write;
378
    GlobalListener global;
379
 
380
    //-------------
381
 
382
    public static void main(String args[]) throws Exception {
383
        TestTLBReadWriteAccess test1 = new TestTLBReadWriteAccess();
384
 
385
        for(int i=0; i<100; i++) {
386
            test1.go(i);
387
 
388
            System.out.println("Run " + i + " complete.");
389
        }
390
 
391
        System.out.println("[Main] thread end.");
392
    }
393
}

powered by: WebSVN 2.1.0

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