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

Subversion Repositories wbddr3

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

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 8 dgisselq
                        // While the specification allows precharging an already
54
                        // precharged bank, we can keep that from happening
55
                        // here:
56
                        // assert(m_state&7);
57
                        // Only problem is, this will currently break our
58
                        // refresh logic.
59 4 dgisselq
                        break;
60
                case DDR_ACTIVATE:
61 6 dgisselq
                        m_state = 1;
62 4 dgisselq
                        m_row = addr & 0x7fff;
63
                        break;
64
                case DDR_READ: case DDR_WRITE:
65 6 dgisselq
                        printf("BANK::R/W Request, m_state = %d\n", m_state);
66 4 dgisselq
                        assert((m_state&7) == 7);
67
                        break;
68
                case DDR_ZQS:
69
                        assert((m_state&7) == 0);
70
                        break;
71
                case DDR_NOOP:
72
                        m_state <<= 1;
73
                        m_state |= (m_state&2)>>1;
74
                        break;
75
                default:
76
                        break;
77
        }
78
}
79
 
80
int gbl_state, gbl_counts;
81
 
82
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
83
        m_memlen = (1<<(lglen-2));
84
        m_mem = new unsigned[m_memlen];
85
        m_reset_state = 0;
86
        m_reset_counts= 0;
87
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
88
        for(int i=0; i<NTIMESLOTS; i++)
89
                m_bus[i].m_used = 0;
90
        m_busloc = 0;
91
}
92
 
93
unsigned DDRSDRAMSIM::operator()(int reset_n, int cke,
94
                int csn, int rasn, int casn, int wen,
95
                int dqs, int dm, int odt, int busoe,
96
                int addr, int ba, int data) {
97
 
98
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
99
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
100
        if ((m_reset_state!=0)&&(reset_n==0)) {
101
                m_reset_state = 0;
102
                m_reset_counts = 0;
103
        } else if (m_reset_state < 16) {
104
                switch(m_reset_state) {
105
                case 0:
106
                        m_reset_counts++;
107
                        if (reset_n) {
108
                                assert(m_reset_counts > 40000);
109
                                m_reset_counts = 0;
110
                                m_reset_state = 1;
111
                        } break;
112
                case 1:
113
                        m_reset_counts++;
114
                        if (cke) {
115
                                assert(m_reset_counts > 100000);
116
                                m_reset_counts = 0;
117
                                m_reset_state = 2;
118
                        } break;
119
                case 2:
120
                        m_reset_counts++;
121 6 dgisselq
                        assert(cke);
122 4 dgisselq
                        if (cmd != DDR_NOOP) {
123
                                assert(m_reset_counts > 147);
124
                                m_reset_counts = 0;
125
                                m_reset_state = 3;
126
                                assert(cmd == DDR_MRSET);
127
                                assert(ba == 2);
128
                                assert(addr == 0x040);
129
                        } break;
130
                case 3:
131
                        m_reset_counts++;
132 6 dgisselq
                        assert(cke);
133 4 dgisselq
                        if (cmd != DDR_NOOP) {
134 5 dgisselq
                                // assert(m_reset_counts > 3);
135 4 dgisselq
                                m_reset_counts = 0;
136
                                m_reset_state = 4;
137
                                assert(cmd == DDR_MRSET);
138 5 dgisselq
                                // assert(ba == 1);
139
                                // assert(addr == 0x847);
140 4 dgisselq
                        } break;
141
                case 4:
142
                        m_reset_counts++;
143 6 dgisselq
                        assert(cke);
144 4 dgisselq
                        if (cmd != DDR_NOOP) {
145 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
146 4 dgisselq
                                assert(m_reset_counts > 3);
147
                                m_reset_counts = 0;
148
                                m_reset_state = 5;
149
                                assert(cmd == DDR_MRSET);
150
                                assert(ba == 0);
151
                                assert(addr == 0x210);
152
                        } break;
153
                case 5:
154
                        m_reset_counts++;
155 6 dgisselq
                        assert(cke);
156 4 dgisselq
                        if (cmd != DDR_NOOP) {
157 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
158
                                assert(m_reset_counts > 11);
159 4 dgisselq
                                m_reset_counts = 0;
160
                                m_reset_state = 6;
161
                                assert(cmd == DDR_ZQS);
162 5 dgisselq
                                assert(addr == 0x400);
163 4 dgisselq
                        } break;
164
                case 6:
165
                        m_reset_counts++;
166 6 dgisselq
                        assert(cke);
167 4 dgisselq
                        if (cmd != DDR_NOOP) {
168 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
169 4 dgisselq
                                assert(m_reset_counts > 512);
170
                                m_reset_counts = 0;
171
                                m_reset_state = 7;
172
                                assert(cmd == DDR_PRECHARGE);
173 5 dgisselq
                                assert(addr == 0x400);
174 4 dgisselq
                        } break;
175
                case 7:
176
                        m_reset_counts++;
177 6 dgisselq
                        assert(cke);
178 4 dgisselq
                        if (cmd != DDR_NOOP) {
179 5 dgisselq
                                printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
180 4 dgisselq
                                assert(m_reset_counts > 3);
181
                                m_reset_counts = 0;
182
                                m_reset_state = 8;
183
                                assert(cmd == DDR_REFRESH);
184 6 dgisselq
                                m_clocks_since_refresh = 0;
185 4 dgisselq
                        } break;
186
                case 8:
187
                        m_reset_counts++;
188 6 dgisselq
                        assert(cke);
189 4 dgisselq
                        assert(cmd == DDR_NOOP);
190 5 dgisselq
                        if (m_reset_counts > 140) {
191 4 dgisselq
                                m_reset_state = 16;
192 5 dgisselq
                                printf("DDR3-SDRAM: Leaving reset state\n");
193
                        }
194 4 dgisselq
                        break;
195
                default:
196
                        break;
197
                }
198
 
199
                gbl_state = m_reset_state;
200
                gbl_counts= m_reset_counts;
201 6 dgisselq
                m_nrefresh_issued = nREF;
202 7 dgisselq
                m_clocks_since_refresh++;
203 6 dgisselq
        } else if (!cke) {
204 4 dgisselq
                assert(0&&"Clock not enabled!");
205 6 dgisselq
        } else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
206
                if (DDR_REFRESH == cmd) {
207
                        m_clocks_since_refresh = 0;
208
                        if (m_nrefresh_issued >= (int)nREF)
209 7 dgisselq
                                m_nrefresh_issued = 1;
210 6 dgisselq
                        else
211
                                m_nrefresh_issued++;
212
                } else {
213
                        m_clocks_since_refresh++;
214
                        assert(DDR_NOOP == cmd);
215
                }
216
                for(int i=0; i<NBANKS; i++)
217
                        m_bank[i].tick(DDR_REFRESH,0);
218 7 dgisselq
 
219
                if (m_nrefresh_issued == nREF)
220
                        printf("DDRSDRAM::Refresh cycle complete\n");
221 6 dgisselq
        } else {
222
                // In operational mode!!
223
 
224
                m_clocks_since_refresh++;
225
                assert(m_clocks_since_refresh < (int)ckREFIn);
226
                switch(cmd) {
227 4 dgisselq
                case DDR_MRSET:
228
                        assert(0&&"Modes should only be set in reset startup");
229
                        for(int i=0; i<NBANKS; i++)
230
                                m_bank[i].tick(DDR_MRSET,0);
231
                        break;
232
                case DDR_REFRESH:
233
                        for(int i=0; i<NBANKS; i++)
234
                                m_bank[i].tick(DDR_REFRESH,0);
235 6 dgisselq
                        m_clocks_since_refresh = 0;
236
                        assert(0 && "Internal err: Refresh should be handled above");
237 4 dgisselq
                        break;
238
                case DDR_PRECHARGE:
239
                        if (addr & 0x40) {
240
                                // Precharge all
241
                                for(int i=0; i<NBANKS; i++)
242
                                        m_bank[i].tick(DDR_PRECHARGE,0);
243
                        } else {
244
                                m_bank[ba].tick(DDR_PRECHARGE,0);
245
                                for(int i=0; i<NBANKS; i++)
246
                                        if (ba != i)
247
                                                m_bank[i].tick(DDR_NOOP,0);
248
                        }
249
                        break;
250
                case DDR_ACTIVATE:
251 7 dgisselq
                        printf("DDRSIM::ACTIVE, clocks_since_refresh = %d >= %d\n", m_clocks_since_refresh, ckRFC);
252
                        assert(m_clocks_since_refresh >= (int)ckRFC);
253 4 dgisselq
                        m_bank[ba].tick(DDR_ACTIVATE,addr);
254
                        for(int i=0; i<NBANKS; i++)
255
                                if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
256
                        break;
257
                case DDR_WRITE:
258
                        {
259 6 dgisselq
                                // This SIM doesn't handle out of order writes
260
                                assert((addr&7)==0);
261
                                m_bank[ba].tick(DDR_WRITE, addr);
262 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
263 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
264 7 dgisselq
                                unsigned caddr = m_bank[ba].m_row;
265 8 dgisselq
                                caddr <<= 3;
266 7 dgisselq
                                caddr |= ba;
267
                                caddr <<= 10;
268
                                caddr |= addr;
269
                                caddr &= ~7;
270
                                caddr >>= 1;
271 4 dgisselq
 
272 7 dgisselq
                                printf("DDRSDRAM::WRITE ADDR = %04x|%d|%04x|%d -> %06x\n",
273
                                        m_bank[ba].m_row, ba, addr, 0, caddr);
274
 
275 4 dgisselq
                                BUSTIMESLOT *tp;
276 7 dgisselq
                                int     offset = m_busloc+ckCL+1;
277 4 dgisselq
 
278 7 dgisselq
                                tp = &m_bus[(offset+0)&(NTIMESLOTS-1)];
279
                                printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL);
280
                                tp->m_addr = caddr  ;
281 4 dgisselq
                                tp->m_used = 1;
282
                                tp->m_read = 0;
283
 
284 7 dgisselq
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
285
                                tp->m_addr = caddr+1;
286 4 dgisselq
                                tp->m_used = 1;
287
                                tp->m_read = 0;
288
 
289 7 dgisselq
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
290
                                tp->m_addr = caddr+2;
291 4 dgisselq
                                tp->m_used = 1;
292
                                tp->m_read = 0;
293
 
294 7 dgisselq
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
295
                                tp->m_addr = caddr+3;
296 4 dgisselq
                                tp->m_used = 1;
297
                                tp->m_read = 0;
298
                        } break;
299
                case DDR_READ:
300
                        {
301 6 dgisselq
                                // This SIM doesn't handle out of order reads
302
                                assert((addr&7)==0);
303
                                m_bank[ba].tick(DDR_READ, addr);
304 4 dgisselq
                                for(int i=0; i<NBANKS; i++)
305 6 dgisselq
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
306 7 dgisselq
                                unsigned caddr = m_bank[ba].m_row;
307 8 dgisselq
                                caddr <<= 3;
308 7 dgisselq
                                caddr |= ba;
309
                                caddr <<= 10;
310
                                caddr |= addr;
311
                                caddr &= ~7;
312
                                caddr >>= 1;
313 4 dgisselq
 
314
                                BUSTIMESLOT *tp;
315
 
316 8 dgisselq
                                int offset = (m_busloc+ckCL+1)&(NTIMESLOTS-1);
317
                                tp = &m_bus[(offset)&(NTIMESLOTS-1)];
318 7 dgisselq
                                tp->m_data = m_mem[caddr];
319
                                tp->m_addr = caddr;
320 4 dgisselq
                                tp->m_used = 1;
321
                                tp->m_read = 1;
322
 
323 8 dgisselq
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
324 7 dgisselq
                                tp->m_data = m_mem[caddr+1];
325
                                tp->m_addr = caddr+1;
326 4 dgisselq
                                tp->m_used = 1;
327
                                tp->m_read = 1;
328
 
329 8 dgisselq
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
330 7 dgisselq
                                tp->m_data = m_mem[caddr+2];
331
                                tp->m_addr = caddr+2;
332 4 dgisselq
                                tp->m_used = 1;
333
                                tp->m_read = 1;
334
 
335 8 dgisselq
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
336 7 dgisselq
                                tp->m_data = m_mem[caddr+3];
337
                                tp->m_addr = caddr+3;
338 4 dgisselq
                                tp->m_used = 1;
339
                                tp->m_read = 1;
340
                        } break;
341
                case DDR_ZQS:
342
                        assert(0&&"Sim does not support ZQS outside of startup");
343
                        break;
344
                case DDR_NOOP:
345
                        for(int i=0; i<NBANKS; i++)
346
                                m_bank[i].tick(DDR_NOOP,addr);
347
                        break;
348
                default: // We are deselecteda
349
                        for(int i=0; i<NBANKS; i++)
350
                                m_bank[i].tick(DDR_NOOP,addr);
351
                        break;
352 6 dgisselq
                }
353 4 dgisselq
        }
354
 
355
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
356
 
357
        BUSTIMESLOT     *ts = &m_bus[m_busloc];
358 7 dgisselq
        if (ts->m_used) {
359
                printf("Current timeslot = %2d, used", m_busloc);
360
                if (ts->m_read)
361
                        printf(", read");
362
                printf("\n");
363
        }
364 4 dgisselq
        unsigned vl = ts->m_data;
365
        assert( ((!ts->m_used)||(busoe))
366
                || ((ts->m_used)&&(ts->m_read)));
367
 
368
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
369 7 dgisselq
        if ((ts->m_used)&&(!ts->m_read)&&(!dm)) {
370
                printf("Setting MEM[%08x] = %08x\n", ts->m_addr, data);
371 4 dgisselq
                m_mem[ts->m_addr] = data;
372 7 dgisselq
        }
373 4 dgisselq
        ts->m_used = 0;
374
        ts->m_read = 0;
375
        ts->m_addr = -1;
376
        return (!busoe)?vl:data;
377
}
378
 

powered by: WebSVN 2.1.0

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