Line 37... |
Line 37... |
//
|
//
|
#include <stdio.h>
|
#include <stdio.h>
|
#include <assert.h>
|
#include <assert.h>
|
|
|
const unsigned ckCL = 5,
|
const unsigned ckCL = 5,
|
ckRC = 3;
|
ckRC = 3,
|
|
ckRFC = 320, // Clocks from refresh to activate
|
|
nREF = 4,
|
|
ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
|
|
ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC;
|
|
|
#include "ddrsdramsim.h"
|
#include "ddrsdramsim.h"
|
void BANKINFO::tick(int cmd, unsigned addr) {
|
void BANKINFO::tick(int cmd, unsigned addr) {
|
switch(cmd) {
|
switch(cmd) {
|
case DDR_PRECHARGE:
|
case DDR_PRECHARGE:
|
m_state <<= 1;
|
m_state = 6;
|
// m_state |= 1;
|
|
m_state &= 6;
|
|
break;
|
break;
|
case DDR_ACTIVATE:
|
case DDR_ACTIVATE:
|
m_state <<= 1;
|
m_state = 1;
|
m_state |= 1;
|
|
m_state &= 7;
|
|
m_row = addr & 0x7fff;
|
m_row = addr & 0x7fff;
|
break;
|
break;
|
case DDR_READ: case DDR_WRITE:
|
case DDR_READ: case DDR_WRITE:
|
|
printf("BANK::R/W Request, m_state = %d\n", m_state);
|
assert((m_state&7) == 7);
|
assert((m_state&7) == 7);
|
break;
|
break;
|
case DDR_ZQS:
|
case DDR_ZQS:
|
assert((m_state&7) == 0);
|
assert((m_state&7) == 0);
|
break;
|
break;
|
Line 109... |
Line 110... |
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 2;
|
m_reset_state = 2;
|
} break;
|
} break;
|
case 2:
|
case 2:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
assert(m_reset_counts > 147);
|
assert(m_reset_counts > 147);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 3;
|
m_reset_state = 3;
|
assert(cmd == DDR_MRSET);
|
assert(cmd == DDR_MRSET);
|
assert(ba == 2);
|
assert(ba == 2);
|
assert(addr == 0x040);
|
assert(addr == 0x040);
|
} break;
|
} break;
|
case 3:
|
case 3:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
// assert(m_reset_counts > 3);
|
// assert(m_reset_counts > 3);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 4;
|
m_reset_state = 4;
|
assert(cmd == DDR_MRSET);
|
assert(cmd == DDR_MRSET);
|
// assert(ba == 1);
|
// assert(ba == 1);
|
// assert(addr == 0x847);
|
// assert(addr == 0x847);
|
} break;
|
} break;
|
case 4:
|
case 4:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
printf("DDR3-SDRAM::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
assert(m_reset_counts > 3);
|
assert(m_reset_counts > 3);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 5;
|
m_reset_state = 5;
|
Line 140... |
Line 144... |
assert(ba == 0);
|
assert(ba == 0);
|
assert(addr == 0x210);
|
assert(addr == 0x210);
|
} break;
|
} break;
|
case 5:
|
case 5:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
printf("DDR3-SDRAM::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
assert(m_reset_counts > 11);
|
assert(m_reset_counts > 11);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 6;
|
m_reset_state = 6;
|
assert(cmd == DDR_ZQS);
|
assert(cmd == DDR_ZQS);
|
assert(addr == 0x400);
|
assert(addr == 0x400);
|
} break;
|
} break;
|
case 6:
|
case 6:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
printf("DDR3-SDRAM::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
assert(m_reset_counts > 512);
|
assert(m_reset_counts > 512);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 7;
|
m_reset_state = 7;
|
assert(cmd == DDR_PRECHARGE);
|
assert(cmd == DDR_PRECHARGE);
|
assert(addr == 0x400);
|
assert(addr == 0x400);
|
} break;
|
} break;
|
case 7:
|
case 7:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
printf("DDR3-SDRAM::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
assert(m_reset_counts > 3);
|
assert(m_reset_counts > 3);
|
m_reset_counts = 0;
|
m_reset_counts = 0;
|
m_reset_state = 8;
|
m_reset_state = 8;
|
assert(cmd == DDR_REFRESH);
|
assert(cmd == DDR_REFRESH);
|
|
m_clocks_since_refresh = 0;
|
} break;
|
} break;
|
case 8:
|
case 8:
|
m_reset_counts++;
|
m_reset_counts++;
|
|
assert(cke);
|
assert(cmd == DDR_NOOP);
|
assert(cmd == DDR_NOOP);
|
if (m_reset_counts > 140) {
|
if (m_reset_counts > 140) {
|
m_reset_state = 16;
|
m_reset_state = 16;
|
printf("DDR3-SDRAM: Leaving reset state\n");
|
printf("DDR3-SDRAM: Leaving reset state\n");
|
}
|
}
|
Line 181... |
Line 190... |
break;
|
break;
|
}
|
}
|
|
|
gbl_state = m_reset_state;
|
gbl_state = m_reset_state;
|
gbl_counts= m_reset_counts;
|
gbl_counts= m_reset_counts;
|
} else if (cke == 0) {
|
m_nrefresh_issued = nREF;
|
|
} else if (!cke) {
|
assert(0&&"Clock not enabled!");
|
assert(0&&"Clock not enabled!");
|
} else switch(cmd) {
|
} else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
|
|
if (DDR_REFRESH == cmd) {
|
|
m_clocks_since_refresh = 0;
|
|
if (m_nrefresh_issued >= (int)nREF)
|
|
m_nrefresh_issued = 0;
|
|
else
|
|
m_nrefresh_issued++;
|
|
} else {
|
|
m_clocks_since_refresh++;
|
|
assert(DDR_NOOP == cmd);
|
|
}
|
|
for(int i=0; i<NBANKS; i++)
|
|
m_bank[i].tick(DDR_REFRESH,0);
|
|
} else {
|
|
// In operational mode!!
|
|
|
|
m_clocks_since_refresh++;
|
|
assert(m_clocks_since_refresh < (int)ckREFIn);
|
|
switch(cmd) {
|
case DDR_MRSET:
|
case DDR_MRSET:
|
assert(0&&"Modes should only be set in reset startup");
|
assert(0&&"Modes should only be set in reset startup");
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_MRSET,0);
|
m_bank[i].tick(DDR_MRSET,0);
|
break;
|
break;
|
case DDR_REFRESH:
|
case DDR_REFRESH:
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_REFRESH,0);
|
m_bank[i].tick(DDR_REFRESH,0);
|
|
m_clocks_since_refresh = 0;
|
|
assert(0 && "Internal err: Refresh should be handled above");
|
break;
|
break;
|
case DDR_PRECHARGE:
|
case DDR_PRECHARGE:
|
if (addr & 0x40) {
|
if (addr & 0x40) {
|
// Precharge all
|
// Precharge all
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
Line 212... |
Line 242... |
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
|
if (i!=ba) m_bank[i].tick(DDR_NOOP,0);
|
break;
|
break;
|
case DDR_WRITE:
|
case DDR_WRITE:
|
{
|
{
|
|
// This SIM doesn't handle out of order writes
|
|
assert((addr&7)==0);
|
|
m_bank[ba].tick(DDR_WRITE, addr);
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_WRITE,addr);
|
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
|
unsigned addr = m_bank[ba].m_row;
|
unsigned addr = m_bank[ba].m_row;
|
addr <<= 13;
|
addr <<= 13;
|
addr |= ba;
|
addr |= ba;
|
addr <<= 10;
|
addr <<= 10;
|
addr |= addr;
|
addr |= addr;
|
Line 245... |
Line 278... |
tp->m_used = 1;
|
tp->m_used = 1;
|
tp->m_read = 0;
|
tp->m_read = 0;
|
} break;
|
} break;
|
case DDR_READ:
|
case DDR_READ:
|
{
|
{
|
|
// This SIM doesn't handle out of order reads
|
|
assert((addr&7)==0);
|
|
m_bank[ba].tick(DDR_READ, addr);
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_READ,addr);
|
if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
|
unsigned addr = m_bank[ba].m_row;
|
unsigned addr = m_bank[ba].m_row;
|
addr <<= 13;
|
addr <<= 13;
|
addr |= ba;
|
addr |= ba;
|
addr <<= 10;
|
addr <<= 10;
|
addr |= addr;
|
addr |= addr;
|
Line 292... |
Line 328... |
default: // We are deselecteda
|
default: // We are deselecteda
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_NOOP,addr);
|
m_bank[i].tick(DDR_NOOP,addr);
|
break;
|
break;
|
}
|
}
|
|
}
|
|
|
m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
|
m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
|
|
|
BUSTIMESLOT *ts = &m_bus[m_busloc];
|
BUSTIMESLOT *ts = &m_bus[m_busloc];
|
unsigned vl = ts->m_data;
|
unsigned vl = ts->m_data;
|