Exemple #1
0
int main(int argc, const char **argv)
{

	MemServerRequestProxy *hostMemServerRequest = new MemServerRequestProxy(IfcNames_HostMemServerRequest);
	MMURequestProxy *dmap = new MMURequestProxy(IfcNames_HostMMURequest);
	DmaManager *dma = new DmaManager(dmap);
	MemServerIndication *hostMemServerIndication = new MemServerIndication(hostMemServerRequest, IfcNames_HostMemServerIndication);
	MMUIndication *hostMMUIndication = new MMUIndication(dma, IfcNames_HostMMUIndication);

	fprintf(stderr, "Main::allocating memory...\n");

	device = new FlashRequestProxy(IfcNames_FlashRequest);
	FlashIndication *deviceIndication = new FlashIndication(IfcNames_FlashIndication);
	
	srcAlloc = portalAlloc(srcAlloc_sz);
	dstAlloc = portalAlloc(dstAlloc_sz);
	srcBuffer = (unsigned int *)portalMmap(srcAlloc, srcAlloc_sz);
	dstBuffer = (unsigned int *)portalMmap(dstAlloc, dstAlloc_sz);

	fprintf(stderr, "dstAlloc = %x\n", dstAlloc); 
	fprintf(stderr, "srcAlloc = %x\n", srcAlloc); 
	
	pthread_mutex_init(&flashReqMutex, NULL);
	pthread_cond_init(&flashFreeTagCond, NULL);

	printf( "Done initializing hw interfaces\n" ); fflush(stdout);

	portalExec_start();
	printf( "Done portalExec_start\n" ); fflush(stdout);

	portalDCacheFlushInval(dstAlloc, dstAlloc_sz, dstBuffer);
	portalDCacheFlushInval(srcAlloc, srcAlloc_sz, srcBuffer);
	ref_dstAlloc = dma->reference(dstAlloc);
	ref_srcAlloc = dma->reference(srcAlloc);

	for (int t = 0; t < NUM_TAGS; t++) {
		readTagTable[t].busy = false;
		writeTagTable[t].busy = false;
		int byteOffset = t * PAGE_SIZE;
		device->addDmaWriteRefs(ref_dstAlloc, byteOffset, t);
		device->addDmaReadRefs(ref_srcAlloc, byteOffset, t);
		readBuffers[t] = dstBuffer + byteOffset/sizeof(unsigned int);
		writeBuffers[t] = srcBuffer + byteOffset/sizeof(unsigned int);
	}
	
	for (int blk=0; blk<BLOCKS_PER_CHIP; blk++) {
		for (int c=0; c<CHIPS_PER_BUS; c++) {
			for (int bus=0; bus< CHIPS_PER_BUS; bus++) {
				flashStatus[bus][c][blk] = UNINIT;
			}
		}
	}


	for (int t = 0; t < NUM_TAGS; t++) {
		for ( int i = 0; i < PAGE_SIZE/sizeof(unsigned int); i++ ) {
			readBuffers[t][i] = 0;
			writeBuffers[t][i] = 0;
		}
	}

	device->start(0);
	device->setDebugVals(0,0); //flag, delay

	device->debugDumpReq(0);
	sleep(1);
	device->debugDumpReq(0);
	sleep(1);
	//TODO: test writes and erases
	

	
	//test erases
	for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
		for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
			for (int bus = 0; bus < NUM_BUSES; bus++){
				eraseBlock(bus, chip, blk, waitIdleEraseTag());
			}
		}
	}

	while (true) {
		usleep(100);
		if ( getNumErasesInFlight() == 0 ) break;
	}
	
	
	//read back erased pages
	for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
		for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
			for (int bus = 0; bus < NUM_BUSES; bus++){
				int page = 0;
				readPage(bus, chip, blk, page, waitIdleReadBuffer());
			}
		}
	}
	while (true) {
		usleep(100);
		if ( getNumReadsInFlight() == 0 ) break;
	}


	//write pages
	//FIXME: in old xbsv, simulatneous DMA reads using multiple readers cause kernel panic
	//Issue each bus separately for now
	for (int bus = 0; bus < NUM_BUSES; bus++){
	
		for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
			for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
				int page = 0;
				//get free tag
				int freeTag = waitIdleWriteBuffer();
				//fill write memory
				for (int w=0; w<PAGE_SIZE/sizeof(unsigned int); w++) {
					writeBuffers[freeTag][w] = hashAddrToData(bus, chip, blk, w);
				}
				//send request
				writePage(bus, chip, blk, page, freeTag);
			}
			while (true) {
				usleep(100);
				if ( getNumWritesInFlight() == 0 ) break;
			}
		}
		
		
	} //each bus
	

	timespec start, now;
	clock_gettime(CLOCK_REALTIME, & start);

	for (int repeat = 0; repeat < 1; repeat++){
		for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
			for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
				for (int bus = 0; bus < NUM_BUSES; bus++){

				//int blk = rand() % 1024;
				//int chip = rand() % 8;
				//int bus = rand() % 8;
					int page = 0;
					readPage(bus, chip, blk, page, waitIdleReadBuffer());
				}
			}
		}
	}
	
	int elapsed = 0;
	while (true) {
		usleep(100);
		if (elapsed == 0) {
			elapsed=10000;
			device->debugDumpReq(0);
		}
		else {
			elapsed--;
		}
		if ( getNumReadsInFlight() == 0 ) break;
	}
	device->debugDumpReq(0);

	clock_gettime(CLOCK_REALTIME, & now);
	fprintf(stderr, "LOG: finished reading from page! %f\n", timespec_diff_sec(start, now) );

	for ( int t = 0; t < NUM_TAGS; t++ ) {
		for ( int i = 0; i < PAGE_SIZE/sizeof(unsigned int); i++ ) {
			fprintf(stderr,  "%x %x %x\n", t, i, readBuffers[t][i] );
		}
	}
	if (testPass==1) {
		fprintf(stderr, "LOG: TEST PASSED!\n");
	}
	else {
		fprintf(stderr, "LOG: **ERROR: TEST FAILED!\n");
	}


}
Exemple #2
0
int main(int argc, const char **argv)
{

	int myid = 0;

	fprintf(stderr, "Main: myid=%d\n", myid);

	MemServerRequestProxy *hostMemServerRequest = new MemServerRequestProxy(IfcNames_HostMemServerRequest);
	MMURequestProxy *dmap = new MMURequestProxy(IfcNames_HostMMURequest);
	DmaManager *dma = new DmaManager(dmap);
	MemServerIndication *hostMemServerIndication = new MemServerIndication(hostMemServerRequest, IfcNames_HostMemServerIndication);
	MMUIndication *hostMMUIndication = new MMUIndication(dma, IfcNames_HostMMUIndication);

	fprintf(stderr, "Main::allocating memory...\n");

	device = new FlashRequestProxy(IfcNames_FlashRequest);
	FlashIndication *deviceIndication = new FlashIndication(IfcNames_FlashIndication);
	
	srcAlloc = portalAlloc(srcAlloc_sz);
	dstAlloc = portalAlloc(dstAlloc_sz);
	srcBuffer = (unsigned int *)portalMmap(srcAlloc, srcAlloc_sz);
	dstBuffer = (unsigned int *)portalMmap(dstAlloc, dstAlloc_sz);

	fprintf(stderr, "dstAlloc = %x\n", dstAlloc); 
	fprintf(stderr, "srcAlloc = %x\n", srcAlloc); 
	
	pthread_mutex_init(&flashReqMutex, NULL);
	pthread_cond_init(&flashFreeTagCond, NULL);

	printf( "Done initializing hw interfaces\n" ); fflush(stdout);

	portalExec_start();
	printf( "Done portalExec_start\n" ); fflush(stdout);

	portalDCacheFlushInval(dstAlloc, dstAlloc_sz, dstBuffer);
	portalDCacheFlushInval(srcAlloc, srcAlloc_sz, srcBuffer);
	ref_dstAlloc = dma->reference(dstAlloc);
	ref_srcAlloc = dma->reference(srcAlloc);

	device->setDmaWriteRef(ref_dstAlloc);
	device->setDmaReadRef(ref_srcAlloc);
	for (int t = 0; t < NUM_TAGS; t++) {
		readTagTable[t].busy = false;
		writeTagTable[t].busy = false;
		int byteOffset = t * PAGE_SIZE;
		printf("byteOffset=%x\n", byteOffset); fflush(stdout);
		readBuffers[t] = dstBuffer + byteOffset/sizeof(unsigned int);
		writeBuffers[t] = srcBuffer + byteOffset/sizeof(unsigned int);
	}
	
	for (int node=0; node<NUM_NODES; node++) {
		for (int blk=0; blk<BLOCKS_PER_CHIP; blk++) {
			for (int c=0; c<CHIPS_PER_BUS; c++) {
				for (int bus=0; bus< CHIPS_PER_BUS; bus++) {
					flashStatus[node][bus][c][blk] = UNINIT;
				}
			}
		}
	}


	for (int t = 0; t < NUM_TAGS; t++) {
		for ( int i = 0; i < PAGE_SIZE/sizeof(unsigned int); i++ ) {
			readBuffers[t][i] = 0;
			writeBuffers[t][i] = 0;
		}
	}


	//Start ext aurora
	auroraifc_start(myid);

	device->start(0);
	device->setDebugVals(0,0); //flag, delay

	device->debugDumpReq(0);
	sleep(1);
	device->debugDumpReq(0);
	sleep(1);

	if (myid==0) {

		
		timespec start, now;
		double timeElapsed = 0;
		int node = myid;

		if (doerasewrites) {
			//test erases
			//for (int node=NUM_NODES-1; node >= 1; node--) 
			//for (int node=DST_NODE; node == DST_NODE; node++) 
				for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
					for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
						for (int bus = 0; bus < NUM_BUSES; bus++){
							eraseBlock(node, bus, chip, blk, waitIdleEraseTag());
						}
					}
				}

			while (true) {
				usleep(100);
				if ( getNumErasesInFlight() == 0 ) break;
			}


			//read back erased pages
			//for (int node=NUM_NODES-1; node >= 1; node--) 
			//for (int node=DST_NODE; node == DST_NODE; node++) 
				for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
					for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
						for (int bus = 0; bus < NUM_BUSES; bus++){
							int page = 0;
							readPage(node, bus, chip, blk, page, waitIdleReadBuffer());
						}
					}
				}

			while (true) {
				usleep(100);
				if ( getNumReadsInFlight() == 0 ) break;
			}
			

			//write pages
			//FIXME: in old xbsv, simulatneous DMA reads using multiple readers cause kernel panic
			//Issue each bus separately for now

			int pagesWritten = 0;
			clock_gettime(CLOCK_REALTIME, & start);
			//for (int node=NUM_NODES-1; node >= 1; node--) 
			//for (int node=DST_NODE; node == DST_NODE; node++) 
				for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
					for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
						for (int bus = 0; bus < NUM_BUSES; bus++){
							int page = 0;
							//get free tag
							int freeTag = waitIdleWriteBuffer();
							//fill write memory; REMOVE THIS FOR PERFORMANCE TESTING!
							for (int w=0; w<PAGE_SIZE/sizeof(unsigned int); w++) {
								writeBuffers[freeTag][w] = hashAddrToData(node, bus, chip, blk, w);
							}
							//send request
							writePage(node, bus, chip, blk, page, freeTag); 
							pagesWritten++;
						}
					}
				}
			while (true) {
				usleep(100);
				if ( getNumWritesInFlight() == 0 ) break;
			}

			clock_gettime(CLOCK_REALTIME, & now);
			timeElapsed = timespec_diff_sec(start, now);
			fprintf(stderr, "LOG: finished writing! time=%f, numPages=%d, bandwidth=%f MB/s\n", timeElapsed, pagesWritten, (pagesWritten*8)/timeElapsed/1024  );

		} //doerasewrites

	
		sleep(1);
	
		int pagesRead = 0;
		clock_gettime(CLOCK_REALTIME, & start);
		
	
		//for (int node=NUM_NODES-1; node >= 1; node--) {
		//for (int node=DST_NODE; node == DST_NODE; node++) {
		for (int repeat = 0; repeat < 10; repeat++){
			for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
				for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
					for (int bus = 0; bus < NUM_BUSES; bus++){
						pagesRead++;
						int page = 0;
						readPage(node, bus, chip, blk, page, waitIdleReadBuffer());
					}
				}
			}
		}
		//}

		while (true) {
			if ( getNumReadsInFlight() == 0 ) break;
			usleep(100);
		}

		clock_gettime(CLOCK_REALTIME, & now);
		timeElapsed = timespec_diff_sec(start, now);
		fprintf(stderr, "LOG: finished SEQUENTIAL reads! time=%f, numPages=%d, bandwidth=%f MB/s\n", timeElapsed, pagesRead, (pagesRead*8)/timeElapsed/1024  );

		sleep(1);

		pagesRead=0;
		clock_gettime(CLOCK_REALTIME, & start);
		for (int repeat = 0; repeat < 100000; repeat++){
			int bus = rand()%NUM_BUSES;
			int chip = rand()%CHIPS_PER_BUS;
			int blk = rand()%BLOCKS_PER_CHIP;
			int page = rand()%PAGES_PER_BLOCK;
			readPage(node, bus, chip, blk, page, waitIdleReadBuffer());
			pagesRead++;

		}

		while (true) {
			if ( getNumReadsInFlight() == 0 ) break;
			usleep(100);
		}

		clock_gettime(CLOCK_REALTIME, & now);
		timeElapsed = timespec_diff_sec(start, now);
		fprintf(stderr, "LOG: finished RANDOM reads! time=%f, numPages=%d, bandwidth=%f MB/s\n", timeElapsed, pagesRead, (pagesRead*8)/timeElapsed/1024  );




		device->debugDumpReq(0);
		sleep(1);
		


		for ( int t = 0; t < NUM_TAGS; t++ ) {
			for ( int i = 0; i < PAGE_SIZE/sizeof(unsigned int); i++ ) {
				fprintf(stderr,  "%x %x %x\n", t, i, readBuffers[t][i] );
			}
		}
		if (!verbose) {
			fprintf(stderr, "LOG: DONE! data check skipped\n");
		} 
		else if (testPass==1) {
			fprintf(stderr, "LOG: TEST PASSED!\n");
		}
		else {
			fprintf(stderr, "LOG: **ERROR: TEST FAILED!\n");
		}
		

	} 
	else {
		fprintf(stderr, "Sleeping infinitely...\n");
		while (true) {
		device->debugDumpReq(0);
		sleep(1);
		}
		sleep(1000000);
	}
}
Exemple #3
0
//---------------------------------------------
//Local erase, read, write, read test
//---------------------------------------------
void local_test(bool check, int read_repeat, int debug_lvl ) {
	LOG(0, "LOG: starting local_test...\n");
	g_checkdata = check;
	g_debuglevel = debug_lvl;
	g_testpass = true;
	int node = myid;

	timespec start, now;
	double timeElapsed = 0; 
	double bw = 0;
	//erase all blocks
	for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
		for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
			for (int bus = 0; bus < NUM_BUSES; bus++){
				eraseBlock(node, bus, chip, blk, waitIdleEraseTag());
			}
		}
	}

	while (true) {
		if ( getNumErasesInFlight() == 0 ) break;
	}

	//read back erased pages
	for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
		for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
			for (int bus = 0; bus < NUM_BUSES; bus++){
				int page = 0;
				readPage(node, bus, chip, blk, page, waitIdleReadBuffer());
			}
		}
	}

	while (true) {
		if ( getNumReadsInFlight() == 0 ) break;
	}


	int pagesWritten = 0;
	clock_gettime(CLOCK_REALTIME, & start);
	//write pages
	for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
		for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
			for (int bus = 0; bus < NUM_BUSES; bus++){
				int page = 0;
				int freeTag = waitIdleWriteBuffer();
				if (g_checkdata) {
					//fill write memory only if we're doing readback checks
					for (int w=0; w<PAGE_SIZE/sizeof(unsigned int); w++) {
						writeBuffers[freeTag][w] = hashAddrToData(node, bus, chip, blk, w);
					}
				}
				//send request
				writePage(node, bus, chip, blk, page, freeTag); 
				pagesWritten++;
			}
		}
	}
	while (true) {
		if ( getNumWritesInFlight() == 0 ) break;
	}
	clock_gettime(CLOCK_REALTIME, & now);
	timeElapsed = timespec_diff_sec(start, now);
	bw = (pagesWritten*8)/timeElapsed/1024; //MB/s
	//double latency = timeElapsed/pagesWritten;
	//double latency_us = latency*1000000;
	LOG(0, "LOG: finished writing to page. Time=%f, NumPages=%d, BW=%f MB/s\n", 
							timeElapsed, pagesWritten, bw);


	int pagesRead = 0;
	clock_gettime(CLOCK_REALTIME, & start);
	for (int rep = 0; rep < read_repeat; rep++) {
		for (int blk = 0; blk < BLOCKS_PER_CHIP; blk++){
			for (int chip = 0; chip < CHIPS_PER_BUS; chip++){
				for (int bus = 0; bus < NUM_BUSES; bus++){
					int page = 0;
					readPage(node, bus, chip, blk, page, waitIdleReadBuffer());
					pagesRead++;
				}
			}
		}
	}
	while (true) {
		if ( getNumReadsInFlight() == 0 ) break;
	}
	clock_gettime(CLOCK_REALTIME, & now);
	timeElapsed = timespec_diff_sec(start, now);
	bw = (pagesRead*8)/timeElapsed/1024; //MB/s

	LOG(0, "LOG: reading from page. Time=%f, NumPages=%d, BW=%f MB/s\n", 
							timeElapsed, pagesRead, bw);

	device->debugDumpReq(0);
	sleep(1);

	for ( int t = 0; t < NUM_TAGS; t++ ) {
		for ( int i = 0; i < PAGE_SIZE/sizeof(unsigned int); i++ ) {
			LOG(1, "%x %x %x\n", t, i, readBuffers[t][i] );
		}
	}

	if (g_checkdata) {
		if (g_testpass) {
			LOG(0, "LOG: local_test passed!\n");
		}
		else {
			LOG(0, "LOG: **ERROR: local_test FAILED!\n");
		}
	} else {
			LOG(0, "LOG: local_test complete. No checks done\n");
	}
}
Exemple #4
0
int main(int argc, const char **argv)
{
	testPassed=true;

	fprintf(stderr, "Initializing Connectal & DMA...\n");

	device = new FlashRequestProxy(IfcNames_FlashRequestS2H);
	FlashIndication deviceIndication(IfcNames_FlashIndicationH2S);
    DmaManager *dma = platformInit();

	fprintf(stderr, "Main::allocating memory...\n");
	
	// Memory for DMA
	srcAlloc = portalAlloc(srcAlloc_sz, 0);
	dstAlloc = portalAlloc(dstAlloc_sz, 0);
	srcBuffer = (unsigned int *)portalMmap(srcAlloc, srcAlloc_sz); // Host->Flash Write
	dstBuffer = (unsigned int *)portalMmap(dstAlloc, dstAlloc_sz); // Flash->Host Read

	// Memory for FTL
	blkmapAlloc = portalAlloc(blkmapAlloc_sz * 2, 0);
	char *ftlPtr = (char*)portalMmap(blkmapAlloc, blkmapAlloc_sz * 2);
	blkmap      = (uint16_t(*)[NUM_LOGBLKS]) (ftlPtr);  // blkmap[Seg#][LogBlk#]
	blkmgr      = (uint16_t(*)[NUM_CHIPS][NUM_BLOCKS])  (ftlPtr+blkmapAlloc_sz); // blkmgr[Bus][Chip][Block]

	fprintf(stderr, "dstAlloc = %x\n", dstAlloc); 
	fprintf(stderr, "srcAlloc = %x\n", srcAlloc); 
	fprintf(stderr, "blkmapAlloc = %x\n", blkmapAlloc); 
	
	pthread_mutex_init(&flashReqMutex, NULL);
	pthread_cond_init(&flashFreeTagCond, NULL);

	printf( "Done initializing hw interfaces\n" ); fflush(stdout);

	portalCacheFlush(dstAlloc, dstBuffer, dstAlloc_sz, 1);
	portalCacheFlush(srcAlloc, srcBuffer, srcAlloc_sz, 1);
	portalCacheFlush(blkmapAlloc, blkmap, blkmapAlloc_sz*2, 1);

	ref_dstAlloc = dma->reference(dstAlloc);
	ref_srcAlloc = dma->reference(srcAlloc);
	ref_blkmapAlloc = dma->reference(blkmapAlloc);

	device->setDmaWriteRef(ref_dstAlloc);
	device->setDmaReadRef(ref_srcAlloc);
	device->setDmaMapRef(ref_blkmapAlloc);

	for (int t = 0; t < NUM_TAGS; t++) {
		readTagTable[t].busy = false;
		writeTagTable[t].busy = false;
		eraseTagTable[t].busy = false;

		int byteOffset = t * FPAGE_SIZE;
		readBuffers[t] = dstBuffer + byteOffset/sizeof(unsigned int);
		writeBuffers[t] = srcBuffer + byteOffset/sizeof(unsigned int);
	}

	for (int lpa=0; lpa < NUM_SEGMENTS*NUM_LOGBLKS*NUM_PAGES_PER_BLK; lpa++) {
		flashStatus[lpa] = UNINIT;
	}

	for (int t = 0; t < NUM_TAGS; t++) {
		for ( unsigned int i = 0; i < FPAGE_SIZE/sizeof(unsigned int); i++ ) {
			readBuffers[t][i] = 0xDEADBEEF;
			writeBuffers[t][i] = 0xBEEFDEAD;
		}
	}

	long actualFrequency=0;
	long requestedFrequency=1e9/MainClockPeriod;
	int status = setClockFrequency(0, requestedFrequency, &actualFrequency);
	fprintf(stderr, "Requested Freq: %5.2f, Actual Freq: %5.2f, status=%d\n"
			,(double)requestedFrequency*1.0e-6
			,(double)actualFrequency*1.0e-6,status);

	printf( "Start!\n" ); fflush(stdout);
	device->start(0);
	device->setDebugVals(0,0); //flag, delay

	device->debugDumpReq(0);
	sleep(1);

	printf( "Read initial FTL table from table.dump.0\n" ); fflush(stdout);
	// Read Initial FTL table
	if (readFTLfromFile("table.dump.0", ftlPtr) != 0) {
		fprintf(stderr, "Read Failure\n");
		return -1;
	}
	printf( "Done reading table.dump.0\n" ); fflush(stdout);

	printf( "MAP Upload to HW!\n" ); fflush(stdout);
	device->uploadMap();

	timespec start, now;
	clock_gettime(CLOCK_REALTIME, & start);

	printf( "Test Write!\n" ); fflush(stdout);

	for (int logblk = 0; logblk < NUM_LOGBLKS; logblk++){
		// test only 1024 segments due to some bad blocks (cannot allocate full 4096 segments)
		for (int segnum = 0; segnum < 1024; segnum++) {
			// assuming page_ofs = 0
			int lpa = (segnum<<14) + logblk;
			int freeTag = waitIdleWriteBuffer();

			// fill write memory
			for (unsigned int w=0; w<FPAGE_SIZE_VALID/sizeof(unsigned int); w++) {
				writeBuffers[freeTag][w] = hashAddrToData(lpa, w);
			}

			writePage(freeTag, lpa);
		}
	}

	while (true) {
		usleep(100);
		if ( getNumWritesInFlight() == 0 ) break;
	}

	// read back Map and Save to table.dump.1
	device->downloadMap(); // read table from FPGA
	if(writeFTLtoFile("table.dump.1", ftlPtr) != 0) {
		fprintf(stderr, "Write Failure\n");
		return -1;
	}

	printf( "Test Read!\n" ); fflush(stdout);
	
	for (int logblk = 0; logblk < NUM_LOGBLKS; logblk++){
		// test only 1024 segments due to some bad blocks (cannot allocate full 4096 segments)
		for (int segnum = 0; segnum < 1024; segnum++) {
			// assuming page_ofs = 0
			int lpa = (segnum<<14) + logblk;
			readPage(waitIdleReadBuffer(), lpa);
		}
	}

	while (true) {
		usleep(100);
		if ( getNumReadsInFlight() == 0 ) break;
	}

	printf( "Test Erase!\n" ); fflush(stdout);
	for (int logblk = 0; logblk < NUM_LOGBLKS; logblk++){
		// test only 1024 segments due to some bad blocks (cannot allocate full 4096 segments)
		for (int segnum = 0; segnum < 1024; segnum++) {
			// assuming page_ofs = 0
			int lpa = (segnum<<14) + logblk;
			eraseBlock(waitIdleEraseTag(), lpa);
		}
	}

	while (true) {
		usleep(100);
		if ( getNumErasesInFlight() == 0 ) break;
	}

	int elapsed = 0;
	while (true) {
		usleep(100);
		if (elapsed == 0) {
			elapsed=10000;
			device->debugDumpReq(0);
		}
		else {
			elapsed--;
		}
		if ( getNumReadsInFlight() == 0 ) break;
	}
	device->debugDumpReq(0);

	clock_gettime(CLOCK_REALTIME, & now);
	fprintf(stderr, "LOG: finished reading from page! %f\n", timespec_diff_sec(start, now) );

	sleep(2);
}