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

Subversion Repositories ao486

[/] [ao486/] [trunk/] [ao486_tool/] [src/] [ao486/] [module/] [memory/] [AvalonListener.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;
28
 
29
import java.util.HashMap;
30
import java.util.LinkedList;
31
import java.util.Random;
32
 
33
public class AvalonListener implements Listener {
34
 
35
    public interface AvalonInterface {
36
        void avalon_read(int cycle, long read_address) throws Exception;
37
        void avalon_write(int cycle, long write_address) throws Exception;
38
    }
39
 
40
    public AvalonListener(Random random, AvalonInterface avalon_interface) {
41
        this.random = random;
42
        this.avalon_interface = avalon_interface;
43
 
44
        memory = new HashMap<>();
45
        to_read = new LinkedList<>();
46
    }
47
 
48
    public void set_memory(long address, long value, int length) {
49
        for(int i=0; i<length; i++) {
50
            memory.put(address, (byte)(value & 0xFF));
51
//System.out.printf("[%x] = %x\n", address, value & 0xFF);
52
            address++;
53
            value >>= 8;
54
        }
55
    }
56
 
57
    //-----------------------------
58
 
59
    public int get_memory(long address) {
60
        address &= 0xFFFFFFFF;
61
 
62
        if(memory.containsKey(address) == false) memory.put(address, (byte)random.nextInt());
63
 
64
        byte val = memory.get(address);
65
        return ((int)val) & 0xFF;
66
    }
67
 
68
    // must be continuous '1'
69
    boolean check_write_byteenable(long byteenable) {
70
        byteenable &= 0xF;
71
 
72
        boolean started = false;
73
        for(int i=0; i<4; i++) {
74
            boolean bit = (byteenable & 1) == 1;
75
 
76
            if(bit == false && started && byteenable > 0) return false;
77
            if(bit) started = true;
78
 
79
            byteenable >>= 1;
80
        }
81
        return true;
82
    }
83
 
84
    void append_written(long address, long data, long byteenable) {
85
        byteenable &= 0xF;
86
 
87
        for(int i=0; i<4; i++) {
88
            if((byteenable & 1) == 1) {
89
                memory.put(address+i,(byte)(data & 0xFF));
90
            }
91
 
92
            byteenable >>= 1;
93
            data >>= 8;
94
        }
95
    }
96
 
97
    @Override
98
    public void set_input(int cycle, Input input) throws Exception {
99
 
100
        if(state <= 0) {
101
            input.avm_waitrequest = random.nextInt(4) == 0;
102
        }
103
 
104
        if(state > 0) {
105
            int index = state-1;
106
 
107
            long value =
108
                    (((int)to_read.get(0) & 0xFF)     ) |
109
                    (((int)to_read.get(1) & 0xFF) << 8) |
110
                    (((int)to_read.get(2) & 0xFF) << 16) |
111
                    (((int)to_read.get(3) & 0xFF) << 24);
112
 
113
            input.avm_readdata      = value;
114
            input.avm_waitrequest   = scenario[index] >= 2;
115
            input.avm_readdatavalid = scenario[index] == 1 || scenario[index] == 3;
116
 
117
            if(input.avm_readdatavalid) for(int i=0; i<4; i++) to_read.removeFirst();
118
 
119
            state++;
120
        }
121
 
122
        was_waitrequest = input.avm_waitrequest;
123
    }
124
 
125
    @Override
126
    public void get_output(int cycle, Output output) throws Exception {
127
 
128
        if(output.avm_read && output.avm_write) throw new Exception("avm_read && avm_write");
129
 
130
        if(state == 0 && output.avm_read) {
131
            address    = output.avm_address;
132
            byteenable = output.avm_byteenable;
133
            burstcount = output.avm_burstcount;
134
 
135
            if(byteenable != 0xF) throw new Exception("Invalid read byteenable: " + byteenable);
136
            if(burstcount == 0)   throw new Exception("Invalid read burstcount: " + burstcount);
137
 
138
            state = 1;
139
 
140
            to_read.clear();
141
            for(int i=0; i<burstcount; i++) {
142
                for(int j=0; j<4; j++) to_read.add((byte)get_memory(address + i*4 + j));
143
            }
144
 
145
            LinkedList<Integer> vec = new LinkedList<>();
146
            for(int i=0; i<burstcount; ) {
147
 
148
                int val = random.nextInt(4);
149
                vec.add(val);
150
 
151
                if(val == 1 || val == 3) i++;
152
            }
153
 
154
            scenario = new int[vec.size()];
155
            for(int i=0; i<scenario.length; i++) {
156
                scenario[i] = vec.get(i);
157
                //System.out.println("--- scenario[" + i + "]: " + scenario[i]);
158
            }
159
        }
160
        else if(state > 0 && state > scenario.length) {
161
            avalon_interface.avalon_read(cycle, address);
162
            state = 0;
163
        }
164
        else if(state > 0) {
165
 
166
            if(address != output.avm_address)       throw new Exception(String.format("Invalid read address: %x != %x, cycle: %d, state: %d", address, output.avm_address, cycle, state));
167
            if(byteenable != output.avm_byteenable) throw new Exception("Invalid read byteenable: " + byteenable);
168
            if(burstcount != output.avm_burstcount) throw new Exception("Invalid read burstcount: " + burstcount);
169
 
170
            if(output.avm_write) throw new Exception("Invalid avm_write.");
171
 
172
        }
173
        else if(state == 0 && output.avm_write) {
174
            address    = output.avm_address;
175
            writedata  = output.avm_writedata;
176
            byteenable = output.avm_byteenable;
177
            burstcount = output.avm_burstcount;
178
 
179
            if(check_write_byteenable(byteenable) == false) throw new Exception("Invalid write byteenable: " + byteenable);
180
            if(burstcount == 0)                             throw new Exception("Invalid write burstcount: " + burstcount);
181
 
182
            state = -1;
183
 
184
            if(was_waitrequest == false) {
185
                append_written(address, writedata, byteenable);
186
 
187
                if(state == -burstcount) {
188
                    avalon_interface.avalon_write(cycle, address);
189
                    state = 0;
190
                }
191
                else {
192
                    state--;
193
                }
194
            }
195
            was_write_accepted = was_waitrequest == false;
196
        }
197
        else if(state < 0) {
198
            if(address != output.avm_address)       throw new Exception("Invalid write address: " + address);
199
            if(burstcount != output.avm_burstcount) throw new Exception("Invalid write burstcount: " + burstcount);
200
 
201
            if(was_write_accepted) {
202
                byteenable = output.avm_byteenable;
203
                writedata  = output.avm_writedata;
204
            }
205
            else {
206
                if(byteenable != output.avm_byteenable) throw new Exception("Invalid write byteenable: " + byteenable + ", output.byteenable: " + output.avm_byteenable + ", cycle: " + cycle);
207
                if(writedata  != output.avm_writedata)  throw new Exception("Invalid writedata: " + writedata);
208
            }
209
            was_write_accepted = was_waitrequest == false;
210
 
211
            if(check_write_byteenable(byteenable) == false) throw new Exception("Invalid write byteenable: " + byteenable);
212
 
213
            if(output.avm_write == false) throw new Exception("Invalid avm_write.");
214
 
215
            if(was_waitrequest == false) {
216
                append_written(address - 4*(state+1), writedata, byteenable);
217
 
218
                if(state == -burstcount) {
219
                    avalon_interface.avalon_write(cycle, address);
220
                    state = 0;
221
                }
222
                else {
223
                    state--;
224
                }
225
            }
226
        }
227
    }
228
 
229
    /*
230
    //Input
231
    boolean avm_waitrequest                 = false;
232
    boolean avm_readdatavalid               = false;
233
    long    avm_readdata                    = 0; //32
234
 
235
    //Output
236
    long    avm_address; //32
237
    long    avm_writedata; //32
238
    long    avm_byteenable; //4
239
    long    avm_burstcount; //3
240
    boolean avm_write;
241
    boolean avm_read;
242
    */
243
 
244
    LinkedList<Byte> to_read;
245
    boolean was_waitrequest;
246
 
247
    boolean was_read_accepted;
248
    boolean was_write_accepted;
249
 
250
    long    address;
251
    long    writedata;
252
    long    byteenable;
253
    long    burstcount;
254
 
255
    int state; // 0-idle; 1..- read; -1..- write;
256
    int scenario[]; //0- idle; 1- readdatavalid; 2- waitrequest; 3- readdatavalid && waitrequest
257
 
258
    Random random;
259
 
260
    HashMap<Long, Byte> memory;
261
 
262
    AvalonInterface avalon_interface;
263
}

powered by: WebSVN 2.1.0

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