Line 6... |
Line 6... |
|
|
short SDRAMSIM::operator()(int clk, int cke, int cs_n, int ras_n, int cas_n, int we_n,
|
short SDRAMSIM::operator()(int clk, int cke, int cs_n, int ras_n, int cas_n, int we_n,
|
int bs, unsigned addr, int driv, short data) {
|
int bs, unsigned addr, int driv, short data) {
|
short result = 0;
|
short result = 0;
|
|
|
if (driv)
|
if (driv) // If the bus is going out, reads don't make sense ... but
|
result = data;
|
result = data; // read what we output anyway
|
else if (!clk)
|
else if (!clk) // If the clock is zero, return our last value
|
return m_last_value;
|
return m_last_value; // Always called w/clk=1, thus never here
|
if (!cke) {
|
if (!cke) {
|
fprintf(stderr, "This simulation only supports CKE high!\n");
|
fprintf(stderr, "This simulation only supports CKE high!\n");
|
fprintf(stderr, "\tCKE = %d\n", cke);
|
fprintf(stderr, "\tCKE = %d\n", cke);
|
fprintf(stderr, "\tCS_n = %d\n", cs_n);
|
fprintf(stderr, "\tCS_n = %d\n", cs_n);
|
fprintf(stderr, "\tRAS_n = %d\n", ras_n);
|
fprintf(stderr, "\tRAS_n = %d\n", ras_n);
|
Line 27... |
Line 27... |
m_clocks_till_idle--;
|
m_clocks_till_idle--;
|
if (m_pwrup == 0) {
|
if (m_pwrup == 0) {
|
assert((ras_n)&&(cas_n)&&(we_n));
|
assert((ras_n)&&(cas_n)&&(we_n));
|
if (m_clocks_till_idle == 0) {
|
if (m_clocks_till_idle == 0) {
|
m_pwrup++;
|
m_pwrup++;
|
printf("Successful power up wait, moving to state #1\n");
|
// printf("Successful power up wait, moving to state #1\n");
|
}
|
}
|
} else if (m_pwrup == 1) {
|
} else if (m_pwrup == 1) {
|
if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)&&(addr&0x0400)) {
|
if ((!cs_n)&&(!ras_n)&&(cas_n)&&(!we_n)&&(addr&0x0400)) {
|
// Wait until a precharge all banks command
|
// Wait until a precharge all banks command
|
m_pwrup++;
|
m_pwrup++;
|
printf("Successful precharge command, moving to state #2\n");
|
// printf("Successful precharge command, moving to state #2\n");
|
m_clocks_till_idle = 8;
|
m_clocks_till_idle = 8;
|
}
|
}
|
} else if (m_pwrup == 2) {
|
} else if (m_pwrup == 2) {
|
// Need 8 auto refresh cycles before or after the mode
|
// Need 8 auto refresh cycles before or after the mode
|
// set command. We'll insist they be before.
|
// set command. We'll insist they be before.
|
if (m_clocks_till_idle == 0) {
|
if (m_clocks_till_idle == 0) {
|
m_pwrup++;
|
m_pwrup++;
|
printf("Successful initial auto-refresh, waiting for mode-set\n");
|
// printf("Successful initial auto-refresh, waiting for mode-set\n");
|
for(int i=0; i<m_nrefresh; i++)
|
for(int i=0; i<m_nrefresh; i++)
|
m_refresh_time[i] = MAX_REFRESH_TIME;
|
m_refresh_time[i] = MAX_REFRESH_TIME;
|
} else
|
} else
|
assert((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n));
|
assert((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n));
|
} else if (m_pwrup == 3) {
|
} else if (m_pwrup == 3) {
|
const int tRSC = 2;
|
const int tRSC = 2;
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(!we_n)){
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(!we_n)){
|
// mode set
|
// mode set
|
printf("Mode set: %08x\n", addr);
|
// printf("Mode set: %08x\n", addr);
|
assert(addr == 0x021);
|
assert(addr == 0x021);
|
m_pwrup++;
|
m_pwrup++;
|
printf("Successful mode set, moving to state #3, tRSC = %d\n", tRSC);
|
// printf("Successful mode set, moving to state #3, tRSC = %d\n", tRSC);
|
m_clocks_till_idle=tRSC;
|
m_clocks_till_idle=tRSC;
|
}
|
}
|
} else if (m_pwrup == 4) {
|
} else if (m_pwrup == 4) {
|
assert(cs_n);
|
assert(cs_n);
|
if (m_clocks_till_idle == 0) {
|
if (m_clocks_till_idle == 0) {
|
m_pwrup = POWERED_UP_STATE;
|
m_pwrup = POWERED_UP_STATE;
|
m_clocks_till_idle = 0;
|
m_clocks_till_idle = 0;
|
printf("Successful settup! SDRAM switching to operational\n");
|
// printf("Successful settup! SDRAM switching to operational\n");
|
} else if (m_clocks_till_idle == 1) {
|
} else if (m_clocks_till_idle == 1) {
|
;
|
;
|
} else assert(0 && "Should never get here!");
|
} else assert(0 && "Should never get here!");
|
} else if (m_pwrup == 5) {
|
} else if (m_pwrup == 5) {
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
|
Line 108... |
Line 108... |
exit(-3);
|
exit(-3);
|
}
|
}
|
}
|
}
|
|
|
if ((m_clocks_till_idle > 0)&&(m_next_wr)) {
|
if ((m_clocks_till_idle > 0)&&(m_next_wr)) {
|
printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
|
// printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
|
m_mem[m_wr_addr++] = data;
|
m_mem[m_wr_addr++] = data;
|
result = data;
|
result = data;
|
m_next_wr = false;
|
m_next_wr = false;
|
} else {
|
|
result = (driv)?data:m_qdata[m_qloc];
|
|
}
|
}
|
m_qloc = (m_qloc + 1)&m_qmask;
|
m_qloc = (m_qloc + 1)&m_qmask;
|
|
result = (driv)?data:m_qdata[(m_qloc)&m_qmask];
|
|
m_qdata[(m_qloc)&m_qmask] = 0;
|
|
|
|
// if (result != 0)
|
|
// printf("%d RESULT[%3d] = %04x\n", clk, m_qloc, result&0x0ffff);
|
|
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
|
if ((!cs_n)&&(!ras_n)&&(!cas_n)&&(we_n)) {
|
// Auto-refresh command
|
// Auto-refresh command
|
m_refresh_time[m_refresh_loc] = MAX_REFRESH_TIME;
|
m_refresh_time[m_refresh_loc] = MAX_REFRESH_TIME;
|
m_refresh_loc++;
|
m_refresh_loc++;
|
Line 137... |
Line 140... |
} else {
|
} else {
|
// Precharge/close single bank
|
// Precharge/close single bank
|
assert(0 == (bs & (~3))); // Assert w/in bounds
|
assert(0 == (bs & (~3))); // Assert w/in bounds
|
m_bank_status[bs] &= 0x03; // Close the bank
|
m_bank_status[bs] &= 0x03; // Close the bank
|
|
|
printf("Precharging bank %d\n", bs);
|
// printf("Precharging bank %d\n", bs);
|
}
|
}
|
} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(we_n)) {
|
} else if ((!cs_n)&&(!ras_n)&&(cas_n)&&(we_n)) {
|
printf("Activating bank %d\n", bs);
|
// printf("Activating bank %d\n", bs);
|
// Activate a bank!
|
// Activate a bank!
|
if (0 != (bs & (~3))) {
|
if (0 != (bs & (~3))) {
|
m_fail = 2;
|
m_fail = 2;
|
fprintf(stderr, "ERR: Activating a bank w/ more than 2 bits\n");
|
fprintf(stderr, "ERR: Activating a bank w/ more than 2 bits\n");
|
// assert(0 == (bs & (~3))); // Assert w/in bounds
|
// assert(0 == (bs & (~3))); // Assert w/in bounds
|
Line 156... |
Line 159... |
}
|
}
|
m_bank_status[bs] |= 4;
|
m_bank_status[bs] |= 4;
|
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
|
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
|
m_bank_row[bs] = addr;
|
m_bank_row[bs] = addr;
|
} else if ((!cs_n)&&(ras_n)&&(!cas_n)) {
|
} else if ((!cs_n)&&(ras_n)&&(!cas_n)) {
|
printf("R/W Op\n");
|
// printf("R/W Op\n");
|
if (!we_n) {
|
if (!we_n) {
|
// Initiate a write
|
// Initiate a write
|
assert(0 == (bs & (~3))); // Assert w/in bounds
|
assert(0 == (bs & (~3))); // Assert w/in bounds
|
assert(m_bank_status[bs]&1); // Assert bank is open
|
assert(m_bank_status[bs]&1); // Assert bank is open
|
|
|
Line 169... |
Line 172... |
m_wr_addr |= bs;
|
m_wr_addr |= bs;
|
m_wr_addr <<= 9;
|
m_wr_addr <<= 9;
|
m_wr_addr |= (addr & 0x01ff);
|
m_wr_addr |= (addr & 0x01ff);
|
|
|
assert(driv);
|
assert(driv);
|
printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
|
// printf("SDRAM[%08x] <= %04x\n", m_wr_addr, data & 0x0ffff);
|
m_mem[m_wr_addr++] = data;
|
m_mem[m_wr_addr++] = data;
|
m_clocks_till_idle = 2;
|
m_clocks_till_idle = 2;
|
m_next_wr = true;
|
m_next_wr = true;
|
|
|
if (addr & 0x0400) { // Auto precharge
|
if (addr & 0x0400) { // Auto precharge
|
Line 191... |
Line 194... |
rd_addr |= bs;
|
rd_addr |= bs;
|
rd_addr <<= 9;
|
rd_addr <<= 9;
|
rd_addr |= (addr & 0x01ff);
|
rd_addr |= (addr & 0x01ff);
|
|
|
assert(!driv);
|
assert(!driv);
|
printf("SDRAM.Q %04x <= SDRAM[%08x]\n",
|
// printf("SDRAM.Q[%2d] %04x <= SDRAM[%08x]\n",
|
m_mem[rd_addr] & 0x0ffff, rd_addr);
|
// (m_qloc+3)&m_qmask,
|
m_qdata[(m_qloc+1)&m_qmask] = m_mem[rd_addr++];
|
// m_mem[rd_addr] & 0x0ffff, rd_addr);
|
printf("SDRAM.Q %04x <= SDRAM[%08x]\n",
|
m_qdata[(m_qloc+3)&m_qmask] = m_mem[rd_addr++];
|
m_mem[rd_addr] & 0x0ffff, rd_addr);
|
// printf("SDRAM.Q[%2d] %04x <= SDRAM[%08x]\n",
|
m_qdata[(m_qloc+2)&m_qmask] = m_mem[rd_addr++];
|
// (m_qloc+4)&m_qmask,
|
|
// m_mem[rd_addr] & 0x0ffff, rd_addr);
|
|
m_qdata[(m_qloc+4)&m_qmask] = m_mem[rd_addr++];
|
m_clocks_till_idle = 2;
|
m_clocks_till_idle = 2;
|
|
|
if (addr & 0x0400) { // Auto precharge
|
if (addr & 0x0400) { // Auto precharge
|
m_bank_status[bs] &= 3;
|
m_bank_status[bs] &= 3;
|
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
|
m_bank_open_time[bs] = MAX_BANKOPEN_TIME;
|