main.c 9.77 KB
/************************************************************************
  WHAT:	RSP SCALAR UNIT VERIFICATION TEST PROGRAM GENERATOR
  SCCS:	@(#)main.c	1.1 03 Aug 1994
  PTLS:	$Id: main.c,v 1.1.1.1 2002/10/29 08:07:09 blythe Exp $
  FILE:	main.c
  ENGR:	Evan Y. Wang
  PROJ:	Project Reality
  (CR):	1994 Silicon Graphics, Inc.
 ************************************************************************
  Files of Interest:

    main.c	This file.
    alu_wi.c	Arithmetic/logic instruction of the WI format.
    alu_www.c	Arithmetic/logic instruction of the WWW format.
    alu_wwi.c	Arithmetic/logic instruction of the WWI format.
    br*.c	Branch instructions.
    gen.h	Main header file.
    j*.c	Jump instructions.
    ld.c	Load instructions.
    st.c	Store instructions.
    suregre.h	Header file used by test programs and also generators.
    table.c	Instruction table and simulation subroutines.
    vld.c	Vector load instructions.
    vlt.c	Matrix transpose instructions (not yet completed).
    vst.c	Vector store instructions.
 ************************************************************************/
#include <stdio.h>
#include <string.h>
#include "software.h"
#include "gen.h"

FILE *fhSFile;			/* rsp sim source file handle		*/

/************************************************************************
  SCALAR UNIT MODEL AND TEST GENERATION VARIABLES
 ************************************************************************/
DATA	Mem[WMEMSIZE];		/* memory model				*/
DATA	VReg[32][4];		/* vector unit register file model	*/
u32	Reg[32];		/* scalar unit register file model	*/
u32	Res = 0;		/* predicted result			*/
u32	OpA = 0;		/* input operand A			*/
u32	OpB = 0;		/* input operand B			*/
u32	Imm = 0;		/* immediate operand			*/
int	rT = 2;			/* prediction reg ID			*/
int	rA = 3;			/* operand A reg ID			*/
int	rB = 4;			/* operand B reg ID			*/
int	rR = 5;			/* destination reg ID			*/
int	CurTcNo = 1;		/* current test case number		*/
int	NxTcNo = 1;		/* next test case number		*/
int	CntA = 0;		/* index used in enumerating operand A	*/
int	CntB = 0;		/* index used in enumerating operand B	*/
int	CntI = 0;		/* index used in enumerating immed op	*/

int	vT = 0;			/* target vector register ID		*/
int	vA = 1;			/* test vector register A ID		*/
int	vB = 2;			/* test vector register B ID		*/
int	vC = 3;			/* test vector register C ID		*/
int	El;			/* element field			*/
u16	VCC;			/* VCC register (mapped to v$1)		*/
u16	VCO;			/* VCO register	(mapped to v$0)		*/

/************************************************************************
  Lookup(..) - finds a given instruction in the instruction table and
  passes back a pointer to that entry.  Lookup returns TRUE if the entry
  is found and the returned pointer is valid.  Otherwise it returns FALSE.
 ************************************************************************/
PRIVATE u1 Lookup(instr, ip)
    char *instr;		/* instruction name to look up		*/
    I_TABLE **ip;		/* instruction table pointer variable	*/
{
    while (*ip <= &InstrTable[InstrTableSize-1]) {
	if (!strcmp(instr, (*ip)->name))
	    return TRUE;
	else
	    (*ip)++;
    }
    return FALSE;
}   /* Lookup */

/************************************************************************
  Header(..) - print common test program header/comment.
 ************************************************************************/
PRIVATE void Header(outp, ip)
    FILE *outp;
    I_TABLE *ip;
{
    fprintf(outp,"/****************************************************************\n");
    fprintf(outp,"  This program tests the instruction: %s\n", ip->name);
    fprintf(outp," ****************************************************************/\n\n");
    fprintf(outp,"#include \"suregre.h\"\n\n");
    fprintf(outp,".base 0x%8.8lX\n\n", IMEM_BASE);
}   /* Header */

/************************************************************************
  Init

/************************************************************************
  InitModel(..) - initialize variables associated wit the model and
  test generation.
 ************************************************************************/
PRIVATE void InitModel(outp, ip)
    FILE * outp;
    I_TABLE * ip;
{
    int i, j;
    u32 tmp;

    /********************************************************************
      Initialize data memory to:
     ********************************************************************/
    switch (ip->mem) {
      case NMEM:
	break;
      case VMEM:
      case SMEM:
	fprintf(outp,"\t.data\t0x%8.8lX\n", DMEM_BASE);
	tmp = 0x01820384;
	for (i=0; i<WMEMSIZE; i++) {
	    fprintf(outp,"\t.word\t0x%8.8lX\n",*WMem[i]=tmp);
	    tmp += 0x04040404;
	    tmp ^= 0x80808080;
	}
	fprintf(outp,"\n");
	vT = 0; vA = 1; El = 0;
	break;
      case ZMEM:
	fprintf(outp,"\t.data\t0x%8.8lX\n", DMEM_BASE);
	for (i=0; i<WMEMSIZE; i++)
	    fprintf(outp,"\t.word\t0x%8.8lX\n",*WMem[i] = 0);
	fprintf(outp,"\n");
	break;
    }

    Reg[0] = 0;
    fprintf(outp,"\tLI(r0 , 0xFFFF, 0xFFFF);\n");
    for (i=1; i<32; i++) {
	Reg[i] = 0x01010101 * i;		/* init model reg file	*/
	fprintf(outp,"\tLI(r%-2d, 0x%4.4X, 0x%4.4X);\n",
		i, HHW(Reg[i]), LHW(Reg[i]));
    }
    Res = OpA = OpB = Imm = 0;			/* init test operands	*/
    rT=2; rA=3; rB=4; rR=5;			/* init reg IDs		*/
    CurTcNo = 1;				/* reset current test no*/
    CntA = CntB = CntI = 0;

    /********************************************************************
      Initialize vector registers
     ********************************************************************/
    if (ip->mem == VMEM || ip->mem == ZMEM) {
	VReg[0][0].w = VReg[0][1].w = VReg[0][2].w = VReg[0][3].w = 0;
	fprintf(outp,"\tlqv	v0[0], 0 (r0);\n");
	for (i=0; i<32; i++) {
	    for (j=0; j<4; j++) VReg[i][j].w = 0;
	    fprintf(outp,"\tvxor	v%-2d, v0, v0\n", i);
	}
    }
}   /* InitModel */

/************************************************************************
  Tail(..) - print common test end statements.
 ************************************************************************/
PRIVATE void Tail(outp, ip)
    FILE *outp;
    I_TABLE *ip;
{
    fprintf(outp,"\n\tori\tr1, r0, 0xFEED;\n");
    fprintf(outp,"Fail:\tbreak;\n");
}   /* Tail */

/************************************************************************
  FormTest(..) - form top-level test program pieces, calling a lower-
  level routine to generate the test cases.
 ************************************************************************/
PRIVATE void FormTest(ip)
    I_TABLE *ip;
{
    int FileCount = 1;		/* test file count per instruction	*/
    char cTFName[20];		/* output test filename buffer		*/
    FILE *fhTFile;		/* output test file handle		*/

    NxTcNo = 1;

    while (NxTcNo != 0) {	/* when NxTcNo == 0, then done	*/

	/****************************************************************
	  Open output file.
	 ****************************************************************/
	sprintf(cTFName, "%s%d.s", ip->name, FileCount);
	if ((fhTFile = fopen(cTFName, "w")) == NULL) {
	    fprintf(stderr,"ERR: Opening file %s failed.\n", cTFName);
	}

	fprintf(fhSFile,"load %s%d.bin 0x%8.8lX\n",ip->name,FileCount,IMEM_BASE);
	fprintf(fhSFile,"load %s%d.dat 0x%8.8lX\n",ip->name,FileCount,DMEM_BASE);
	fprintf(fhSFile,"dep PC 0\nrun\nreg 1\n\n");
	fprintf(stderr,"Now generating %s%d.s...\n",ip->name,FileCount);

	FileCount++;

	/****************************************************************
	  Generate common header and initialization code.
	 ****************************************************************/
	Header(fhTFile, ip);		/* generate file header		*/
	InitModel(fhTFile, ip);		/* init regster file model	*/

	/****************************************************************
	  Generate test cases - We call the appropriate test case
	  generator as stored in the instruction table.  We pass the
	  generator a pointer to the table entry so it can retrieve
	  additional information from the table, the NxTcNo for creating
	  multiple files per instruction, and, the output file handle so
	  the generator can write test cases directly into the test
	  program file.
	 ****************************************************************/
	NxTcNo = ip->gen(fhTFile, ip);

	/****************************************************************
	  Complete each test program with ending code and close the file.
	 ****************************************************************/
	Tail(fhTFile, ip);		/* generate tail		*/
	fclose(fhTFile);

	/****************************************************************
	  Sanity check - could use assert facility here.
	 ****************************************************************/
	if (NxTcNo > 0x1000) {
	    fprintf(stderr,
		    "WARN: Too many test cases generated to be correct!\n");
	    exit(1);
	}

    }   /* while */

}   /* FormTest */

/************************************************************************
  main(..) - gen program entry point.  Determining whether we are
  generating all tests in the instruction table (see table.c) as
  indicated by the absence of any command line argument or just a
  selected few given on the command line.  FormTest is called to
  generate the test program(s) for each instruction.
 ************************************************************************/
void main(argc, argv)
    int argc;
    char *argv[];
{
    I_TABLE *ip = &InstrTable[0];	/* instruction entry pointer	*/

    if ((fhSFile = fopen("su.src", "w")) == NULL) {
	fprintf(stderr,"ERR: Opening file rspsim.src failed.\n");
    }
    fprintf(fhSFile,"silent\n");

    if (argc == 1) {			/* generate all tests		*/
	while (ip <= &InstrTable[InstrTableSize-1])
	    FormTest(ip++);
    } else {				/* generate selected ones	*/
	while (argc-- > 1) {
	    ip = &InstrTable[0];	/* instruction entry pointer	*/
	    if (Lookup(argv[argc], &ip))
		FormTest(ip);
	    else
		printf("ERR: Could not find %s in instruction table.\n",
		       argv[argc]);
	}
    }

    fprintf(fhSFile,"q\n");
    fclose(fhSFile);

}   /* main */