/***************************** * PAL Simulator * * version 2.0 * * * * stdin * * command line opt s * * -e echo flag * * -l long output * * -x1 or -x0 value of * * don't care * * * * walz@cps3xx (william walz) * *****************************/ #define MAX_NUM_STACKS 10 // max number of stacks allowed #define MAX_OUTPUT_TERMS 10 // max number of output terms allowed #define NUM_OF_PINS 25 // max number of pins used #define MAX_VECTORS 200 // max number of vectors allowed #define MAX_LABEL_SIZE 20 // max number of characters allowed for a label #define SANITY_CHECK 150 // max number of operands and operators in a // single equation extern "C" { /* NeXTstation interface */ #include /* will work with g++ though */ #include #include #include #include } /************************************************************************ * Data Structures * * * * node: * * A node holds the value and state for each operand or operator in an * * equation. It also points to the next node. The end of the list * * is signaled by the 'next' field pointing to itself. The ascii text * * for an operand or operator is held in 'info'. * * * * output: * * Each output structure holds the value and state of an output label * * and pointers to the begining 'head' of the equations for that label * * and the current 'node' (held in 'pnode'). The ascii text of the * * label is held in 'label'. * * * * pin_io: * * Pin_io holds the state and value of each pin. And the ascii text * * for the label assigned to that pin (held in 'x'). Also there is a * * declared flag. * * * * val: * * Val is simply an array of 100 integers used by stack. * * * ************************************************************************/ typedef struct node { char info[20]; int value,state; struct node * next;}; typedef struct output {char label[20];int value,ostate;struct node *pnode, *head;}; typedef struct pin_io { char x[20];int state,value,pin,declared;}; typedef struct val {int x[100];}; void remove_comment(void); /* forward defined functions */ void error(int); void cursor_x(int); int no_case_cmp(char *,char *); /********************************************************************* * Class Stack: * * * * This Class is a simple array type implementaion of a stack made * * up of MAX pointers to arrays of 100 integers. If no stack * * # argument is given stack zero will be assumed. Note that Stack * * is invoked with the number of stacks needed, if no argument is * * given 1 stack will be created. * * * *********************************************************************/ class Stack { static int top_of_stack[MAX_NUM_STACKS]; struct val *stack; public: Stack(int y=1) { if (y>MAX_NUM_STACKS) /* check validity of */ {printf("Internal Error!\n");exit(1);} /* requested stacks */ for(int x=0;xnext;return(a);} int find_pin(char *); }; /*********************************************/ /* Add an operand or operator to an equation */ void PAL::build_eqn(struct node *t,int echo=0) { if (pal[pcount].pnode==NULL) pal[pcount].head=t; else pal[pcount].pnode->next=t; pal[pcount].pnode=t; t->next=t; if (echo==1) printf(" ::Operand Entered\n"); } /********************************************************/ /* Find Pin this checks to see if label is in Pin table */ int PAL::find_pin(char *a) { int found=0; for(int x=0;xNUM_OF_PINS) {error=3;done++;} } } } } return error; } /***************************************************************************/ /* This member function takes 3 arguments. 1st argument is used to convey */ /* the current vector number to the user. The 2nd argument is passed a one */ /* to tell function that the key word 'vector' has already been found, or */ /* a zero to tell the function to check for the key word 'vector'. */ /* this function also removes comments. The last argument is the long_flag.*/ int PAL::read_vector(int num_vec,int found=0,int long_flag=0) { char c[100];int output=0,x,temp=0; if (scanf("%s",c)==EOF) output++; // get input else if (no_case_cmp(c,"end")==1) output++; // check to see if done else { if (no_case_cmp(c,"vector")==1 || found==1) { if (found==0) scanf("%s",c); /* process vector */ printf("##Vector Number: %d Read in: %s\n",num_vec,c); if (long_flag==1) printf("##Vector Assignments:\n"); for(x=0;x<23;x++) { switch(c[x]) { case '1': temp=1; break; case '0': temp=0; break; case 'X': temp=dont_care; break; case 'N': break; case 'L': temp=0; break; case 'H': temp=1; break; default:temp=0;break; } if (long_flag==1 && variables[x+1].declared==1) printf("%s\t=\t%d\n",variables[x+1].x,temp); variables[x+1].value=temp; } } else if (c[0]=='\'') // process comment {remove_comment();output=2;} } return (output); } /*********************************************/ /* This member function evaluates the vector */ int PAL::eval_vector(int echo=0,int long_flag=0) { printf("##Evaluationg Vector\n"); char c,b[2],a[4];int z,out,t1,t2,t3,term_count,result,eqn,error; for(int x=0;xinfo,variables[z].x)==0) t1=variables[z].value; else if (strcmp(pal[x].pnode->info,"1")==0) t1=1; else if (strcmp(pal[x].pnode->info,"0")==0) t1=0; if (t1!=1000) { /** the equation below xor's the value with the state *****/ pal[x].pnode->value=(t1 ^ pal[x].pnode->state); if (long_flag==1) { if (pal[x].pnode->state==1) strcpy(b,"/"); else strcpy(b," "); if (t3==0) strcpy(a," "); else strcpy(a," "); printf("%s%s%s(%d) ",a,b,pal[x].pnode->info, pal[x].pnode->value); t3++; } break; } } if (long_flag==1 && t1==1000) { if (pal[x].pnode->info[0]=='+') {t3=0;printf("\n\n + \n\n");} else printf(" %s ",pal[x].pnode->info); if (t3>3) {printf("\n");t3=0;} } if (pal[x].pnode==pal[x].pnode->next) { if (long_flag==1) printf("\n\n"); break; } pal[x].pnode=pal[x].pnode->next; } } for(x=0;xvalue; /* push the and terms on the and stack */ t2=pal[eqn].pnode->state; /* changing stacks when a '+' is found */ if (t2==0 || t2==1) and_stack.Push(t1,term_count); else if (t2==10) term_count++; if (pal[eqn].pnode==pal[eqn].pnode->next) break; pal[eqn].pnode=pal[eqn].pnode->next; } for(x=1;x=1) printf("\n%s = %d",pal[eqn].label,result); if (long_flag==1 || error>=1) printf("\nExpected Result %d\n",variables[z].value); } if (error!=0) printf("\nERROR Result does not equal expected result!\n\n"); else printf("##Vector is correct\n\n"); return error; } /***************** * Remove comment * *****************/ void remove_comment() {char b;while(b!='\n') b=fgetc(stdin);} /**************************** * compare ignoring case * * -note second variable * * assumed to be lowercase * ****************************/ int no_case_cmp(char *a,char *b) { char c[100]; for(int x=0;xMAX_LABEL_SIZE) return 1; else return 0; } /************* * Find Label * *************/ struct output * find_label(int echo=0) { struct output *temp=new output; strcpy(temp->label,"none"); char c[200],b[200];int x; if (scanf("%s",c)==EOF) strcpy(c,"none"); /* EOF detected done */ else { switch (c[0]) { case 'e': case 'E': /* check for end */ if (no_case_cmp(c,"end")==1) strcpy(c,"done"); break; case '\'': remove_comment(); /* remove comment */ strcpy(c,"comment"); break; case 'v': case 'V': /* check for vector */ if (no_case_cmp(c,"vector")==1) strcpy(c,"vector"); break; default: if (size_test(c)==1) error(8); if (isalpha(c[0]) || c[0]=='/') { /****** check output state *******/ scanf("%s",b); if (strcmp(b,"/=")==0) temp->ostate=1; else if (b[0]=='=') temp->ostate=0; else error(9); if (echo==1) printf("\n\n## Found Label: %s\n",c); } } } strcpy(temp->label,c); return (temp); } /***************/ /* get operand */ /***************/ struct node *get_operand(PAL pld_file,int echo=0) { char c[200];int offset=0; struct node *temp=new node; scanf("%s",c);temp->value=0; if (size_test(c)==1) error(8); if (c[strlen(c)-1]==';') /* check for end of equation */ {temp->value=1;c[strlen(c)-1]=0;} switch (c[0]) { case '/': /* check to see if inversion */ if (pld_file.find_pin(c)==1) /* is needed */ {offset=0;temp->state=0;} else {offset=1;temp->state=1;} break; case ';': temp->state=-1;break; case '+': temp->state=10;break; case '*': temp->state=20;break; case '\'': temp->state=30; remove_comment(); break; default: temp->state=0; break; } if (echo==1 && temp->state!=30) printf(" ## Found Operand: %s\n",c); strcpy(temp->info,c+offset); return(temp); } /************************ * error function * * -note execution will * * terminate here * ************************/ void error(int type) { switch(type) { case 0:exit(0);break; case 1: fprintf(stderr,"\nCommand Line Errors!!\n\n"); fprintf(stderr,"USAGE: pldsim [-e] [-l] [-x0 | -x1]\n"); fprintf(stderr," -e echo input to output.\n"); fprintf(stderr," -l long output of vectors.\n"); fprintf(stderr," -x1 set don't care value to 1.\n"); fprintf(stderr," -x0 set don't care value to 0.\n\n"); break; case 2: fprintf(stderr,"\nError During Pin Out Read!!\n\n"); break; case 3: fprintf(stderr,"\nError No Start Found!\n\n"); break; case 4: fprintf(stderr,"\nError No Device Found!\n\n"); break; case 5: fprintf(stderr,"\nError No Equations Found!\n\n"); break; case 6: fprintf(stderr,"\nError No Pins Found!\n\n"); break; case 7: fprintf(stderr,"\nError To Many Pins Found!\n\n"); break; case 8: fprintf(stderr,"\nError Label To Long!\n\n"); break; case 9: fprintf(stderr,"\nError Incorrect Format of Label Definition!\n\n"); break; case 10: fprintf(stderr,"\nError Equation too Long!\n\n"); break; default: fprintf(stderr,"\nInternal Error!!\n\n"); break; } fprintf(stderr,"\a\a\n"); fflush(stderr); exit(1); } /************************* * MAIN * * command line opt s * * -e echo flag * * -l long output * * -x1 or -x0 value of * * don't care * * * *************************/ main(int argc, char **argv) { printf("\n\nPAL Equation Simulator\nWritten by Bill Walz\nOCT 1991\n\n"); printf("Enter Equations (begin with 'start' and end with 'end')\n\n"); int done=0,echo_flag=0,long_flag=0,temp_int; int vector_count,x,dont_care=0,sane,z; int error_db[MAX_VECTORS+1]; for(temp_int=0;temp_intlabel,"none")==0 || strcmp(eqn->label,"done")==0 || strcmp(eqn->label,"vector")==0) done++; else if (strcmp(eqn->label,"comment")!=0) { pld_file.begin_eqn(eqn,echo_flag);sane=0; for(;;) { struct node *op=get_operand(pld_file,echo_flag); if (op->state==-1) break; if (op->value==1) {pld_file.build_eqn(op,echo_flag);break;} if (op->state!=30) pld_file.build_eqn(op,echo_flag); if (sane++>SANITY_CHECK) error(10); } pld_file.inc_eqn(); } } if (pld_file.num_eqn()==0) error(5); else printf("\n%d Equations Read\n",pld_file.num_eqn()); if (pld_file.num_pin()==0) error(6); else printf("%d Pins Read\n\n\n",pld_file.num_pin()); switch (eqn->label[0]) { case 'n': case 'd': error(0); break; case 'v': temp_int=0;vector_count=1; pld_file.read_vector(vector_count++,1,long_flag); temp_int=pld_file.eval_vector(echo_flag,long_flag); if (temp_int>=1) error_db[(vector_count-1)]=temp_int; done=0; while(!done) { done=pld_file.read_vector(vector_count++,0,long_flag); if (done==0) { temp_int=0; temp_int+=pld_file.eval_vector(echo_flag,long_flag); if (temp_int>=1) error_db[(vector_count-1)]=temp_int; } else if (done==2) {vector_count--;done=0;} } vector_count=1;temp_int=0; for(x=1;x=1) { printf("%d Error(s) detected at vector: %d\n", error_db[vector_count],vector_count);temp_int++; } vector_count++; } if (temp_int==0) printf("\n\nNo Errors Detected!\n\n"); else printf("\n\n\a%d Vector(s) Have ERRORS!\a\n\n",temp_int); default:break; } }