OpenCores
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);
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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