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

Subversion Repositories wbddr3

[/] [wbddr3/] [trunk/] [bench/] [cpp/] [ddrsdramsim.cpp] - Diff between revs 16 and 18

Only display areas with differences | Details | Blame | View Log

Rev 16 Rev 18
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Filename:    ddrsdramsim.cpp
// Filename:    ddrsdramsim.cpp
//
//
// Project:     A wishbone controlled DDR3 SDRAM memory controller.
// Project:     A wishbone controlled DDR3 SDRAM memory controller.
//
//
// Purpose:     
// Purpose:     
//
//
// Creator:     Dan Gisselquist, Ph.D.
// Creator:     Dan Gisselquist, Ph.D.
//              Gisselquist Technology, LLC
//              Gisselquist Technology, LLC
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
//
//
// This program is free software (firmware): you can redistribute it and/or
// This program is free software (firmware): you can redistribute it and/or
// modify it under the terms of  the GNU General Public License as published
// modify it under the terms of  the GNU General Public License as published
// by the Free Software Foundation, either version 3 of the License, or (at
// by the Free Software Foundation, either version 3 of the License, or (at
// your option) any later version.
// your option) any later version.
//
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
// for more details.
//
//
// You should have received a copy of the GNU General Public License along
// You should have received a copy of the GNU General Public License along
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// with this program.  (It's in the $(ROOT)/doc directory, run make with no
// target there if the PDF file isn't present.)  If not, see
// target there if the PDF file isn't present.)  If not, see
// <http://www.gnu.org/licenses/> for a copy.
// <http://www.gnu.org/licenses/> for a copy.
//
//
// License:     GPL, v3, as defined and found on www.gnu.org,
// License:     GPL, v3, as defined and found on www.gnu.org,
//              http://www.gnu.org/licenses/gpl.html
//              http://www.gnu.org/licenses/gpl.html
//
//
//
//
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//
//
//
//
#include <stdio.h>
#include <stdio.h>
#include <assert.h>
#include <assert.h>
 
 
#include "ddrsdramsim.h"
#include "ddrsdramsim.h"
 
 
#define PREFIX  "DDR3-SDRAM"
#define PREFIX  "DDR3-SDRAM"
const unsigned ckCL = 6,
const unsigned
 
                ckRESET = 64000, // 200us @ 320MHz
 
                ckCKE = 160000, // 500us @ 320MHz
 
                ckCL = 5,
                ckCWL = 5,
                ckCWL = 5,
                ckRP = 6,
                ckRP = 5,
                ckWR = 6,
                ckWR = 5,
                ckRAS = 15,
                ckRAS = 12,
                ckRC = 20,
                ckRC = 16,
                ckMRD = 4,
                ckMRD = 4,
                ckMOD = 12,
                ckMOD = 12,
                ckZQinit = 512,
                ckZQinit = 512,
                ckODT = ckCWL-2,
                ckODT = ckCWL-2,
                ckRFC = 64, // Clocks from refresh to activate
                ckXPR = 56, // Exit reset clocks from CKE HIGH to valid command
                ckREFI = 1560*NWIDTH, // 7.8us @ 200MHz = 7.8e-6 * 200e6 = 1560
                ckRFC = 52, // Clocks from refresh to activate
 
                ckREFI = 2496, // 7.8us @ 320MHz
                DDR_MR2 = 0x0040 | (((ckCWL-5)&7)<<3),
                DDR_MR2 = 0x0040 | (((ckCWL-5)&7)<<3),
                DDR_MR1 = 0x0044,
                DDR_MR1 = 0x0044,
                DDR_MR0 = 0x0000 | (((ckCL-4)&0x07)<<4) | ((ckCL>11)?0x4:0)
                DDR_MR0 = 0x0000 | (((ckCL-4)&0x07)<<4) | ((ckCL>11)?0x4:0)
                                |((ckWR==16)?0
                                |((ckWR==16)?0
                                        :(ckWR>=8)?((((ckWR-8)>>1)+8)<<9)
                                        :(ckWR>=8)?((((ckWR-8)>>1)+8)<<9)
                                        :((ckWR-5+1)<<9)),
                                        :((ckWR-5+1)<<9)),
 
                // Don't pull in any refreshes ...
                nREF = 1;
                nREF = 1;
 
 
BANKINFO::BANKINFO(void) {
BANKINFO::BANKINFO(void) {
        m_state = 0; m_row = 0; m_wcounter = 0; m_min_time_before_precharge=0;
        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:
                case DDR_REFRESH:
                        assert(m_state == 0);
                        assert(m_state == 0);
                        break;
                        break;
                case DDR_PRECHARGE:
                case DDR_PRECHARGE:
                        // assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
                        // assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
                        m_state &= -2;
                        m_state &= -2;
                        // 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) {
                        if (m_min_time_before_precharge != 0) {
                                printf("BANK-FAIL: TIME-BEFORE-PRECHARGE = %d (should be zero)\n", m_min_time_before_precharge);
                                printf("BANK-FAIL: TIME-BEFORE-PRECHARGE = %d (should be zero)\n", m_min_time_before_precharge);
                                assert(m_min_time_before_precharge == 0);
                                assert(m_min_time_before_precharge == 0);
                        } if (m_min_time_before_activate != 0) {
                        } if (m_min_time_before_activate != 0) {
                                printf("BANK-FAIL: TIME-BEFORE-ACTIVATE = %d (should be zero)\n", m_min_time_before_activate);
                                printf("BANK-FAIL: TIME-BEFORE-ACTIVATE = %d (should be zero)\n", m_min_time_before_activate);
                                assert(m_min_time_before_activate==0);
                                assert(m_min_time_before_activate==0);
                        }
                        }
                        */
                        */
                        break;
                        break;
                case DDR_ACTIVATE:
                case DDR_ACTIVATE:
                        assert((m_state&((1<<ckRP)-1)) == 0);
                        // assert((m_state&((1<<ckRP)-1)) == 0);
                        if (((m_state&7)!=0)&&((addr&0x7fff) != m_row)) {
                        if (((m_state&((1<<ckRP)-1))!=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);
                                printf(PREFIX "::BANK-FAIL: Attempt to Activate an already active bank without closing it first (m_state = %x)\n", m_state);
                                assert((m_state&7)==0);
                                // assert((m_state&((1<<ckRP)-1))==0);
 
                        } else if((m_state&((1<<ckRP)-1)) != 0) {
 
                                printf(PREFIX "::DOUBLE-ACTIVATE!!\n");
                        }
                        }
 
 
                        /*
                        /*
                        if (m_wcounter != 0) {
                        if (m_wcounter != 0) {
                                printf("BANK-FAIL: ACTIVATE too soon after write (wcounter = %d)\n", m_wcounter);
                                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) {
                        } if (m_min_time_before_activate!=0) {
                                printf("BANK-FAIL: ACTIVATE too soon after last activate, (ctr=%d)\n", m_min_time_before_activate);
                                printf("BANK-FAIL: ACTIVATE too soon after last activate, (ctr=%d)\n", m_min_time_before_activate);
                                assert(m_min_time_before_activate==0);
                                assert(m_min_time_before_activate==0);
                        }
                        }
                        */
                        */
                        m_state = 1;
                        m_state = 1;
                        m_row = addr & 0x7fff;
                        m_row = addr & 0x7fff;
printf("BANK -- Setting address to %04x\n", m_row);
                        printf(PREFIX "::BANK -- Setting address to %04x\n", m_row);
                        m_min_time_before_precharge = ckRAS;
                        m_min_time_before_precharge = ckRAS;
                        m_min_time_before_activate = ckRC;
                        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;
                        if ((m_state&((1<<ckRP)-1)) != ((1<<ckRP)-1)) {
                        if ((m_state&((1<<ckRP)-1)) != ((1<<ckRP)-1)) {
                                printf(PREFIX "::R/W Error: m_state = %08x, ckRP = %d (%08x)\n",
                                printf(PREFIX "::R/W Error: m_state = %08x, ckRP = %d (%08x)\n",
                                        m_state, ckRP, ((1<<ckRP)-1));
                                        m_state, ckRP, ((1<<ckRP)-1));
                                assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
                                // assert((m_state&((1<<ckRP)-1)) == ((1<<ckRP)-1));
                        }
                        }
                        if (m_min_time_before_precharge)
                        if (m_min_time_before_precharge)
                                m_min_time_before_precharge--;
                                m_min_time_before_precharge--;
                        if (m_min_time_before_activate)
                        if (m_min_time_before_activate)
                                m_min_time_before_activate--;
                                m_min_time_before_activate--;
                        break;
                        break;
                case DDR_ZQS:
                case DDR_ZQS:
                        assert((m_state&((1<<ckRP)-1)) == 0);
                        assert((m_state&((1<<ckRP)-1)) == 0);
                        if (m_min_time_before_precharge)
                        if (m_min_time_before_precharge)
                                m_min_time_before_precharge--;
                                m_min_time_before_precharge--;
                        if (m_min_time_before_activate)
                        if (m_min_time_before_activate)
                                m_min_time_before_activate--;
                                m_min_time_before_activate--;
                        break;
                        break;
                case DDR_NOOP:
                case DDR_NOOP:
 
                        // NO BREAK: Fall through.  On a NOOP we do the same
 
                        // as if the chip were de-selected.
 
                default:
                        m_state <<= 1;
                        m_state <<= 1;
                        m_state |= (m_state&2)>>1;
                        m_state |= (m_state&2)>>1;
                        m_state &= ((1<<ckRP)-1);
                        m_state &= ((1<<ckRP)-1);
 
                        // Else the chip was de-selected, and we only need
 
                        // tick time away -- as in a NOOP.
                        if (m_min_time_before_precharge)
                        if (m_min_time_before_precharge)
                                m_min_time_before_precharge--;
                                m_min_time_before_precharge--;
                        if (m_min_time_before_activate)
                        if (m_min_time_before_activate)
                                m_min_time_before_activate--;
                                m_min_time_before_activate--;
                        break;
                        break;
                default:
 
                        break;
 
        }
        }
}
}
 
 
int gbl_state, gbl_counts;
int gbl_state, gbl_counts;
 
 
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
DDRSDRAMSIM::DDRSDRAMSIM(int lglen) {
        m_memlen = (1<<(lglen-2));
        m_memlen = (1<<(lglen-2));
        m_mem = new unsigned[m_memlen];
        m_mem = new unsigned[m_memlen];
        m_reset_state = 0;
        m_reset_state = 0;
        m_reset_counts= 0;
        m_reset_counts= 0;
        assert(NTIMESLOTS > ckCL+3);
        assert(NTIMESLOTS > ckCL+3);
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
        m_bus = new BUSTIMESLOT[NTIMESLOTS];
        for(int i=0; i<NTIMESLOTS; i++)
        for(int i=0; i<NTIMESLOTS; i++)
                m_bus[i].m_used = 0;
                m_bus[i].m_used = 0;
        for(int i=0; i<NTIMESLOTS; i++)
        for(int i=0; i<NTIMESLOTS; i++)
                m_bus[i].m_rtt = 0;
                m_bus[i].m_rtt = 0;
        m_busloc = 0;
        m_busloc = 0;
}
}
 
 
unsigned DDRSDRAMSIM::apply(int reset_n, int cke,
unsigned DDRSDRAMSIM::apply(int reset_n, int cke,
                int csn, int rasn, int casn, int wen,
                int csn, int rasn, int casn, int wen,
                int dqs, int dm, int odt, int busoe,
                int dqs, int dm, int odt, int busoe,
                int addr, int ba, int data) {
                int addr, int ba, int data) {
        BUSTIMESLOT     *ts, *nxtts;
        BUSTIMESLOT     *ts, *nxtts;
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
        int     cmd = (reset_n?0:32)|(cke?0:16)|(csn?8:0)
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
                        |(rasn?4:0)|(casn?2:0)|(wen?1:0);
 
 
        if ((m_reset_state!=0)&&(reset_n==0)) {
        if ((m_reset_state!=0)&&(reset_n==0)) {
                m_reset_state = 0;
                m_reset_state = 0;
                m_reset_counts = 0;
                m_reset_counts = 0;
        } else if (m_reset_state < 16) {
        } else if (m_reset_state < 16) {
                // printf(PREFIX "::Reset-CMD = %02x,BA=%d,ADDR=%04x, counts = %d\n", cmd, ba, addr, m_reset_counts);
                // printf(PREFIX "::Reset-CMD = %02x,BA=%d,ADDR=%04x, counts = %d\n", cmd, ba, addr, m_reset_counts);
                switch(m_reset_state) {
                switch(m_reset_state) {
                case 0:
                case 0:
                        m_reset_counts++;
                        m_reset_counts++;
                        if (reset_n) {
                        if (reset_n) {
                                assert(m_reset_counts > 40000*NWIDTH);
                                assert(m_reset_counts >= (int)ckRESET);
                                m_reset_counts = 0;
                                m_reset_counts = 0;
                                m_reset_state = 1;
                                m_reset_state = 1;
                        } break;
                        } break;
                case 1:
                case 1:
                        m_reset_counts++;
                        m_reset_counts++;
                        if (cke) {
                        if (cke) {
                                assert(m_reset_counts > 100000*NWIDTH);
                                assert(m_reset_counts >= (int)ckCKE);
                                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);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                assert(m_reset_counts > (int)(ckRFC+2*NWIDTH));
                                assert(m_reset_counts >= (int)ckXPR);
                                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
                                // Set MR2
                                assert(ba == 2);
                                assert(ba == 2);
                                printf(PREFIX "::Checking DDR-MR2(%04x) against %04x\n", addr, DDR_MR2);
                                printf(PREFIX "::Checking DDR-MR2(%04x) against %04x\n", addr, DDR_MR2);
                                assert(addr == DDR_MR2);
                                assert(addr == DDR_MR2);
                        } break;
                        } break;
                case 3:
                case 3:
                        m_reset_counts++;
                        m_reset_counts++;
                        assert(cke);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                assert(m_reset_counts >= (int)ckMRD);
                                assert(m_reset_counts >= (int)ckMRD);
                                m_reset_counts = 0;
                                m_reset_counts = 0;
                                m_reset_state = 4;
                                m_reset_state = 4;
                                assert(cmd == DDR_MRSET);
                                assert(cmd == DDR_MRSET);
                                // Set MR1
                                // Set MR1
                                assert(ba == 1);
                                assert(ba == 1);
                                assert(addr == DDR_MR1);
                                assert(addr == DDR_MR1);
                        } break;
                        } break;
                case 4:
                case 4:
                        m_reset_counts++;
                        m_reset_counts++;
                        assert(cke);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                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 >= (int)ckMRD);
                                assert(m_reset_counts >= (int)ckMRD);
                                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
                                // Set MR0
                                assert(ba == 0);
                                assert(ba == 0);
                                assert(addr == DDR_MR0);
                                assert(addr == DDR_MR0);
                        } break;
                        } break;
                case 5:
                case 5:
                        m_reset_counts++;
                        m_reset_counts++;
                        assert(cke);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                printf(PREFIX "::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                printf(PREFIX "::RESET-CMD[5]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                assert(m_reset_counts >= (int)ckMOD);
                                assert(m_reset_counts >= (int)ckMOD);
                                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);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                printf(PREFIX "::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                printf(PREFIX "::RESET-CMD[6]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                assert(m_reset_counts >= (int)ckZQinit);
                                assert(m_reset_counts >= (int)ckZQinit);
                                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);
                        assert(cke);
                        if (cmd != DDR_NOOP) {
                        if ((cmd != DDR_NOOP)&&(cmd&DDR_DESELECT)==0) {
                                printf(PREFIX "::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                printf(PREFIX "::RESET-CMD[7]: %d:%08x[%d]@0x%04x\n", cmd, m_reset_counts, ba, addr);
                                assert(m_reset_counts >= (int)ckRP);
                                assert(m_reset_counts >= (int)ckRP);
                                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;
                                m_clocks_since_refresh = 0;
                        } break;
                        } break;
                case 8:
                case 8:
                        m_reset_counts++;
                        m_reset_counts++;
                        assert(cke);
                        assert(cke);
                        assert(cmd == DDR_NOOP);
                        assert((cmd == DDR_NOOP)||(cmd&DDR_DESELECT));
                        if (m_reset_counts > (int)ckRFC) {
                        if (m_reset_counts > (int)ckRFC) {
                                m_reset_state = 16;
                                m_reset_state = 16;
                                printf(PREFIX ": Leaving reset state\n");
                                printf(PREFIX ": Leaving reset state\n");
                        }
                        }
                        break;
                        break;
                default:
                default:
                        break;
                        break;
                }
                }
 
 
                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++)
                for(int i=0; i<NBANKS; i++)
                        m_bank[i].tick(cmd, 0);
                        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;
                        if (m_nrefresh_issued >= (int)nREF)
                        if (m_nrefresh_issued >= (int)nREF)
                                m_nrefresh_issued = 1;
                                m_nrefresh_issued = 1;
                        else
                        else
                                m_nrefresh_issued++;
                                m_nrefresh_issued++;
                } 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(cmd,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!!
 
 
                m_clocks_since_refresh++;
                m_clocks_since_refresh++;
                if (m_clocks_since_refresh > (int)ckREFI) {
                if (m_clocks_since_refresh > (int)ckREFI) {
                        printf(PREFIX "::ERROR! Clocks since refresh = %d, which isn\'t less than %d\n", m_clocks_since_refresh, ckREFI);
                        printf(PREFIX "::ERROR! Clocks since refresh = %d, which isn\'t less than %d\n", m_clocks_since_refresh, ckREFI);
                }
                }
                assert(m_clocks_since_refresh <= (int)ckREFI);
                assert(m_clocks_since_refresh <= (int)ckREFI);
                switch(cmd) {
                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;
                        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 & 0x400) {
                        if (addr & 0x400) {
                                // Precharge all
                                // Precharge all
                                printf(PREFIX "::Precharging all banks\n");
                                printf(PREFIX "::Precharging all banks\n");
                                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 {
                                printf(PREFIX "::Precharging bank [%d]\n", ba);
                                printf(PREFIX "::Precharging bank [%d]\n", ba);
                                m_bank[ba].tick(DDR_PRECHARGE,0);
                                m_bank[ba].tick(DDR_PRECHARGE,0);
                                for(int i=0; i<NBANKS; i++)
                                for(int i=0; i<NBANKS; i++)
                                        if (ba != i)
                                        if (ba != i)
                                                m_bank[i].tick(DDR_NOOP,0);
                                                m_bank[i].tick(DDR_NOOP,0);
                        }
                        }
                        break;
                        break;
                case DDR_ACTIVATE:
                case DDR_ACTIVATE:
                        if (m_clocks_since_refresh < (int)ckRFC) {
                        if (m_clocks_since_refresh < (int)ckRFC) {
                                printf(PREFIX "::ACTIVATE -- not enough clocks since refresh, %d < %d should be true\n", m_clocks_since_refresh, ckRFC);
                                printf(PREFIX "::ACTIVATE -- not enough clocks since refresh, %d < %d should be true\n", m_clocks_since_refresh, ckRFC);
                                assert(m_clocks_since_refresh >= (int)ckRFC);
                                assert(m_clocks_since_refresh >= (int)ckRFC);
                        }
                        }
                        printf(PREFIX "::Activating bank %d, address %08x\n", ba, addr);
                        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:
                        {
                        {
                                // This SIM doesn't handle out of order writes
                                // This SIM doesn't handle out of order writes
                                assert((addr&7)==0);
                                assert((addr&7)==0);
                                m_bank[ba].tick(DDR_WRITE, addr);
                                m_bank[ba].tick(DDR_WRITE, addr);
                                for(int i=0; i<NBANKS; i++)
                                for(int i=0; i<NBANKS; i++)
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
                                unsigned caddr = m_bank[ba].m_row;
                                unsigned caddr = m_bank[ba].m_row;
                                caddr <<= 3;
                                caddr <<= 3;
                                caddr |= ba;
                                caddr |= ba;
                                caddr <<= 10;
                                caddr <<= 10;
                                caddr |= addr;
                                caddr |= addr;
                                caddr &= ~7;
                                caddr &= ~7;
                                caddr >>= 1;
                                caddr >>= 1;
 
 
                                BUSTIMESLOT *tp;
                                BUSTIMESLOT *tp;
                                int     offset = m_busloc+ckCWL+1;
                                int     offset = m_busloc+ckCWL+1;
 
 
                                tp = &m_bus[(offset+0)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+0)&(NTIMESLOTS-1)];
                                // printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL);
                                // printf("Setting bus timeslots from (now=%d)+%d=%d to now+%d+3\n", m_busloc, ckCL,(m_busloc+ckCL)&(NTIMESLOTS-1), ckCL);
                                tp->m_addr = caddr  ;
                                tp->m_addr = caddr  ;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 0;
                                tp->m_read = 0;
 
 
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
                                tp->m_addr = caddr+1;
                                tp->m_addr = caddr+1;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 0;
                                tp->m_read = 0;
 
 
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
                                tp->m_addr = caddr+2;
                                tp->m_addr = caddr+2;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 0;
                                tp->m_read = 0;
 
 
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
                                tp->m_addr = caddr+3;
                                tp->m_addr = caddr+3;
                                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
                                // This SIM doesn't handle out of order reads
                                assert((addr&7)==0);
                                assert((addr&7)==0);
                                m_bank[ba].tick(DDR_READ, addr);
                                m_bank[ba].tick(DDR_READ, addr);
                                for(int i=0; i<NBANKS; i++)
                                for(int i=0; i<NBANKS; i++)
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
                                        if (i!=ba)m_bank[i].tick(DDR_NOOP,addr);
                                unsigned caddr = m_bank[ba].m_row;
                                unsigned caddr = m_bank[ba].m_row;
                                caddr <<= 3;
                                caddr <<= 3;
                                caddr |= ba;
                                caddr |= ba;
                                caddr <<= 10;
                                caddr <<= 10;
                                caddr |= addr;
                                caddr |= addr;
                                caddr &= ~7;
                                caddr &= ~7;
                                caddr >>= 1;
                                caddr >>= 1;
 
 
                                BUSTIMESLOT *tp;
                                BUSTIMESLOT *tp;
 
 
                                printf(PREFIX"::READ(%03x:%d:%03x => %08x) Queuing %08x:%08x:%08x:%08x\n",
                                printf(PREFIX"::READ(%03x:%d:%03x => %08x) Queuing %08x:%08x:%08x:%08x\n",
                                        m_bank[ba].m_row, ba, addr,
                                        m_bank[ba].m_row, ba, addr,
                                        caddr,
                                        caddr,
                                        m_mem[caddr  ], m_mem[caddr+1],
                                        m_mem[caddr  ], m_mem[caddr+1],
                                        m_mem[caddr+2], m_mem[caddr+3]);
                                        m_mem[caddr+2], m_mem[caddr+3]);
                                int offset = (m_busloc+ckCL+1)&(NTIMESLOTS-1);
                                int offset = (m_busloc+ckCL+1)&(NTIMESLOTS-1);
                                tp = &m_bus[(offset)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset)&(NTIMESLOTS-1)];
                                tp->m_data = m_mem[caddr];
                                tp->m_data = m_mem[caddr];
                                tp->m_addr = caddr;
                                tp->m_addr = caddr;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 1;
                                tp->m_read = 1;
 
 
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+1)&(NTIMESLOTS-1)];
                                tp->m_data = m_mem[caddr+1];
                                tp->m_data = m_mem[caddr+1];
                                tp->m_addr = caddr+1;
                                tp->m_addr = caddr+1;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 1;
                                tp->m_read = 1;
 
 
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+2)&(NTIMESLOTS-1)];
                                tp->m_data = m_mem[caddr+2];
                                tp->m_data = m_mem[caddr+2];
                                tp->m_addr = caddr+2;
                                tp->m_addr = caddr+2;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 1;
                                tp->m_read = 1;
 
 
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
                                tp = &m_bus[(offset+3)&(NTIMESLOTS-1)];
                                tp->m_data = m_mem[caddr+3];
                                tp->m_data = m_mem[caddr+3];
                                tp->m_addr = caddr+3;
                                tp->m_addr = caddr+3;
                                tp->m_used = 1;
                                tp->m_used = 1;
                                tp->m_read = 1;
                                tp->m_read = 1;
                        } break;
                        } break;
                case DDR_ZQS:
                case DDR_ZQS:
                        assert(0&&"Sim does not support ZQS outside of startup");
                        assert(0&&"Sim does not support ZQS outside of startup");
                        break;
                        break;
                case DDR_NOOP:
                case DDR_NOOP:
                        for(int i=0; i<NBANKS; i++)
                default: // We are deselected
                                m_bank[i].tick(DDR_NOOP,addr);
 
                        break;
 
                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;
                }
                }
 
 
                if (false) {
                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) {
                                        flag = true;
                                        flag = true;
                                        break;
                                        break;
                                }
                                }
                        } if (flag) {
                        } if (flag) {
                        printf(PREFIX "::DQS = %d BUSLOC = %d\n", dqs, (m_busloc+1)&(NTIMESLOTS-1));
                        printf(PREFIX "::DQS = %d BUSLOC = %d\n", dqs, (m_busloc+1)&(NTIMESLOTS-1));
                        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];
                                printf("BUS[%2d] ", bl);
                                printf("BUS[%2d] ", bl);
                                if (nxtts->m_used)
                                if (nxtts->m_used)
                                        printf(" USED");
                                        printf(" USED");
                                if (nxtts->m_read)
                                if (nxtts->m_read)
                                        printf(" READ");
                                        printf(" READ");
                                if (nxtts->m_rtt)
                                if (nxtts->m_rtt)
                                        printf(" RTT");
                                        printf(" RTT");
                                printf("\n");
                                printf("\n");
                        }}
                        }}
                }
                }
 
 
                ts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
                ts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
                if (dqs) {
                if (dqs) {
                        /*
                        if ((!ts->m_rtt)||(!m_last_rtt)) {
                        if ((!ts->m_rtt)||(!m_last_rtt)) {
                                printf(PREFIX "ODT(dqs is true) m_rtt is %s and last_rtt is %s.  Both should be true if DQS.  (ERROR!)\n",
                                printf(PREFIX "ODT(dqs is true) m_rtt is %s and last_rtt is %s.  Both should be true if DQS.  (ERROR!)\n",
                                        (ts->m_rtt)?"true":"false",
                                        (ts->m_rtt)?"true":"false",
                                        (m_last_rtt)?"true":"false");
                                        (m_last_rtt)?"true":"false");
                        }
                        } */
 
                        assert((ts->m_rtt)&&(m_last_rtt));
                        assert((ts->m_rtt)&&(m_last_rtt));
                } else if (!m_last_dqs)
                } // else if (!m_last_dqs)
                        assert(!m_last_rtt);
                //      assert(!m_last_rtt);
        }
        }
 
 
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
        m_busloc = (m_busloc+1)&(NTIMESLOTS-1);
 
 
        ts = &m_bus[m_busloc];
        ts = &m_bus[m_busloc];
        nxtts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
        nxtts = &m_bus[(m_busloc+1)&(NTIMESLOTS-1)];
        unsigned vl = ts->m_data;
        unsigned vl = ts->m_data;
 
 
        assert( ((!ts->m_used)||(busoe))
        /*
                || ((ts->m_used)&&(ts->m_read)&&(!busoe))
        assert( ((!ts->m_used)||(busoe))
                || ((ts->m_used)&&(!ts->m_read)&&(busoe))
                || ((ts->m_used)&&(ts->m_read)&&(!busoe))
                );
                || ((ts->m_used)&&(!ts->m_read)&&(busoe))
 
                );
 
        */
 
 
        m_last_dqs = dqs;
        m_last_dqs = dqs;
        m_last_rtt = ts->m_rtt;
        m_last_rtt = ts->m_rtt;
 
 
        if (ts->m_used) {
        /*
                if (ts->m_read)
        if (ts->m_used) {
                        assert((!dqs)&&(!m_last_dqs));
                if (ts->m_read)
                else
                        assert((!dqs)&&(!m_last_dqs));
                        assert((dqs) && (m_last_dqs));
                else
        } else if (!nxtts->m_used)
                        assert((dqs) && (m_last_dqs));
                assert(!dqs);
        } else if (!nxtts->m_used)
 
                assert(!dqs);
 
        */
 
 
        assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
        // assert((!ts->m_used)||(ts->m_addr < (unsigned)m_memlen));
        if ((ts->m_used)&&(!ts->m_read)&&(dm != 0x0f)) {
        if ((ts->m_used)&&(!ts->m_read)&&(dm != 0x0f)) {
                printf(PREFIX "::Setting MEM[%08x] = %08x (%02x)\n", ts->m_addr, data, dm);
                printf(PREFIX "::Setting MEM[%08x] = %08x (%02x)\n", ts->m_addr, data, dm);
                unsigned mask = 0;
                unsigned mask = 0;
                if (dm&0x08) mask = 0x0ff;
                if (dm&0x08) mask = 0x0ff;
                mask <<= 8; if (dm&0x004) mask |= 0x0ff;
                mask <<= 8; if (dm&0x004) mask |= 0x0ff;
                mask <<= 8; if (dm&0x002) mask |= 0x0ff;
                mask <<= 8; if (dm&0x002) mask |= 0x0ff;
                mask <<= 8; if (dm&0x001) mask |= 0x0ff;
                mask <<= 8; if (dm&0x001) mask |= 0x0ff;
                m_mem[ts->m_addr] = (data & (~mask)) | (m_mem[ts->m_addr]&mask);
                m_mem[ts->m_addr] = (data & (~mask)) | (m_mem[ts->m_addr]&mask);
        } else if ((ts->m_used)&&(ts->m_read)) {
        } else if ((ts->m_used)&&(ts->m_read)) {
                printf(PREFIX ":: %08x\n", vl);
                printf(PREFIX ":: %08x\n", vl);
        }
        }
 
 
        m_bus[(m_busloc+ckODT-1)&(NTIMESLOTS-1)].m_rtt = (odt)&&(reset_n);
        m_bus[(m_busloc+ckODT-1)&(NTIMESLOTS-1)].m_rtt = (odt)&&(reset_n);
        ts->m_used = 0;
        ts->m_used = 0;
        ts->m_read = 0;
        ts->m_read = 0;
        ts->m_addr = -1;
        ts->m_addr = -1;
        ts->m_rtt  = 0;
        ts->m_rtt  = 0;
        return (!busoe)?vl:data;
        return (!busoe)?vl:data;
}
}
 
 
 
 

powered by: WebSVN 2.1.0

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