Line 38... |
Line 38... |
#include <stdio.h>
|
#include <stdio.h>
|
#include <assert.h>
|
#include <assert.h>
|
|
|
#define PREFIX "DDR3-SDRAM"
|
#define PREFIX "DDR3-SDRAM"
|
const unsigned ckCL = 5,
|
const unsigned ckCL = 5,
|
ckRC = 3,
|
ckRC = 10,
|
|
ckRAS = 7,
|
ckRFC = 320, // Clocks from refresh to activate
|
ckRFC = 320, // Clocks from refresh to activate
|
nREF = 4,
|
ckREFI = 1560; // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
|
ckREFI = 1560, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
|
/*
|
ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC;
|
const unsigned nREF = 4,
|
|
ckREFIn = nREF*ckREFI - (nREF-1) * ckRFC;
|
|
*/
|
|
const unsigned nREF = 1,
|
|
ckREFIn = ckREFI;
|
|
|
#include "ddrsdramsim.h"
|
#include "ddrsdramsim.h"
|
|
|
|
BANKINFO::BANKINFO(void) {
|
|
m_state = 0; m_row = 0; m_wcounter = 0; m_min_time_before_precharge=0;
|
|
}
|
|
|
void BANKINFO::tick(int cmd, unsigned addr) {
|
void BANKINFO::tick(int cmd, unsigned addr) {
|
if (m_wcounter)
|
if (m_wcounter)
|
m_wcounter--;
|
m_wcounter--;
|
switch(cmd) {
|
switch(cmd) {
|
|
case DDR_REFRESH:
|
|
assert(m_state == 0);
|
|
break;
|
case DDR_PRECHARGE:
|
case DDR_PRECHARGE:
|
m_state = 6;
|
m_state = 6;
|
// While the specification allows precharging an already
|
// While the specification allows precharging an already
|
// precharged bank, we can keep that from happening
|
// precharged bank, we can keep that from happening
|
// here:
|
// here:
|
// assert(m_state&7);
|
// assert(m_state&7);
|
// Only problem is, this will currently break our
|
// Only problem is, this will currently break our
|
// refresh logic.
|
// refresh logic.
|
|
if (m_min_time_before_precharge != 0) {
|
|
printf("BANK-FAIL: TIME-BEFORE-PRECHARGE = %d (should be zero)\n", m_min_time_before_precharge);
|
|
assert(m_min_time_before_precharge == 0);
|
|
} if (m_min_time_before_activate != 0) {
|
|
printf("BANK-FAIL: TIME-BEFORE-ACTIVATE = %d (should be zero)\n", m_min_time_before_activate);
|
|
assert(m_min_time_before_activate==0);
|
|
}
|
break;
|
break;
|
case DDR_ACTIVATE:
|
case DDR_ACTIVATE:
|
|
if (((m_state&7)!=0)&&((addr&0x7fff) != m_row)) {
|
|
printf("BANK-FAIL: Attempt to Activate an already active bank without closing it first (m_state = %x)\n", m_state);
|
|
assert((m_state&7)==0);
|
|
}
|
|
if (m_wcounter != 0) {
|
|
printf("BANK-FAIL: ACTIVATE too soon after write (wcounter = %d)\n", m_wcounter);
|
assert(m_wcounter == 0);
|
assert(m_wcounter == 0);
|
|
} if (m_min_time_before_activate!=0) {
|
|
printf("BANK-FAIL: ACTIVATE too soon after last activate, (ctr=%d)\n", m_min_time_before_activate);
|
|
assert(m_min_time_before_activate==0);
|
|
}
|
m_state = 1;
|
m_state = 1;
|
m_row = addr & 0x7fff;
|
m_row = addr & 0x7fff;
|
|
m_min_time_before_precharge = ckRAS;
|
|
m_min_time_before_activate = ckRC;
|
break;
|
break;
|
case DDR_READ: case DDR_WRITE:
|
case DDR_READ: case DDR_WRITE:
|
if (DDR_READ)
|
if (DDR_READ)
|
assert(m_wcounter == 0);
|
assert(m_wcounter == 0);
|
else
|
else
|
m_wcounter = 3+4+4;
|
m_wcounter = 3+4+4;
|
printf("BANK::R/W Request, m_state = %d\n", m_state);
|
|
assert((m_state&7) == 7);
|
assert((m_state&7) == 7);
|
|
if (m_min_time_before_precharge)
|
|
m_min_time_before_precharge--;
|
|
if (m_min_time_before_activate)
|
|
m_min_time_before_activate--;
|
break;
|
break;
|
case DDR_ZQS:
|
case DDR_ZQS:
|
assert((m_state&7) == 0);
|
assert((m_state&7) == 0);
|
|
if (m_min_time_before_precharge)
|
|
m_min_time_before_precharge--;
|
|
if (m_min_time_before_activate)
|
|
m_min_time_before_activate--;
|
break;
|
break;
|
case DDR_NOOP:
|
case DDR_NOOP:
|
m_state <<= 1;
|
m_state <<= 1;
|
m_state |= (m_state&2)>>1;
|
m_state |= (m_state&2)>>1;
|
|
m_state &= 0x0f;
|
|
if (m_min_time_before_precharge)
|
|
m_min_time_before_precharge--;
|
|
if (m_min_time_before_activate)
|
|
m_min_time_before_activate--;
|
break;
|
break;
|
default:
|
default:
|
break;
|
break;
|
}
|
}
|
}
|
}
|
Line 133... |
Line 177... |
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);
|
|
// Set MR2
|
assert(ba == 2);
|
assert(ba == 2);
|
assert(addr == 0x040);
|
assert(addr == 0x040);
|
} break;
|
} break;
|
case 3:
|
case 3:
|
m_reset_counts++;
|
m_reset_counts++;
|
Line 144... |
Line 189... |
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);
|
// Set MR1
|
// assert(addr == 0x847);
|
assert(ba == 1);
|
|
assert(addr == 0x844);
|
} break;
|
} break;
|
case 4:
|
case 4:
|
m_reset_counts++;
|
m_reset_counts++;
|
assert(cke);
|
assert(cke);
|
if (cmd != DDR_NOOP) {
|
if (cmd != DDR_NOOP) {
|
printf(PREFIX "::RESET-CMD[4]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
|
printf(PREFIX "::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;
|
assert(cmd == DDR_MRSET);
|
assert(cmd == DDR_MRSET);
|
|
// Set MR0
|
assert(ba == 0);
|
assert(ba == 0);
|
assert(addr == 0x210);
|
assert(addr == 0x210);
|
} break;
|
} break;
|
case 5:
|
case 5:
|
m_reset_counts++;
|
m_reset_counts++;
|
Line 209... |
Line 256... |
|
|
gbl_state = m_reset_state;
|
gbl_state = m_reset_state;
|
gbl_counts= m_reset_counts;
|
gbl_counts= m_reset_counts;
|
m_nrefresh_issued = nREF;
|
m_nrefresh_issued = nREF;
|
m_clocks_since_refresh++;
|
m_clocks_since_refresh++;
|
|
for(int i=0; i<NBANKS; i++)
|
|
m_bank[i].tick(cmd, 0);
|
} else if (!cke) {
|
} else if (!cke) {
|
assert(0&&"Clock not enabled!");
|
assert(0&&"Clock not enabled!");
|
} else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
|
} else if ((cmd == DDR_REFRESH)||(m_nrefresh_issued < (int)nREF)) {
|
if (DDR_REFRESH == cmd) {
|
if (DDR_REFRESH == cmd) {
|
m_clocks_since_refresh = 0;
|
m_clocks_since_refresh = 0;
|
Line 223... |
Line 272... |
} else {
|
} else {
|
m_clocks_since_refresh++;
|
m_clocks_since_refresh++;
|
assert(DDR_NOOP == cmd);
|
assert(DDR_NOOP == cmd);
|
}
|
}
|
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(cmd,0);
|
|
|
if (m_nrefresh_issued == nREF)
|
if (m_nrefresh_issued == nREF)
|
printf(PREFIX "::Refresh cycle complete\n");
|
printf(PREFIX "::Refresh cycle complete\n");
|
} else {
|
} else {
|
// In operational mode!!
|
// In operational mode!!
|
Line 245... |
Line 294... |
m_bank[i].tick(DDR_REFRESH,0);
|
m_bank[i].tick(DDR_REFRESH,0);
|
m_clocks_since_refresh = 0;
|
m_clocks_since_refresh = 0;
|
assert(0 && "Internal err: Refresh should be handled above");
|
assert(0 && "Internal err: Refresh should be handled above");
|
break;
|
break;
|
case DDR_PRECHARGE:
|
case DDR_PRECHARGE:
|
if (addr & 0x40) {
|
if (addr & 0x400) {
|
// Precharge all
|
// Precharge all
|
for(int i=0; i<NBANKS; i++)
|
for(int i=0; i<NBANKS; i++)
|
m_bank[i].tick(DDR_PRECHARGE,0);
|
m_bank[i].tick(DDR_PRECHARGE,0);
|
} else {
|
} else {
|
m_bank[ba].tick(DDR_PRECHARGE,0);
|
m_bank[ba].tick(DDR_PRECHARGE,0);
|
Line 258... |
Line 307... |
m_bank[i].tick(DDR_NOOP,0);
|
m_bank[i].tick(DDR_NOOP,0);
|
}
|
}
|
break;
|
break;
|
case DDR_ACTIVATE:
|
case DDR_ACTIVATE:
|
assert(m_clocks_since_refresh >= (int)ckRFC);
|
assert(m_clocks_since_refresh >= (int)ckRFC);
|
|
printf(PREFIX "::Activating bank %d, address %08x\n", ba, addr);
|
m_bank[ba].tick(DDR_ACTIVATE,addr);
|
m_bank[ba].tick(DDR_ACTIVATE,addr);
|
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:
|
Line 356... |
Line 406... |
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;
|
}
|
}
|
|
|
if (true) {
|
if (false) {
|
bool flag = false;
|
bool flag = false;
|
for(int i=0; i<5; i++) {
|
for(int i=0; i<5; i++) {
|
int bl = (m_busloc+1+i)&(NTIMESLOTS-1);
|
int bl = (m_busloc+1+i)&(NTIMESLOTS-1);
|
nxtts = &m_bus[bl];
|
nxtts = &m_bus[bl];
|
if (nxtts->m_used) {
|
if (nxtts->m_used) {
|