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

Subversion Repositories wbddr3

[/] [wbddr3/] [trunk/] [bench/] [cpp/] [ddrsdramsim.cpp] - Blame information for rev 6

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 4 dgisselq
////////////////////////////////////////////////////////////////////////////////
2
//
3
// Filename:    ddrsdramsim.cpp
4
//
5
// Project:     A wishbone controlled DDR3 SDRAM memory controller.
6
//
7
// Purpose:     
8
//
9
// Creator:     Dan Gisselquist, Ph.D.
10
//              Gisselquist Technology, LLC
11
//
12
////////////////////////////////////////////////////////////////////////////////
13
//
14
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
15
//
16
// This program is free software (firmware): you can redistribute it and/or
17
// modify it under the terms of  the GNU General Public License as published
18
// by the Free Software Foundation, either version 3 of the License, or (at
19
// your option) any later version.
20
//
21
// This program is distributed in the hope that it will be useful, but WITHOUT
22
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
23
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
24
// for more details.
25
//
26
// You should have received a copy of the GNU General Public License along
27
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
28
// target there if the PDF file isn't present.)  If not, see
29
// <http://www.gnu.org/licenses/> for a copy.
30
//
31
// License:     GPL, v3, as defined and found on www.gnu.org,
32
//              http://www.gnu.org/licenses/gpl.html
33
//
34
//
35
////////////////////////////////////////////////////////////////////////////////
36
//
37
//
38
#include <stdio.h>
39
#include <assert.h>
40
 
41
const unsigned ckCL = 5,
42 6 dgisselq
                ckRC = 3,
43
                ckRFC = 320, // Clocks from refresh to activate
44
                nREF = 4,
45
                ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
46
                ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC;
47 4 dgisselq
 
48
#include "ddrsdramsim.h"
49
void    BANKINFO::tick(int cmd, unsigned addr) {
50
        switch(cmd) {
51
                case DDR_PRECHARGE:
52 6 dgisselq
                        m_state = 6;
53 4 dgisselq
                        break;
54
                case DDR_ACTIVATE:
55 6 dgisselq
                        m_state = 1;
56 4 dgisselq
                        m_row = addr & 0x7fff;
57
                        break;
58
                case DDR_READ: case DDR_WRITE:
59 6 dgisselq
                        printf("BANK::R/W Request, m_state = %d\n", m_state);
60 4 dgisselq
                        assert((m_state&7) == 7);
61
                        break;
62
                case DDR_ZQS:
63
                        assert((m_state&7) == 0);
64
                        break;
65
                case DDR_NOOP:
66
                        m_state <<= 1;
67
                        m_state |= (m_state&2)>>1;
68
                        break;
69
                default:
70
                        break;
71
        }
72
}
73
 
74
int gbl_state, gbl_counts;
75
 
76
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
77
        m_memlen = (1<<(lglen-2));
78
        m_mem = new unsigned[m_memlen];
79
        m_reset_state = 0;
80
        m_reset_counts= 0;
81
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
82
        for(int i=0; i<NTIMESLOTS; i++)
83
                m_bus[i].m_used = 0;
84
        m_busloc = 0;
85
}
86
 
87
unsigned DDRSDRAMSIM::operator()(int reset_n, int cke,
88
                int csn, int rasn, int casn, int wen,
89
                int dqs, int dm, int odt, int busoe,
90
                int addr, int ba, int data) {
91
 
92
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
93
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
94
        if ((m_reset_state!=0)&&(reset_n==0)) {
95
                m_reset_state = 0;
96
                m_reset_counts = 0;
97
        } else if (m_reset_state < 16) {
98
                switch(m_reset_state) {
99
                case 0:
100
                        m_reset_counts++;
101
                        if (reset_n) {
102
                                assert(m_reset_counts > 40000);
103
                                m_reset_counts = 0;
104
                                m_reset_state = 1;
105
                        } break;
106
                case 1:
107
                        m_reset_counts++;
108
                        if (cke) {
109
                                assert(m_reset_counts > 100000);
110
                                m_reset_counts = 0;
111
                                m_reset_state = 2;
112
                        } break;
113
                case 2:
114
                        m_reset_counts++;
115 6 dgisselq
                        assert(cke);
116 4 dgisselq
                        if (cmd != DDR_NOOP) {
117
                                assert(m_reset_counts > 147);
118
                                m_reset_counts = 0;
119
                                m_reset_state = 3;
120
                                assert(cmd == DDR_MRSET);
121
                                assert(ba == 2);
122
                                assert(addr == 0x040);
123
                        } break;
124
                case 3:
125
                        m_reset_counts++;
126 6 dgisselq
                        assert(cke);
127 4 dgisselq
                        if (cmd != DDR_NOOP) {
128 5 dgisselq
                                // assert(m_reset_counts > 3);
129 4 dgisselq
                                m_reset_counts = 0;
130
                                m_reset_state = 4;
131
                                assert(cmd == DDR_MRSET);
132 5 dgisselq
                                // assert(ba == 1);
133
                                // assert(addr == 0x847);
134 4 dgisselq
                        } break;
135
                case 4:
136
                        m_reset_counts++;
137 6 dgisselq
                        assert(cke);
138 4 dgisselq
                        if (cmd != DDR_NOOP) {
139 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
140 4 dgisselq
                                assert(m_reset_counts > 3);
141
                                m_reset_counts = 0;
142
                                m_reset_state = 5;
143
                                assert(cmd == DDR_MRSET);
144
                                assert(ba == 0);
145
                                assert(addr == 0x210);
146
                        } break;
147
                case 5:
148
                        m_reset_counts++;
149 6 dgisselq
                        assert(cke);
150 4 dgisselq
                        if (cmd != DDR_NOOP) {
151 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
152
                                assert(m_reset_counts > 11);
153 4 dgisselq
                                m_reset_counts = 0;
154
                                m_reset_state = 6;
155
                                assert(cmd == DDR_ZQS);
156 5 dgisselq
                                assert(addr == 0x400);
157 4 dgisselq
                        } break;
158
                case 6:
159
                        m_reset_counts++;
160 6 dgisselq
                        assert(cke);
161 4 dgisselq
                        if (cmd != DDR_NOOP) {
162 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
163 4 dgisselq
                                assert(m_reset_counts > 512);
164
                                m_reset_counts = 0;
165
                                m_reset_state = 7;
166
                                assert(cmd == DDR_PRECHARGE);
167 5 dgisselq
                                assert(addr == 0x400);
168 4 dgisselq
                        } break;
169
                case 7:
170
                        m_reset_counts++;
171 6 dgisselq
                        assert(cke);
172 4 dgisselq
                        if (cmd != DDR_NOOP) {
173 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
174 4 dgisselq
                                assert(m_reset_counts > 3);
175
                                m_reset_counts = 0;
176
                                m_reset_state = 8;
177
                                assert(cmd == DDR_REFRESH);
178 6 dgisselq
                                m_clocks_since_refresh = 0;
179 4 dgisselq
                        } break;
180
                case 8:
181
                        m_reset_counts++;
182 6 dgisselq
                        assert(cke);
183 4 dgisselq
                        assert(cmd == DDR_NOOP);
184 5 dgisselq
                        if (m_reset_counts > 140) {
185 4 dgisselq
                                m_reset_state = 16;
186 5 dgisselq
                                printf("DDR3-SDRAM: Leaving reset state\n");
187
                        }
188 4 dgisselq
                        break;
189
                default:
190
                        break;
191
                }
192
 
193
                gbl_state = m_reset_state;
194
                gbl_counts= m_reset_counts;
195 6 dgisselq
                m_nrefresh_issued = nREF;
196
        } else if (!cke) {
197 4 dgisselq
                assert(0&&"Clock not enabled!");
198 6 dgisselq
        } else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
199
                if (DDR_REFRESH == cmd) {
200
                        m_clocks_since_refresh = 0;
201
                        if (m_nrefresh_issued >= (int)nREF)
202
                                m_nrefresh_issued = 0;
203
                        else
204
                                m_nrefresh_issued++;
205
                } else {
206
                        m_clocks_since_refresh++;
207
                        assert(DDR_NOOP == cmd);
208
                }
209
                for(int i=0; i<NBANKS; i++)
210
                        m_bank[i].tick(DDR_REFRESH,0);
211
        } else {
212
                // In operational mode!!
213
 
214
                m_clocks_since_refresh++;
215
                assert(m_clocks_since_refresh < (int)ckREFIn);
216
                switch(cmd) {
217 4 dgisselq
                case DDR_MRSET:
218
                        assert(0&&"Modes should only be set in reset startup");
219
                        for(int i=0; i<NBANKS; i++)
220
                                m_bank[i].tick(DDR_MRSET,0);
221
                        break;
222
                case DDR_REFRESH:
223
                        for(int i=0; i<NBANKS; i++)
224
                                m_bank[i].tick(DDR_REFRESH,0);
225 6 dgisselq
                        m_clocks_since_refresh = 0;
226
                        assert(0 && "Internal err: Refresh should be handled above");
227 4 dgisselq
                        break;
228
                case DDR_PRECHARGE:
229
                        if (addr & 0x40) {
230
                                // Precharge all
231
                                for(int i=0; i<NBANKS; i++)
232
                                        m_bank[i].tick(DDR_PRECHARGE,0);
233
                        } else {
234
                                m_bank[ba].tick(DDR_PRECHARGE,0);
235
                                for(int i=0; i<NBANKS; i++)
236
                                        if (ba != i)
237
                                                m_bank[i].tick(DDR_NOOP,0);
238
                        }
239
                        break;
240
                case DDR_ACTIVATE:
241
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
242
                        for(int i=0; i<NBANKS; i++)
243
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
244
                        break;
245
                case DDR_WRITE:
246
                        {
247 6 dgisselq
                                // This SIM doesn't handle out of order writes
248
                                assert((addr&7)==0);
249
                                m_bank[ba].tick(DDR_WRITE, addr);
250 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
251 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
252 4 dgisselq
                                unsigned addr = m_bank[ba].m_row;
253
                                addr <<= 13;
254
                                addr |= ba;
255
                                addr <<= 10;
256
                                addr |= addr;
257
                                addr &= ~3;
258
 
259
                                BUSTIMESLOT *tp;
260
 
261
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
262
                                tp->m_addr = addr  ;
263
                                tp->m_used = 1;
264
                                tp->m_read = 0;
265
 
266
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
267
                                tp->m_addr = addr+1;
268
                                tp->m_used = 1;
269
                                tp->m_read = 0;
270
 
271
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
272
                                tp->m_addr = addr+2;
273
                                tp->m_used = 1;
274
                                tp->m_read = 0;
275
 
276
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
277
                                tp->m_addr = addr+3;
278
                                tp->m_used = 1;
279
                                tp->m_read = 0;
280
                        } break;
281
                case DDR_READ:
282
                        {
283 6 dgisselq
                                // This SIM doesn't handle out of order reads
284
                                assert((addr&7)==0);
285
                                m_bank[ba].tick(DDR_READ, addr);
286 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
287 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
288 4 dgisselq
                                unsigned addr = m_bank[ba].m_row;
289
                                addr <<= 13;
290
                                addr |= ba;
291
                                addr <<= 10;
292
                                addr |= addr;
293
                                addr &= ~3;
294
 
295
                                BUSTIMESLOT *tp;
296
 
297
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
298
                                tp->m_data = m_mem[addr];
299
                                tp->m_addr = addr;
300
                                tp->m_used = 1;
301
                                tp->m_read = 1;
302
 
303
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
304
                                tp->m_data = m_mem[addr+1];
305
                                tp->m_addr = addr+1;
306
                                tp->m_used = 1;
307
                                tp->m_read = 1;
308
 
309
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
310
                                tp->m_data = m_mem[addr+2];
311
                                tp->m_addr = addr+2;
312
                                tp->m_used = 1;
313
                                tp->m_read = 1;
314
 
315
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
316
                                tp->m_data = m_mem[addr+3];
317
                                tp->m_addr = addr+3;
318
                                tp->m_used = 1;
319
                                tp->m_read = 1;
320
                        } break;
321
                case DDR_ZQS:
322
                        assert(0&&"Sim does not support ZQS outside of startup");
323
                        break;
324
                case DDR_NOOP:
325
                        for(int i=0; i<NBANKS; i++)
326
                                m_bank[i].tick(DDR_NOOP,addr);
327
                        break;
328
                default: // We are deselecteda
329
                        for(int i=0; i<NBANKS; i++)
330
                                m_bank[i].tick(DDR_NOOP,addr);
331
                        break;
332 6 dgisselq
                }
333 4 dgisselq
        }
334
 
335
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
336
 
337
        BUSTIMESLOT     *ts = &m_bus[m_busloc];
338
        unsigned vl = ts->m_data;
339
        assert( ((!ts->m_used)||(busoe))
340
                || ((ts->m_used)&&(ts->m_read)));
341
 
342
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
343
        if ((ts->m_used)&&(!ts->m_read)&&(!dm))
344
                m_mem[ts->m_addr] = data;
345
        ts->m_used = 0;
346
        ts->m_read = 0;
347
        ts->m_addr = -1;
348
        return (!busoe)?vl:data;
349
}
350
 

powered by: WebSVN 2.1.0

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