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

Subversion Repositories wbddr3

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

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 7 dgisselq
                m_clocks_since_refresh++;
197 6 dgisselq
        } else if (!cke) {
198 4 dgisselq
                assert(0&&"Clock not enabled!");
199 6 dgisselq
        } else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
200
                if (DDR_REFRESH == cmd) {
201
                        m_clocks_since_refresh = 0;
202
                        if (m_nrefresh_issued >= (int)nREF)
203 7 dgisselq
                                m_nrefresh_issued = 1;
204 6 dgisselq
                        else
205
                                m_nrefresh_issued++;
206
                } else {
207
                        m_clocks_since_refresh++;
208
                        assert(DDR_NOOP == cmd);
209
                }
210
                for(int i=0; i<NBANKS; i++)
211
                        m_bank[i].tick(DDR_REFRESH,0);
212 7 dgisselq
 
213
                if (m_nrefresh_issued == nREF)
214
                        printf("DDRSDRAM::Refresh cycle complete\n");
215 6 dgisselq
        } else {
216
                // In operational mode!!
217
 
218
                m_clocks_since_refresh++;
219
                assert(m_clocks_since_refresh < (int)ckREFIn);
220 7 dgisselq
                printf("Clocks to refresh should be %4d-%4d = %4d = 0x%04x\n",
221
                        ckREFIn, m_clocks_since_refresh,
222
                        ckREFIn- m_clocks_since_refresh,
223
                        ckREFIn- m_clocks_since_refresh);
224 6 dgisselq
                switch(cmd) {
225 4 dgisselq
                case DDR_MRSET:
226
                        assert(0&&"Modes should only be set in reset startup");
227
                        for(int i=0; i<NBANKS; i++)
228
                                m_bank[i].tick(DDR_MRSET,0);
229
                        break;
230
                case DDR_REFRESH:
231
                        for(int i=0; i<NBANKS; i++)
232
                                m_bank[i].tick(DDR_REFRESH,0);
233 6 dgisselq
                        m_clocks_since_refresh = 0;
234
                        assert(0 && "Internal err: Refresh should be handled above");
235 4 dgisselq
                        break;
236
                case DDR_PRECHARGE:
237
                        if (addr & 0x40) {
238
                                // Precharge all
239
                                for(int i=0; i<NBANKS; i++)
240
                                        m_bank[i].tick(DDR_PRECHARGE,0);
241
                        } else {
242
                                m_bank[ba].tick(DDR_PRECHARGE,0);
243
                                for(int i=0; i<NBANKS; i++)
244
                                        if (ba != i)
245
                                                m_bank[i].tick(DDR_NOOP,0);
246
                        }
247
                        break;
248
                case DDR_ACTIVATE:
249 7 dgisselq
                        printf("DDRSIM::ACTIVE, clocks_since_refresh = %d >= %d\n", m_clocks_since_refresh, ckRFC);
250
                        assert(m_clocks_since_refresh >= (int)ckRFC);
251 4 dgisselq
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
252
                        for(int i=0; i<NBANKS; i++)
253
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
254
                        break;
255
                case DDR_WRITE:
256
                        {
257 6 dgisselq
                                // This SIM doesn't handle out of order writes
258
                                assert((addr&7)==0);
259
                                m_bank[ba].tick(DDR_WRITE, addr);
260 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
261 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
262 7 dgisselq
                                unsigned caddr = m_bank[ba].m_row;
263
                                caddr <<= 13;
264
                                caddr |= ba;
265
                                caddr <<= 10;
266
                                caddr |= addr;
267
                                caddr &= ~7;
268
                                caddr >>= 1;
269 4 dgisselq
 
270 7 dgisselq
                                printf("DDRSDRAM::WRITE ADDR = %04x|%d|%04x|%d -> %06x\n",
271
                                        m_bank[ba].m_row, ba, addr, 0, caddr);
272
 
273 4 dgisselq
                                BUSTIMESLOT *tp;
274 7 dgisselq
                                int     offset = m_busloc+ckCL+1;
275 4 dgisselq
 
276 7 dgisselq
                                tp = &m_bus[(offset+0)&(NTIMESLOTS-1)];
277
                                printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL);
278
                                tp->m_addr = caddr  ;
279 4 dgisselq
                                tp->m_used = 1;
280
                                tp->m_read = 0;
281
 
282 7 dgisselq
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
283
                                tp->m_addr = caddr+1;
284 4 dgisselq
                                tp->m_used = 1;
285
                                tp->m_read = 0;
286
 
287 7 dgisselq
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
288
                                tp->m_addr = caddr+2;
289 4 dgisselq
                                tp->m_used = 1;
290
                                tp->m_read = 0;
291
 
292 7 dgisselq
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
293
                                tp->m_addr = caddr+3;
294 4 dgisselq
                                tp->m_used = 1;
295
                                tp->m_read = 0;
296
                        } break;
297
                case DDR_READ:
298
                        {
299 6 dgisselq
                                // This SIM doesn't handle out of order reads
300
                                assert((addr&7)==0);
301
                                m_bank[ba].tick(DDR_READ, addr);
302 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
303 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
304 7 dgisselq
                                unsigned caddr = m_bank[ba].m_row;
305
                                caddr <<= 13;
306
                                caddr |= ba;
307
                                caddr <<= 10;
308
                                caddr |= addr;
309
                                caddr &= ~7;
310
                                caddr >>= 1;
311 4 dgisselq
 
312
                                BUSTIMESLOT *tp;
313
 
314
                                tp = &m_bus[(m_busloc+ckCL+0)&(NTIMESLOTS-1)];
315 7 dgisselq
                                tp->m_data = m_mem[caddr];
316
                                tp->m_addr = caddr;
317 4 dgisselq
                                tp->m_used = 1;
318
                                tp->m_read = 1;
319
 
320
                                tp = &m_bus[(m_busloc+ckCL+1)&(NTIMESLOTS-1)];
321 7 dgisselq
                                tp->m_data = m_mem[caddr+1];
322
                                tp->m_addr = caddr+1;
323 4 dgisselq
                                tp->m_used = 1;
324
                                tp->m_read = 1;
325
 
326
                                tp = &m_bus[(m_busloc+ckCL+2)&(NTIMESLOTS-1)];
327 7 dgisselq
                                tp->m_data = m_mem[caddr+2];
328
                                tp->m_addr = caddr+2;
329 4 dgisselq
                                tp->m_used = 1;
330
                                tp->m_read = 1;
331
 
332
                                tp = &m_bus[(m_busloc+ckCL+3)&(NTIMESLOTS-1)];
333 7 dgisselq
                                tp->m_data = m_mem[caddr+3];
334
                                tp->m_addr = caddr+3;
335 4 dgisselq
                                tp->m_used = 1;
336
                                tp->m_read = 1;
337
                        } break;
338
                case DDR_ZQS:
339
                        assert(0&&"Sim does not support ZQS outside of startup");
340
                        break;
341
                case DDR_NOOP:
342
                        for(int i=0; i<NBANKS; i++)
343
                                m_bank[i].tick(DDR_NOOP,addr);
344
                        break;
345
                default: // We are deselecteda
346
                        for(int i=0; i<NBANKS; i++)
347
                                m_bank[i].tick(DDR_NOOP,addr);
348
                        break;
349 6 dgisselq
                }
350 4 dgisselq
        }
351
 
352
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
353
 
354
        BUSTIMESLOT     *ts = &m_bus[m_busloc];
355 7 dgisselq
        if (ts->m_used) {
356
                printf("Current timeslot = %2d, used", m_busloc);
357
                if (ts->m_read)
358
                        printf(", read");
359
                printf("\n");
360
        }
361 4 dgisselq
        unsigned vl = ts->m_data;
362
        assert( ((!ts->m_used)||(busoe))
363
                || ((ts->m_used)&&(ts->m_read)));
364
 
365
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
366 7 dgisselq
        if ((ts->m_used)&&(!ts->m_read)&&(!dm)) {
367
                printf("Setting MEM[%08x] = %08x\n", ts->m_addr, data);
368 4 dgisselq
                m_mem[ts->m_addr] = data;
369 7 dgisselq
        }
370 4 dgisselq
        ts->m_used = 0;
371
        ts->m_read = 0;
372
        ts->m_addr = -1;
373
        return (!busoe)?vl:data;
374
}
375
 

powered by: WebSVN 2.1.0

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