URL
https://opencores.org/ocsvn/wbddr3/wbddr3/trunk
Subversion Repositories wbddr3
[/] [wbddr3/] [trunk/] [bench/] [cpp/] [ddrsdram_tb.cpp] - Rev 18
Compare with Previous | Blame | View Log
//////////////////////////////////////////////////////////////////////////////// // // Filename: ddrsdram_tb.cpp // // Project: A wishbone controlled DDR3 SDRAM memory controller. // // Purpose: To determine whether or not the wbddrsdram Verilog module works. // Run this program with no arguments. If the last line output // is "SUCCESS", you will know it works. // // Creator: Dan Gisselquist, Ph.D. // Gisselquist Technology, LLC // //////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2015-2016, Gisselquist Technology, LLC // // 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 // by the Free Software Foundation, either version 3 of the License, or (at // your option) any later version. // // This program is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // 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 // target there if the PDF file isn't present.) If not, see // <http://www.gnu.org/licenses/> for a copy. // // License: GPL, v3, as defined and found on www.gnu.org, // http://www.gnu.org/licenses/gpl.html // // //////////////////////////////////////////////////////////////////////////////// // // #include <stdio.h> #include "verilated.h" #include "Vwbddrsdram.h" #include "pddrsim.h" // #include "ddrsdramsim.h" const int BOMBCOUNT = 512, SDRAMMASK = 0x0ffffff, LGMEMSIZE = 28; char cmdchar(int cmd) { const char cmdstr[] = { 'M', 'R', 'P', 'A', 'W', 'R', 'Z', 'n' }; // Try to decode a six bit bit-mask field into a command if (cmd&32) return 'Z'; else if (cmd&16) return '-'; else if (cmd&8) return '.'; else return cmdstr[cmd]; } class DDRSDRAM_TB { long m_tickcount; Vwbddrsdram *m_core; PDDRSIM *m_sdram; bool m_bomb; public: DDRSDRAM_TB(void) { m_core = new Vwbddrsdram; m_sdram= new PDDRSIM(LGMEMSIZE); } unsigned operator[](const int index) { return (*m_sdram)[index]; } void set(unsigned addr, unsigned v) { m_sdram->set(addr, v); } void tick(void) { m_core->i_clk = 1; (*m_sdram)( m_core->o_ddr_reset_n, m_core->o_ddr_cke, m_core->o_ddr_bus_oe, m_core->o_ddr_cmd_a, m_core->o_ddr_cmd_b, m_core->o_ddr_cmd_c, m_core->o_ddr_cmd_d, m_core->o_ddr_data, m_core->i_ddr_data); bool writeout = (!m_core->v__DOT__reset_override); int cmda, cmdb, cmdc, cmdd; cmda = (m_core->o_ddr_reset_n?0:32) |(m_core->o_ddr_cke?0:16) |((m_core->o_ddr_cmd_a&(1<<26))?8:0) |((m_core->o_ddr_cmd_a&(1<<25))?4:0) |((m_core->o_ddr_cmd_a&(1<<24))?2:0) |((m_core->o_ddr_cmd_a&(1<<23))?1:0); cmdb = (m_core->o_ddr_reset_n?0:32) |(m_core->o_ddr_cke?0:16) |((m_core->o_ddr_cmd_b&(1<<26))?8:0) |((m_core->o_ddr_cmd_b&(1<<25))?4:0) |((m_core->o_ddr_cmd_b&(1<<24))?2:0) |((m_core->o_ddr_cmd_b&(1<<23))?1:0); cmdc = (m_core->o_ddr_reset_n?0:32) |(m_core->o_ddr_cke?0:16) |((m_core->o_ddr_cmd_c&(1<<26))?8:0) |((m_core->o_ddr_cmd_c&(1<<25))?4:0) |((m_core->o_ddr_cmd_c&(1<<24))?2:0) |((m_core->o_ddr_cmd_c&(1<<23))?1:0); cmdd = (m_core->o_ddr_reset_n?0:32) |(m_core->o_ddr_cke?0:16) |((m_core->o_ddr_cmd_d&(1<<26))?8:0) |((m_core->o_ddr_cmd_d&(1<<25))?4:0) |((m_core->o_ddr_cmd_d&(1<<24))?2:0) |((m_core->o_ddr_cmd_d&(1<<23))?1:0); if (writeout) { printf("%08lx-WB: %s/%s %s%s%s %s@0x%08x[", m_tickcount, (m_core->i_wb_cyc)?"CYC":" ", (m_core->i_wb_stb)?"STB":" ", (m_core->o_wb_stall)?"STALL":" ", (m_core->o_wb_ack)?"ACK":" ", (m_core->o_bus)?"BUS":" ", (m_core->i_wb_we)?"W":"R", (m_core->i_wb_addr)); printf(".%02x:.%02x:.%04x:%08x/.%02x:.%02x:.%04x:%08x] -- ", (m_core->i_wb_data[3]&0x000ff), (m_core->i_wb_data[2]&0x0ff), (m_core->i_wb_data[1]&0x0ffff), (m_core->i_wb_data[0]), (m_core->o_wb_data[3]&0x000ff), (m_core->o_wb_data[2]&0x0ff), (m_core->o_wb_data[1]&0x0ffff), (m_core->o_wb_data[0])); printf("%s%s %c%c%c%c %s%s%s%s[%x%x%x%x]%s ", (m_core->o_ddr_reset_n)?" ":"R", (m_core->o_ddr_cke)?"CK":" ", cmdchar(cmda), cmdchar(cmdb), cmdchar(cmdc), cmdchar(cmdd), // // Drive DQS? ((m_core->o_ddr_cmd_a>>5)&1)?"D":"-", ((m_core->o_ddr_cmd_b>>5)&1)?"D":"-", ((m_core->o_ddr_cmd_c>>5)&1)?"D":"-", ((m_core->o_ddr_cmd_d>>5)&1)?"D":"-", // // The data mask ((m_core->o_ddr_cmd_a>>1)&0x0f), ((m_core->o_ddr_cmd_b>>1)&0x0f), ((m_core->o_ddr_cmd_c>>1)&0x0f), ((m_core->o_ddr_cmd_d>>1)&0x0f), // // Drive ODT? (m_core->o_ddr_cmd_a&1)?"O":" "); printf(" C%xA%x", m_core->v__DOT__cmd_pipe, m_core->v__DOT__nxt_pipe); // // Now the 4 bank addresses printf(" B[%d,%d,%d,%d]@%04x ", (m_core->o_ddr_cmd_a>>(6+14))&0x07, // Get the bank address (m_core->o_ddr_cmd_b>>(6+14))&0x07, // Get the bank address (m_core->o_ddr_cmd_c>>(6+14))&0x07, // Get the bank address (m_core->o_ddr_cmd_d>>(6+14))&0x07, // Get the bank address ((m_core->o_ddr_cmd_d>>6)&0x03fff));// The command address printf(".%02x:.%02x:.%04x:%08x .%02x:.%02x:.%04x:%08x", (m_core->i_ddr_data[3]&0x0ff),(m_core->i_ddr_data[2]&0x0ff), (m_core->i_ddr_data[1]&0x0ffff),(m_core->i_ddr_data[0]), (m_core->o_ddr_data[3]&0x0ff),(m_core->o_ddr_data[2]&0x0ff), (m_core->o_ddr_data[1]&0x0ffff), (m_core->o_ddr_data[0])); printf(" FIFO[%x,%x](%02x:%02x:%04x:%08x)", m_core->v__DOT__bus_fifo_head, m_core->v__DOT__bus_fifo_tail, m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][3]&0x0ff, m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][2]&0x0ff, m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][1]&0x0ffff, m_core->v__DOT__bus_fifo_data[m_core->v__DOT__bus_fifo_tail][0]); printf(" BUS[A%03x/R%03x/K%03x]", (m_core->v__DOT__bus_active), (m_core->v__DOT__bus_read), (m_core->v__DOT__bus_ack)); /* // Reset logic printf(" RST(%06x%s[%2d] - %08x->%08x)", m_core->v__DOT__reset_timer, (m_core->v__DOT__reset_ztimer)?"Z":" ", (m_core->v__DOT__reset_address), (m_core->v__DOT__reset_instruction), (m_core->v__DOT__reset_cmd)); */ printf(" R_%s%03x[%d]%04x//.:%08x", (!m_core->v__DOT__r_pending)?"_" :(m_core->v__DOT__r_we)?"W":"R", (m_core->v__DOT__r_row), (m_core->v__DOT__r_bank), (m_core->v__DOT__r_col), (m_core->v__DOT__r_data[3])); printf(" S_%s%03x[%d]%04x//.:%08x%s%s", (!m_core->v__DOT__s_pending)?"_" :(m_core->v__DOT__s_we)?"W":"R", (m_core->v__DOT__s_row), (m_core->v__DOT__s_bank), (m_core->v__DOT__s_col), (m_core->v__DOT__s_data[3]), (m_core->v__DOT__pipe_stall)?"P":" ", "-" //(m_core->v__DOT__s_stall)?"S":" " ); printf(" %s%s%s", "B", // (m_core->v__DOT__all_banks_closed)?"b":"B", (m_core->v__DOT__cmd_pipe&1)?"C":"N", //:(m_core->v__DOT__maybe_close_next_bank)?"c":"N", (m_core->v__DOT__cmd_pipe&2)?"O":"K"); // :(m_core->v__DOT__maybe_open_next_bank)?"o":"K"); for(int i=0; i<8; i++) { printf("%s%x|%02x@%x%s", (m_core->v__DOT__r_bank==i)?"R":"[", m_core->v__DOT__bank_status[i], m_sdram->bank_state(i), m_core->v__DOT__bank_address[i], (m_core->v__DOT__r_nxt_bank==i)?"N":"]"); } printf(" %s%s%s%s%s%s%s", (m_core->v__DOT__reset_override)?"R":" ", (m_core->v__DOT__need_refresh)?"N":" ", (m_core->v__DOT__cmd_pipe&1)?"C":" ", (m_core->v__DOT__cmd_pipe&2)?"O":" ", (m_core->v__DOT__cmd_pipe&4)?"v":" ", (m_core->v__DOT__nxt_pipe&1)?"c":" ", (m_core->v__DOT__nxt_pipe&2)?"o":" "); /* // Refresh logic printf(" F%s%05x:%x/%s", (m_core->v__DOT__refresh_ztimer)?"Z":" ", m_core->v__DOT__refresh_counter, m_core->v__DOT__refresh_addr, (m_core->v__DOT__need_refresh)?"N":" "); */ printf("\n"); } // A consistency check ... /* if (m_core->v__DOT__bus_fifo_head != m_core->v__DOT__bus_fifo_tail) { fflush(stdout); if (cmd == DDR_REFRESH) printf("FAIL: CMD=REFRESH, but head != tail\n"); assert(cmd != DDR_REFRESH); } */ m_core->eval(); m_core->i_clk = 0; m_core->eval(); m_tickcount++; /* if ((m_core->o_wb_ack)&&(!m_core->i_wb_cyc)) { printf("SETTING ERR TO TRUE!!!!! ACK w/ no CYC\n"); // m_bomb = true; } */ } void reset(void) { m_core->i_reset = 1; m_core->i_wb_cyc = 0; m_core->i_wb_stb = 0; tick(); m_core->i_reset = 0; } void wb_tick(void) { m_core->i_wb_cyc = 0; m_core->i_wb_stb = 0; tick(); assert(!m_core->o_wb_ack); } void wb_read(unsigned a, unsigned *buf) { int errcount = 0; printf("WB-READ(%08x)\n", a); m_core->i_wb_cyc = 1; m_core->i_wb_stb = 1; m_core->i_wb_we = 0; m_core->i_wb_sel = 0x0ffff; assert((a & 3)==0); m_core->i_wb_addr= (a>>2) & SDRAMMASK; if (m_core->o_wb_stall) { while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) tick(); } tick(); m_core->i_wb_stb = 0; while((errcount++ < BOMBCOUNT)&&(!m_core->o_wb_ack)) tick(); for(int j=0; j<4; j++) { buf[j] = m_core->o_wb_data[j]; if (buf[j] != (*this)[a+j]) { printf("READ-FAIL\n"); assert(buf[j] == (*this)[a]); } } // Release the bus? m_core->i_wb_cyc = 0; m_core->i_wb_stb = 0; if(errcount >= BOMBCOUNT) { printf("SETTING ERR TO TRUE!!!!!\n"); m_bomb = true; } else if (!m_core->o_wb_ack) { printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n"); m_bomb = true; } tick(); assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); assert(!m_core->o_wb_ack); } void wb_read(unsigned a, int len, unsigned *buf) { int errcount = 0; int THISBOMBCOUNT = BOMBCOUNT * len; int cnt, rdidx, inc; printf("WB-READ(%08x, %d)\n", a, len); while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) wb_tick(); if (errcount >= BOMBCOUNT) { printf("WB-READ(%d): Setting bomb to true (errcount = %d)\n", __LINE__, errcount); m_bomb = true; return; } errcount = 0; m_core->i_wb_cyc = 1; m_core->i_wb_stb = 1; m_core->i_wb_we = 0; m_core->i_wb_sel = 0x0ffff; assert((a&3)==0); m_core->i_wb_addr= (a>>2) & SDRAMMASK; rdidx =0; cnt = 0; inc = 1; do { int s; s = (m_core->o_wb_stall==0)?0:1; tick(); if (!s) m_core->i_wb_addr += inc; cnt += (s==0)?1:0; if (m_core->o_wb_ack) { for(int j=0; j<4; j++) { buf[rdidx+j] = m_core->o_wb_data[j]; printf("WB-READ[%08x] = %08x\n", a+rdidx+j, m_core->o_wb_data[j]); if (buf[rdidx+j] != (*this)[a+rdidx+j]){ printf("READ-FAIL\n"); assert(buf[rdidx+j] == (*this)[a+rdidx+j]); } } rdidx+=4; } } while((cnt < len)&&(errcount++ < THISBOMBCOUNT)); m_core->i_wb_stb = 0; while((rdidx < (len<<2))&&(errcount++ < THISBOMBCOUNT)) { tick(); if (m_core->o_wb_ack) { for(int j=0; j<4; j++) { buf[rdidx+j] = m_core->o_wb_data[j]; printf("WB-READ[%08x] = %08x\n", a+rdidx+j, m_core->o_wb_data[j]); if (buf[rdidx+j] != (*this)[a+rdidx+j]){ printf("READ-FAIL\n"); assert(buf[rdidx+j] == (*this)[a+rdidx+j]); } } rdidx+=4; } } // Release the bus? m_core->i_wb_cyc = 0; if(errcount >= THISBOMBCOUNT) { printf("SETTING ERR TO TRUE!!!!! (errcount=%08x, THISBOMBCOUNT=%08x)\n", errcount, THISBOMBCOUNT); m_bomb = true; } else if (!m_core->o_wb_ack) { printf("SETTING ERR TO TRUE--NO ACK, NO TIMEOUT\n"); m_bomb = true; } tick(); assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); assert(!m_core->o_wb_ack); } void wb_write(unsigned a, unsigned *v) { int errcount = 0; printf("WB-WRITE(%08x) = %08x:%08x:%08x:%08x\n", a, v[0], v[1], v[2], v[3]); m_core->i_wb_cyc = 1; m_core->i_wb_stb = 1; m_core->i_wb_we = 1; assert((a&3)==0); m_core->i_wb_addr= (a>>2) & SDRAMMASK; m_core->i_wb_sel = 0x0ffff; m_core->i_wb_data[0]= v[0]; m_core->i_wb_data[1]= v[1]; m_core->i_wb_data[2]= v[2]; m_core->i_wb_data[3]= v[3]; if (m_core->o_wb_stall) while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) tick(); tick(); m_core->i_wb_stb = 0; while((errcount++ < BOMBCOUNT)&&(!m_core->o_wb_ack)) tick(); // Release the bus? m_core->i_wb_cyc = 0; m_core->i_wb_stb = 0; if(errcount >= BOMBCOUNT) { printf("SETTING ERR TO TRUE!!!!!\n"); m_bomb = true; } tick(); assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); assert(!m_core->o_wb_ack); } void wb_write(unsigned a, unsigned int ln, unsigned *buf) { unsigned errcount = 0, nacks = 0; m_core->i_wb_cyc = 1; m_core->i_wb_stb = 1; assert((a&3)==0); for(unsigned stbcnt=0; stbcnt<(ln<<2); stbcnt+=4) { m_core->i_wb_we = 1; m_core->i_wb_addr= ((a+stbcnt)>>2) & SDRAMMASK; m_core->i_wb_sel = 0x0ffff; m_core->i_wb_data[0]= buf[stbcnt+0]; m_core->i_wb_data[1]= buf[stbcnt+1]; m_core->i_wb_data[2]= buf[stbcnt+2]; m_core->i_wb_data[3]= buf[stbcnt+3]; errcount = 0; while((errcount++ < BOMBCOUNT)&&(m_core->o_wb_stall)) { tick(); if (m_core->o_wb_ack) nacks++; } // Tick, now that we're not stalled. This is the tick // that gets accepted. tick(); if (m_core->o_wb_ack) nacks++; } m_core->i_wb_stb = 0; errcount = 0; while((nacks < ln)&&(errcount++ < BOMBCOUNT)) { tick(); if (m_core->o_wb_ack) { nacks++; errcount = 0; } } // Release the bus m_core->i_wb_cyc = 0; m_core->i_wb_stb = 0; if(errcount >= BOMBCOUNT) { printf("SETTING ERR TO TRUE!!!!!\n"); m_bomb = true; } tick(); assert(m_core->v__DOT__bus_fifo_head == m_core->v__DOT__bus_fifo_tail); assert(!m_core->o_wb_ack); } bool bombed(void) const { return m_bomb; } }; void uload(unsigned len, unsigned *buf) { FILE *fp = fopen("/dev/urandom", "r"); if ((NULL == fp)||(len != fread(buf, sizeof(unsigned), len, fp))) { for(int i=0; i<(int)len; i++) buf[i] = ((unsigned)rand()); } if (NULL == fp) fclose(fp); } int main(int argc, char **argv) { Verilated::commandArgs(argc, argv); DDRSDRAM_TB *tb = new DDRSDRAM_TB; unsigned *rdbuf, *mbuf; unsigned mlen = (1<<(LGMEMSIZE-3)); printf("Giving the core 140k cycles to start up\n"); // Before testing, let's give the unit time enough to warm up tb->reset(); for(int i=0; i<40000+16000+40000+14+6+129+3+13+50; i++) tb->wb_tick(); // Let's short circuit the test, and only test *some* of the memory // space. It'll probably be good enough, and it'll finish while I'm // waiting ... mlen = 1<<16; printf("Getting some memory ...\n"); rdbuf = new unsigned[mlen]; mbuf = new unsigned[mlen]; // Match buffer printf("Charging my memory with random values\n"); uload(mlen, rdbuf); #define CASE_TESTS #define SINGULAR_WRITE #define SINGULAR_READ #define BIGPIPELINE_WRITE #define BIGPIPELINE_READ #define PRIMEVEC_WRITE #define PRIMEVEC_READ #define SKIP_WRITE #define SKIP_READ #ifdef CASE_TESTS { printf("CASE-TEST(WRITE,READ)x8\n"); unsigned v[4]; bool casefail = false; for(int i=0; i<8*4; i+=4) { tb->wb_write(i, &rdbuf[i]); tb->wb_read(i, v); for(int j=0; j<4; j++) { if (v[j] != rdbuf[i+j]) casefail = true; } if (casefail) { printf("CASE-1, %08x:%08x:%08x:%08x " "-> MEM[%08x] -> " "%08x:%08x:%08x:%08x " "FAILED (R/W not equal)\n", rdbuf[i+0], rdbuf[i+1], rdbuf[i+2], rdbuf[i+3], i, v[0], v[1], v[2], v[3]); goto test_failure; } else printf("MATCH[%d] = %08x:%08x:%08x:%08x\n", i,rdbuf[i], rdbuf[i+1], rdbuf[i+2], rdbuf[i+3]); } } // Now repeat, hitting a different bank with each command { printf("CASE-TEST(WRITE,READ)[RND]x8\n"); unsigned a, v[4]; bool casefail = false; for(int i=0; i<8*4; i+=4) { a = (1087 + i*1031)<<2; if (a >= mlen) a &= (mlen-4); tb->wb_write(a, &rdbuf[a]); tb->wb_read(a, v); for(int j=0; j<4; j++) { if (v[j] != rdbuf[a+j]) casefail = true; } if (casefail) { printf("CASE-2, %08x:%08x:%08x:%08x -> " "MEM[%08x] -> %08x:%08x:%08x:%08x " "FAILED (R/W not equal)\n", rdbuf[a+0], rdbuf[a+1], rdbuf[a+2], rdbuf[a+3], a, v[0], v[1], v[2], v[3]); goto test_failure; } } } // And again, hitting the same bank with each command { printf("CASE-TEST(WRITE,READ)[rnd]x8\n"); unsigned a, v[4]; bool casefail = false; for(int i=0; i<8*4; i+=4) { a = (1109 + i*256)<<2; tb->wb_write(a, &rdbuf[a]); tb->wb_read(a, v); for(int j=0; j<4; j++) { if (v[j] != rdbuf[a+j]) casefail = true; } if (casefail) { printf("CASE-3, %08x:%08x:%08x:%08x -> " "MEM[%08x] -> %08x:%08x:%08x:%08x " "FAILED (R/W not equal)\n", rdbuf[a+0], rdbuf[a+1], rdbuf[a+2], rdbuf[a+3], a, v[0], v[1], v[2], v[3]); goto test_failure; } } } // Same thing, but writing all first before reading { printf("CASE-TEST(WRITE[Rnd]x8,READ[Rnd]x8)\n"); unsigned a, v[4]; bool casefail = false; for(int i=0; i<8*4; i+=4) { a = (1109 + i*256)<<2; tb->wb_write(a, &rdbuf[a]); } for(int i=0; i<8*4; i+=4) { a = (1109 + i*256)<<2; tb->wb_read(a, v); for(int j=0; j<4; j++) { if(v[j] != rdbuf[a+j]) casefail = true; } if (casefail) { printf("CASE-4, %08x:%08x:%08x:%08x -> " "MEM[%08x] -> %08x:%08x:%08x:%08x " "FAILED (R/W not equal)\n", rdbuf[a+0], rdbuf[a+1], rdbuf[a+2], rdbuf[a+3], a, v[0], v[1], v[2], v[3]); goto test_failure; } } } // And a quick pipeline test { printf("CASE-TEST(WRITEx8P,READx8P)\n"); unsigned v, mbuf[8*4], a = (379)<<2; tb->wb_write(0, 8, &rdbuf[a]); for(int i=0; i<8*4; i++) { a = (379<<2)+i; if ((v=(*tb)[i]) != rdbuf[a]) { printf("CASE-5, %08x -> MEM[%08x] -> %08x " "FAILED (R/W not equal)\n", rdbuf[a], i, v); goto test_failure; } } tb->wb_read(0, 8, mbuf); for(int i=0; i<8*4; i++) { a = (379<<2)+i; if (mbuf[i] != rdbuf[a]) { printf("CASE-6, %08x -> MEM[%08x] -> %08x " "FAILED (R/W not equal)\n", rdbuf[a], i, mbuf[i]); goto test_failure; } } } #endif #ifdef SINGULAR_WRITE // First test: singular reads through the memory, followed by // singular writes { printf("SINGULAR(WRITE)::Starting the single-write test\n"); for(int i=0; i<(int)mlen; i+=4) { tb->wb_write(i, &rdbuf[i]); tb->wb_tick(); for(int j=0; j<4; j++) { if ((*tb)[i+j] != rdbuf[i+j]) { printf("WRITE[%06x] = %08x (Expecting %08x) " "FAILED\n", i, (*tb)[i+j], rdbuf[i+j]); goto test_failure; } if (tb->bombed()) goto test_failure; } } } #else #ifdef SINGULAR_READ // If we aren't doing the write test, we still need to charge // the memory for the read test. Here we do it manually. for(int i=0; i<(int)mlen; i++) tb->set(i, rdbuf[i]); #endif // !SINGULAR_WRITE && SINGULAR_READ #endif // SINGULAR_WRITE #ifdef SINGULAR_READ { printf("SINGULAR(READ)::Starting the single-read test\n"); for(int i=0; i<(int)mlen; i+=4) { unsigned v[4]; bool casefail = false; tb->wb_read(i, v); for(int j=0; j<4; j++) { if (rdbuf[i+j] != v[j]) casefail = true; } if (casefail) { printf("READ[%06x] = %08x:%08x:%08x:%08x " "(Expecting %08x:%08x:%08x:%08x)\n", i, v[0], v[1], v[2], v[3], rdbuf[i+0], rdbuf[i+1], rdbuf[i+2], rdbuf[i+3]); goto test_failure; } if (tb->bombed()) goto test_failure; tb->wb_tick(); } } #endif #ifdef BIGPIPELINE_WRITE { // Second test: Vector writes going through all memory, followed a // massive vector read printf("BIGPIPELINE_WRITE::Starting the big-pipeline write test\n"); uload(mlen, rdbuf); // Get some new values tb->wb_write(0, mlen/4, rdbuf); if (tb->bombed()) goto test_failure; for(int i=0; i<(int)mlen; i++) { unsigned v; if (rdbuf[i] != (v=(*tb)[i])) { printf("V-WRITE[%06x] = %08x (Expecting %08x)\n", i, v, rdbuf[i]); goto test_failure; } } } #else #ifdef BIGPIPELINE_READ uload(mlen, rdbuf); // Get some new values // If we aren't doing the write test, we still need to charge // the memory for the read test. Here we do it manually. for(int i=0; i<(int)mlen; i++) (*tb)[i] = rdbuf[i]; #endif // BIGPIPELINE_WRITE && BIGPIPELINE_READ #endif #ifdef BIGPIPELINE_READ { printf("BIGPIPELINE_READ::Starting the big-pipeline read test\n"); tb->wb_read( 0, mlen/4, mbuf); if (tb->bombed()) goto test_failure; for(int i=0; i<(int)mlen; i++) { if (rdbuf[i] != mbuf[i]) { printf("V-READ[%06x] = %08x (Expecting %08x)\n", i, mbuf[i], rdbuf[i]); goto test_failure; } } } #endif #ifdef PRIMEVEC_WRITE printf("PRIMEVEC(WRITE)::Starting the prime-vector write test\n"); // Third test: Vector writes going through all memory, in prime numbers // of values at a time, followed by reads via a different prime number uload(mlen, rdbuf); // Get some new values { int nw = 3; for(int i=0; i<(int)mlen; i+=nw*4) { int ln = ((int)mlen-i>nw*4)?(nw*4):mlen-i; tb->wb_write(i, ln/4, &rdbuf[i]); for(int j=0; j<ln; j++) { if ((*tb)[i+j] != rdbuf[i+j]) { printf("P-WRITE[%06x] = %08x (Expecting %08x) FAILED\n", i, (*tb)[i], rdbuf[i]); goto test_failure; } } if (tb->bombed()) goto test_failure; } } #else #ifdef PRIMEVEC_READ uload(mlen, rdbuf); // Get some new values // If we aren't doing the write test, we still need to charge // the memory for the read test. Here we do it manually. for(int i=0; i<(int)mlen; i++) tb->set(i, rdbuf[i]); #endif #endif #ifdef PRIMEVEC_READ printf("PRIMEVEC(READ)::Starting the prime-vector read test\n"); { int nr = 13; for(int i=0; i<(int)mlen; i+=nr*4) { int ln = ((int)mlen-i>nr*4)?(nr*4):(mlen-i); tb->wb_read(i, ln/4, &mbuf[i]); for(int j=0; j<ln; j++) { if (mbuf[i+j] != rdbuf[i+j]) { printf("P-READ[%06x] = %08x (Expecting %08x) FAILED\n", i, mbuf[i], rdbuf[i]); goto test_failure; } } if (tb->bombed()) goto test_failure; } } #endif #ifdef SKIP_WRITE { // Fourth test: Singular writes though all of memory, skipping by some // prime address increment each time, followed by reads via a different // prime numbered increment. printf("SKIP(WRITE)::Starting the skip write test\n"); uload(mlen, rdbuf); // Get some new values for(int i=0; i<(int)mlen; i++) { int loc = (i*3889)&(mlen-4); bool casefail = false; tb->wb_write(loc, &rdbuf[loc]); for(int j=0; j<4; j++) { if ((*tb)[loc+j] != rdbuf[loc+j]) { printf("R-WRITE[%06x] = %08x (Expecting %08x) FAILED\n", i, (*tb)[loc+j], rdbuf[loc+j]); casefail = true; } } if ((casefail)||(tb->bombed())) goto test_failure; } } #else #ifdef SKIP_READ uload(mlen, rdbuf); // Get some new values for(int i=0; i<(int)mlen; i++) tb->set(i, rdbuf[i]); #endif // !SKIP_WRITE && SKIP_READ #endif #ifdef SKIP_READ printf("SKIP(READ)::Starting the skip read/validate/verify test\n"); for(int i=0; i<(int)mlen; i++) { int loc = (i*7477)&(mlen-4); bool casefail = false; tb->wb_read(loc, &mbuf[loc]); for(int j=0; j<4; j++) { if (mbuf[loc] != rdbuf[loc]) { printf("R-READ[%06x] = %08x (Expecting %08x) FAILED\n", loc, mbuf[loc+j], rdbuf[loc+j]); casefail = true; } } if ((tb->bombed())||(casefail)) goto test_failure; } #endif printf("SUCCESS!!\n"); exit(0); test_failure: printf("FAIL-HERE\n"); for(int i=0; i<64; i++) tb->tick(); printf("TEST FAILED\n"); exit(-1); }