ilmain.c 12.6 KB
/************************************************************************
  WHAT:	RSP VECTOR UNIT INTERLOCK VERIFICATION TEST PROGRAM GENERATOR
  SCCS:	%W% %G%
  PTLS:	$Id: ilmain.c,v 1.1.1.1 2002/05/02 03:29:14 blythe Exp $
  ENGR:	Evan Y. Wang
  PROJ:	Project Reality
  (CR):	1994 Silicon Graphics, Inc.
 ************************************************************************/
#include <stdio.h>
#include <string.h>
#include "software.h"
#include "ilgen.h"

/************************************************************************
  REGRESSION TEST GENERATOR VARIABLES.
 ************************************************************************/
FILE *fhSFile;
FILE *fhTFile;
char cTFName[20];
int  Space = 2;

int  Src1RegID = 2;			/* cycle through 1-15		*/
int  Src2RegID = 3;			/* cycle through 1-15		*/
int  Src3RegID = 4;			/* cycle through 1-15		*/
int  DumpRegID = 5;			/* cycle through 1-15		*/
int  CDmpRegID = 6;			/* cycle through 1-15		*/
int  TempRegID = 7;			/* cycle through 1-15		*/
int  DestRegID = 16;			/* Stay fixed for ltv and stv	*/
int  CDstRegID = 24;			/* Stay fixed for ltv and stv	*/

/************************************************************************
  RSP STATE MODEL.
 ************************************************************************/
u32  Vco;
u32  Reg[32];
UD32 VReg[32][4];
UD32 DMem[DMEM_SIZE>>2];				/* 4K of DMEM	*/

u32 Rand32()
{
    return (((u32) (rand()&0x3FF)<<22)
	    | ((u32) (rand()&0x3FF)<<12)
	    | ((u32) (rand()&0xFFF)));
}

/************************************************************************
  Header(..) - print common test program header/comment.
 ************************************************************************/
PRIVATE void Header(outp,fno)
    FILE *outp;
    int  fno;
{
    fprintf(outp,"/********************************");
    fprintf(outp,"********************************\n");
    fprintf(outp,"  SCALAR UNIT INTERLOCK TEST: %d\n", fno);
    fprintf(outp," ********************************");
    fprintf(outp,"********************************/\n\n");
    fprintf(outp,".base 0x%8.8lX\n\n", IMEM_BASE);
} /* Header */

/************************************************************************
  AddSrcEntry(..) - add to the rspsim source file.
 ************************************************************************/
PRIVATE void AddSrcEntry(outp, tfno)
    FILE *outp;
    int  tfno;
{
	fprintf(fhSFile, "load iltest%d.bin 0x04001000\n",tfno);
	fprintf(fhSFile, "load iltest%d.dat 0x04000000\n",tfno);
	fprintf(fhSFile, "dep PC 0\nsilent\nrun\nreg 1\n");

} /* AddSrcEntry */

/************************************************************************
  DmemInit(..) - initialize DMEM.
 ************************************************************************/
PRIVATE void DMemInit(outp)
    FILE *outp;
{
    int i;
    u32 tdp;

    tdp = 0;
    for (i=0; i<(DMEM_SIZE>>2); i++, tdp+=4)
	fprintf(outp,"\t.word\t0x%8.8lX\t\t/* Addr: 0x%4.4X */\n",
		DMem[i].w=Rand32(), tdp);

} /* DMemInit */

/************************************************************************
  RFileInit(..) - initialize scalar unit register file.
 ************************************************************************/
PRIVATE void RFileInit(outp)
    FILE *outp;
{
    int i;
    LI(0 , 0xFFFFFFFF);
    for (i=1; i<32; i++) {
	LI(i, (0x01010101 * i));
    }
} /* RFileInit */
/************************************************************************
  Tail(..) - print common test end statements.
 ************************************************************************/
PRIVATE void Tail(outp)
    FILE *outp;
{
    int i;
    
    fprintf(outp,"\n\tlui\t$1, 0xFEED;\n");
    for (i=0; i<32; i++) {
      fprintf(outp,"\tsw\t$%d, 0x%x($0);\n", i, 0xf80+(i*4));
    }
    fprintf(outp,"Fail:\tbreak;\n");
} /* Tail */

/************************************************************************
  TestGen(..) - generate a test case
 ************************************************************************/
PRIVATE void TestGen(outp,tno,i1,i2,rt,r1,r2,r3,rd,rct,rcd,rtmp)
    FILE *outp;		/* test file handle			*/
    int  tno;		/* test number				*/
    int  i1;		/* test instruction 1 index to I1Table	*/
    int  i2;		/* test instruction 2 index to I2Table	*/
    int  rt;		/* target/destination register ID	*/
    int  r1;		/* source 1 register ID			*/
    int  r2;		/* source 2 register ID			*/
    int  r3;		/* source 2 register ID			*/
    int  rd;		/* dump register ID			*/
    int  rct;		/* check rt register ID			*/
    int  rcd;		/* check rd register ID			*/
    int  rtmp;		/* temp register ID			*/
{
    int i;

    fprintf(outp,"\t/* TEST #%2.2d ",tno);
    fprintf(outp,"*********************************************/\n");
    fprintf(outp,"\t/* T#=$1 Rt=$%d R1=$%d R2=$%d R3=$%d Rd=$%d Rct=$%d Rcd=$%d Rtmp=$%d */\n",
	    rt, r1, r2, r3, rd, rct, rcd, rtmp);
    fprintf(outp,"\tlui\t$1,  0x%X\n\n",tno);

    fprintf(outp,"\t/* Initialization */\n");

    /********************************************************************
      Initialize SU registers
     ********************************************************************/
    Reg[rt] = Reg[rct] = Rand32();	LI(rt,Reg[rt]);
    Reg[r1] = Rand32();			LI(r1,Reg[r1]);
    Reg[r2] = Rand32();			LI(r2,Reg[r2]);
    Reg[r3] = Rand32() & ~0xF;		LI(r3,Reg[r3]);
    Reg[rd] = Reg[rcd] = Rand32();	LI(rd,Reg[rd]);
    Reg[rtmp] = Rand32() & ~0xF;	LI(rtmp,Reg[rtmp]);
    OR(rct,rt,0);
    OR(rcd,rd,0);

    /********************************************************************
      Initialize VU registers
     ********************************************************************/
    LQV( rt,  rtmp);
    LQV( rct, rtmp);
    ADDI(rtmp,rtmp,0x10);
    LQV( r1,  rtmp);
    ADDI(rtmp,rtmp,0x10);
    LQV( r2,  rtmp);
    ADDI(rtmp,rtmp,0x10);
    LQV( r3,  rtmp);
    ADDI(rtmp,rtmp,0x10);
    LQV( rd,  rtmp);
    LQV( rcd, rtmp);
    if (I1Table[i1].op == OP_LTV
	|| I2Table[i2].op == OP_STV) {
	for (i=1; i<8; i++) {
	    ADDI(rtmp,rtmp,0x10);
	    LQV( rt+i, rtmp);
	    LQV( rct+i,rtmp);
	}
    }
    Vco = Reg[r2];  CTC2(r2,0);
    NOP(); NOP(); NOP();
    NEWLINE();

    /********************************************************************
      Pre-compute answer to interlock test by running the same
      instruction pair under non-interlocking circumstance.  This
      is basically, rt replaced by rtmp1, rd replaced rtmp2, and
      NOPs inserted between the pair of test instructions.
     ********************************************************************/
    fprintf(fhTFile,"\t/* Pre-compute answer */\n");
    switch (I1Table[i1].atype) {
      case ARG_VVV: fprintf(fhTFile,I1Table[i1].instr,rct,r1,r2);	break;
      case ARG_VR:  fprintf(fhTFile,I1Table[i1].instr,rct,r1);		break;
      case ARG_RV:  fprintf(fhTFile,I1Table[i1].instr,r1,rct);		break;
      case ARG_R:   fprintf(fhTFile,I1Table[i1].instr,r1);		break;
    }
    NOP(); NOP(); NOP();
    if (I2Table[i2].op == OP_SQV) {
	LQV(rct, r3);
    } else if (I2Table[i2].op == OP_STV) {
	LTV(rct, r3);
    } else {
	switch (I2Table[i2].atype) {
	  case ARG_VVV: fprintf(fhTFile,I2Table[i2].instr,rcd,rct,r3);	break;
	  case ARG_VR:  fprintf(fhTFile,I2Table[i2].instr,rct,r3);	break;
	  case ARG_RV:  fprintf(fhTFile,I2Table[i2].instr,rcd,rct);	break;
	  case ARG_R:   fprintf(fhTFile,I2Table[i2].instr,rcd);		break;
	}
    }

    NOP(); NOP(); NOP();
    CFC2(rt,0);  NOP();
    CTC2(r2,0);

    NEWLINE();

    /********************************************************************
      Print test instruction pair.
     ********************************************************************/
    fprintf(fhTFile,"\t/* Test */\n");
    NOP(); NOP(); NOP();
    switch (I1Table[i1].atype) {
      case ARG_VVV: fprintf(fhTFile,I1Table[i1].instr,rt,r1,r2);	break;
      case ARG_VR:  fprintf(fhTFile,I1Table[i1].instr,rt,r1);		break;
      case ARG_RV:  fprintf(fhTFile,I1Table[i1].instr,r1,rt);		break;
      case ARG_R:   fprintf(fhTFile,I1Table[i1].instr,r1);		break;
    }

    for (i=0; i<Space; i++)
	fprintf(outp,"\tnop\n");

    switch (I2Table[i2].atype) {
      case ARG_VVV: fprintf(fhTFile,I2Table[i2].instr,rd,rt,r3);	break;
      case ARG_VR:  fprintf(fhTFile,I2Table[i2].instr,rt,r3);		break;
      case ARG_RV:  fprintf(fhTFile,I2Table[i2].instr,rd,rt);		break;
      case ARG_R:   fprintf(fhTFile,I2Table[i2].instr,rd);		break;
    }
    NOP(); NOP(); NOP();

    NEWLINE();

} /* TestInit */

/************************************************************************
  ResultCheck(..).
 ************************************************************************/
PRIVATE void ResultCheck(outp,i1,i2,rt,r1,r2,r3,rd,rct,rcd,rtmp)
    FILE *outp;		/* test file handle			*/
    int  i1;		/* test instruction 1 index to I1Table	*/
    int  i2;		/* test instruction 2 index to I2Table	*/
    int  rt;		/* target/destination register ID	*/
    int  r1;		/* source 1 register ID			*/
    int  r2;		/* source 2 register ID			*/
    int  r3;		/* source 3 register ID			*/
    int  rd;		/* dump register ID			*/
    int  rct;		/* check rt register ID			*/
    int  rcd;		/* check rd register ID			*/
    int  rtmp;		/* temp register ID			*/
{
    int i;

    /* buffering from the test instruction pair */
    fprintf(outp,"\t/* Result Check */\n");

    /* check VCO */
    CFC2(r1,0);  NOP();
    BNE(r1,rt);  NOP();
    CTC2(0, 0);  NOP();		/* clear VCO for vector compare */

    /* check scalar dump register */
    BNE(rd,rcd);  NOP();

    /* check dump register */
    Reg[r1] = 0xFF;
    LI(r1,Reg[r1]);
    VEQ(rtmp,rd,rcd);  NOP();  NOP();
    CFC2(rtmp,1);  NOP();
    BNE(rtmp,r1);  NOP();

    if (   I2Table[i2].op == OP_SQV
	|| I1Table[i1].op == OP_LTV
	|| I2Table[i2].op == OP_STV) {

	if (I2Table[i2].op == OP_SQV)  LQV( rct, r3);
	if (I2Table[i2].op == OP_STV)  LTV( rct, r3);

	VEQ(rtmp,rt,rct);  NOP();  NOP();
	CFC2(rtmp,1);  NOP();
	BNE(rtmp,r1);  NOP();

	if (I1Table[i1].op == OP_LTV || I2Table[i2].op == OP_STV) {
	    for (i=1; i<8; i++) {
		VEQ(rtmp, rt+i, rct+i);  NOP();  NOP();
		CFC2(rtmp,1);  NOP();
		BNE(rtmp,r1);  NOP();
	    }
	}
    } else {
	/* check target register */
	VEQ(rtmp,rt,rct);  NOP();  NOP();
	CFC2(rtmp,1);  NOP();
	BNE(rtmp,r1);  NOP();
    }

    NEWLINE();

} /* ResultCheck */

/************************************************************************
  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[];
{
    int i1, i2;
    int FileCount = 1;
    int TestNum = 1;

    if ((fhSFile = fopen("ilt.scr", "w")) == NULL) {
	fprintf(stderr, "ERROR:\tOpening file ilt.scr failed.\n");
	fprintf(stderr, "\tContinuing...\n");
    }

    /********************************************************************
      For each instruction in table I1Table[], generate a test file.
     ********************************************************************/
    for (i1=0; i1<I1TableSize; i1++) {

	/* For each instruction in table I2Table, generate a test case. */
	for (i2=0; i2<I2TableSize; i2++) {

	    i1 = i1;

	    /* Eliminate incompatible instruction pairs. */
	    if (I1Table[i1].grpmsk & I2Table[i2].grpmsk) {

		/* Open test file. */
		sprintf(cTFName,"iltest%d.s",FileCount);
		if ((fhTFile = fopen(cTFName, "w")) == NULL) {
		    fprintf(stderr, "ERROR:\tOpening file %s failed.\n", cTFName);
		    fprintf(stderr, "\tExiting...\n");
		    exit(1);
		}
		Header(fhTFile,FileCount);	/* Print header for files	*/
		DMemInit(fhTFile);		/* Initialize DMEM		*/
		RFileInit(fhTFile);		/* Initialize SU RFile  	*/
		/* Add entry to rspsim source file for current test file. */
		if (fhSFile != NULL) AddSrcEntry(fhSFile, FileCount);

		/* Vary the number of NOPs between the instruction pair. */
		for (Space=3; Space>=0&&Space>=I1Table[i1].min_nop; Space--) {

		    TestGen(fhTFile,
			    TestNum,
			    i1,
			    i2,
			    DestRegID,
			    Src1RegID,
			    Src2RegID,
			    Src3RegID,
			    DumpRegID,
			    CDstRegID,
			    CDmpRegID,
			    TempRegID);

		    ResultCheck(fhTFile,
				i1,
				i2,
				DestRegID,
				Src1RegID,
				Src2RegID,
				Src3RegID,
				DumpRegID,
				CDstRegID,
				CDmpRegID,
				TempRegID);

		    TestNum++;
		    Src1RegID = ((Src1RegID-2)%13)+3;
		    Src2RegID = ((Src2RegID-2)%13)+3;
		    Src3RegID = ((Src3RegID-2)%13)+3;
		    DumpRegID = ((DumpRegID-2)%13)+3;
		    CDmpRegID = ((CDmpRegID-2)%13)+3;
		    TempRegID = ((TempRegID-2)%13)+3;
		}

		Tail(fhTFile);
		fclose(fhTFile);
		fhTFile = NULL;
		FileCount++;
	    }
	}
    }

    fclose(fhSFile);

} /* main */