rdram.c 6.73 KB
/*
 * These routines mmap two files that contain the contents of the
 * Verilog rdram core.  After initializing,  the copy & write routines can
 * be called.  The read routine is used to copy the contents of the file
 * to the internal rdram.  The rdram write task can call the write routine
 * to update the mmap file at the same time the internal core is being
 * written.  Unfortunately,  there is no way for writes to the mmap file
 * to automatically update the internal core.  (have to copy entire image)
 * 
 * The system (RDP,  R4K,  ...) views the memory in BE mode.  However, the
 * rdram is LE internally.  The mmap files will show the memory in BE
 * format.  This is to alleviate or create confusion.  (Take your pick)
 * 
 * A "word" is 64/72 bits
 * 
 * Use strings to pass ascii representations of 72 bit words back & forth
 * 
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <fcntl.h>

#include <PR/verify.h>

#include "acc_user.h"
#include "vcsuser.h"

/* XXX Need to put somewhere else 2 Meg system */
#define MAIN_MEMORY_SIZE        0x200000
#define HIDDEN_FACTOR           8
#define HIDDEN_MEMORY_SIZE      (MAIN_MEMORY_SIZE/HIDDEN_FACTOR)
#define TOTAL_MEMORY_SIZE	(MAIN_MEMORY_SIZE + HIDDEN_MEMORY_SIZE)

/*
#define DEBUG1(s, a0) if (!data) fprintf(stderr, s, a0)
#define DEBUG2(s, a0, a1) if (!data) fprintf(stderr, s, a0, a1)
 */
#define DEBUG1(s, a0)
#define DEBUG2(s, a0, a1)

static s_setval_value value_s = { accBinStrVal };
static s_setval_delay delay_s = { { accRealTime, 0, 0, 0 }, accNoDelay };

/* Global file pointers  (Should be passed in as arguments, but it's a hassle) */
static int rdfd = 0;
static unsigned char *mainaddr = 0, *hiddenaddr = 0;


/*
 * Usage:  $rdram_mmap_init(filename, nrdrams)
 */
void
rdram_mmap_init(int data, int reason)
{
    struct stat statbuf;
    char *file;
    char filename[1024];
    int memsize;
    long nbytes;
    VerifyInfo *vp;
    
    acc_initialize();
    acc_configure(accDevelopmentVersion, "1.6");
    
    file = tf_getcstringp(1);
    memsize = tf_getp(2);
    
    fprintf(stderr, "rdram_mmap_init: file is %s, size %d\n", file, memsize);
    if (mainaddr != NULL) {
	fprintf(stderr, "already initialized mainaddr = %x\n", mainaddr);
	tf_putp(0, 0);
	return;
    }
    
    if (memsize != 1 && memsize != 2) {
	fprintf(stderr, "memsize not 1 or 2!! (%d)\n", memsize);
	tf_putp(0, -1);
	return;
	
    }
    
    nbytes = TOTAL_MEMORY_SIZE * memsize;
    
    /* Open files, and then mmap them in */
    sprintf(filename, "%s.rdram", file);
    if ((rdfd = open(filename, (O_RDWR | O_CREAT), 0644)) == -1) {
	fprintf(stderr, "Could not open <%s>\n", filename);
	tf_putp(0, -1);
	return;
    }
    
    if (fstat(rdfd, &statbuf) == -1) {
	fprintf(stderr, "Could not stat <%s>\n", filename);
	tf_putp(0, -1);
	return;
    }
    
    
    mainaddr = mmap(NULL, nbytes, (PROT_READ | PROT_WRITE),
#ifdef __sgi__
		(MAP_SHARED | MAP_AUTOGROW), rdfd, 0);
#else
		(MAP_SHARED), rdfd, 0);
#endif
		
    hiddenaddr = mainaddr + (MAIN_MEMORY_SIZE * memsize);
		
    fprintf(stderr, "rdram_mmap_init: mainaddr is 0x%x, hiddenaddr is 0x%x\n",
	mainaddr, hiddenaddr);

    if (mainaddr == (unsigned char *)-1) {
	fprintf(stderr, "Could not mmap <%s>\n", filename);
	tf_putp(0, -1);
	return;
    }
    
    /* File created of resized? print warning and autogrow */
    if (statbuf.st_size != nbytes) {
	fprintf(stderr, "Warning! %s grew, was 0x%x now 0x%x\n",
	    filename, statbuf.st_size, nbytes);
	*(mainaddr + nbytes - 1) = 0;
	/* need to copy hidden bits up  if expanding from 2.25 to 4.5 Meg */
	if (statbuf.st_size == TOTAL_MEMORY_SIZE && 
		nbytes == 2 * TOTAL_MEMORY_SIZE) {
	    bcopy(mainaddr + MAIN_MEMORY_SIZE, hiddenaddr, HIDDEN_MEMORY_SIZE);
	    bzero(mainaddr + MAIN_MEMORY_SIZE, HIDDEN_MEMORY_SIZE);
	}
    }

    vp = (VerifyInfo *)(mainaddr + VERIFY_INFO_PHYSADDR);
    
    if (vp->magicNumber != MAGICNUMBER) {
	fprintf(stderr, "Warning! VerifyInfo magic number is 0x%x, not 0x%x\n",
	    vp->magicNumber,  MAGICNUMBER);
    }
    
      
    tf_putp(0, 0);    
}

/*
 * Usage:  $rdram_mmap_init_check(id)
 */
void
rdram_mmap_init_check(int data, int reason)
{
    int memid;
    
    memid = tf_getp(1);
    
    fprintf(stderr, "rdram_mmap_init_check: id %d ", memid);
    
    if (mainaddr != NULL) {
	fprintf(stderr, "already initialized\n");
	tf_putp(0, 0);
    } else {
	fprintf(stderr, "NOT initialized!!\n");
	tf_putp(0, -1);
	
    }
    return;
}

/*
 * Usage:  $rdram_mmap_read(memory_id, offset, core word)
 * Read from file
 */
void
rdram_mmap_read(int data, int reason)
{
    handle hcore_word;
    int memid, offset, i, j;
    unsigned char hiddenbyte, mainbyte, *mp;
    char binstr[73], *cp;

    if(tf_nump() != 3) {
      tf_error("rdram_mmap_read illegal number of arguments: %d", tf_nump());
      tf_putp(0, -1);
    }

    memid = acc_fetch_tfarg_int(1);
    offset = acc_fetch_tfarg_int(2);
    hcore_word = acc_handle_tfarg(3);
    DEBUG2("\nread: id %d, offset is 0x%x\n", memid, offset);

    hiddenbyte = *(hiddenaddr + offset);
    DEBUG2("hidden: %d-->0x%x\n", hiddenaddr + offset, hiddenbyte);
    mp = mainaddr + (offset*8) + 7;
    cp = binstr;
    
    for (i=0; i<8; i++) {
	if (hiddenbyte & 0x01)
	    *cp++ = '1';
	else
	    *cp++ = '0';
	    
	mainbyte = *mp--;
	DEBUG2("%d-->0x%x, ", mp+1, mainbyte);
	for (j=0; j<8; j++) {
	    if (mainbyte & 0x80)
		*cp++ = '1';
	    else
		*cp++ = '0';
	    mainbyte <<= 1;
	}
	hiddenbyte >>= 1;
    }
    *cp = '\0';
    
    DEBUG1("\nstr: [%s]\n", binstr);
    DEBUG1("strlen is %d\n", strlen(binstr));
    
    value_s.value.str = binstr;
    acc_set_value(hcore_word, &value_s, &delay_s);
    tf_putp(0, 0);    
}

/*
 * Usage:  $rdram_mmap_write(memory_id, offset, data)
 * Slame the data in, 
 */
void
rdram_mmap_write(int data, int reason)
{
    handle hcore_word;
    char *val;
    int memid, offset, i, j;
    unsigned char hiddenbyte, mainbyte, *mp;
    char *cp;
    
    if(tf_nump() != 3) {
      tf_error("rdram_mmap_read illegal number of arguments: %d", tf_nump());
      tf_putp(0, -1);
    }

    memid = acc_fetch_tfarg_int(1);
    offset = acc_fetch_tfarg_int(2);
    hcore_word = acc_handle_tfarg(3);
    DEBUG2("\nWrite: id %d, offset is 0x%x\n", memid, offset);

    val = acc_fetch_value(hcore_word, "%b");
    DEBUG1("str: [%s]\n", val);
    DEBUG1("strlen is %d\n", strlen(val));

    hiddenbyte = 0;
    mp = mainaddr + (offset*8) + 7;
    
    for (i=0; i<8; i++) {
	hiddenbyte >>= 1;
	if (*val++ == '1')
	    hiddenbyte |= 0x80;
	
	mainbyte = 0;
	for (j=0; j<8; j++) {
	    mainbyte <<= 1;
	    if (*val++ == '1')
		mainbyte |= 1;
	}
	DEBUG2("%d<--0x%x, ", mp, mainbyte);
	*mp-- = mainbyte;
    }
    DEBUG2("\nhidden: %d<--0x%x\n", hiddenaddr + offset, hiddenbyte);

    *(hiddenaddr + offset) = hiddenbyte;

    tf_putp(0, 0);    
    
    
}