/* ------------------------------------------------------------------------ */ /* SCD (Simulador de circuitos digitales) V0.1a */ /* Autor: Miguel Angel Montejo Raez, Jaen, España */ /* */ /* Este software se rige bajo licencia de software libre, todo uso del */ /* codigo fuente debe incluir el autor original. */ /* */ /* Principio de funcionamiento: */ /* */ /* La forma de simular un proceso electrico es muy simple, usamos dos */ /* matrices de puntos, donde un punto es una conexion electrica. Cada */ /* punto puede adquirir un valor de tension entre 0.0 y 99.99 V. */ /* Realizamos una simulacion en el tiempo, donde en cada fraccion vemos */ /* el estado de cada punto, lo introducimos en los dispositivos y estos */ /* nos dan una respuesta segun su funcionamiento que aplicamos a una */ /* segunda matriz. Despues de cada fraccion copiamos el contenido de la */ /* segunda matriz a la primera y borramos la segunda, para poder realizar */ /* un nuevo analisis. */ /* */ /* Cada dispositivo posee un tiempo de respuesta (efecto de propagacion), */ /* que se simula mediante dispositivos de retardo. */ /* ------------------------------------------------------------------------ */ #include #include #include #include #include /* ------------------------------------------------------------------------ */ /* Funciones */ /* ------------------------------------------------------------------------ */ char lee_fichero(char); void graba_fichero(char); void analisis_tabla(void); void analisis_tiempo(void); void analisis_nudos(void); char analisis_tmp(char); char analisis_clk(void); void error(char); /* ------------------------------------------------------------------------ */ /* Variables globales del circuito */ /* ------------------------------------------------------------------------ */ char titulo_circuito[81]; /* titulo del circuito */ unsigned int *circuito; /* Memoria destinada a guardar el circuito 8000 componentes (4 enteros cada uno) */ unsigned int entradas_tabla[9]; /* entradas definidas para formar la tabla de verdad (8 entradas)*/ unsigned int salidas_tabla[11]; /* salidas para formar la tabla de verdad (10 salidas) */ unsigned int salidas_analisis[11]; /* salidas para tomar las muestras en el analisis (10 salidas) */ char total_entradas;/* indica el total de entradas empleadas */ char total_salidas1;/* indica el total de salidas empleadas en tabla*/ char total_salidas2;/* indica el total de salidas empleadas en analisis*/ unsigned int total_elementos; /* indica el total de componentes en el circuito */ char analiza_tabla; /* 1 formar tabla de verdad, 0 no formarla */ char analiza_tiempo; /* 1 analisis en el tiempo del estado de las salidas 0 no realiza analisis en el tiempo */ unsigned int tiempo_analisis[3]; /* 1- Duracion (0...999) 2- paso (base de tiempos) */ /* BASE DE TIEMPOS: 0 ps, 1 ns, 2 us, 3 ms, 4 s, 5 minutos, 6 horas. /* VALORES PERMITIDOS: Nudos: 0 ... 31999 (32000 se emplea para indicar nudo no empleado). Muestras: 3000 como maximo. */ /* ------------------------------------------------------------------------ */ /* Variables globales para emulacion */ /* ------------------------------------------------------------------------ */ unsigned int vhh,vhl; /* indica el valor del estado alto */ unsigned int vll,vlh; /* indica el valor del estado bajo */ float paso, duracion; unsigned int total_muestras; unsigned int *nudos_ant; /* estado de los nudos previamente (1 int) 0.0 a 99.99 voltios 32000 nudos */ unsigned int *nudos_pos; /* estado de los nudos posteriormente (1 int) 0.0 a 99.99 voltios ESTA TABLA SE COPIA A LA ANTERIOR Y SE BORRA ANTES DE CADA ANALISIS 32000 nudos */ unsigned int *tabla; /* tabla de verdad de entradas y salidas definidas 10 salidas y 8 entradas maximo 256 muestras maximo tama¤o total: 256x18=4608 int (2 bytes) */ unsigned int *muestras; /* memoria de almacenamiento de las muestras tomadas al circuito en el analisis. 3200 muestras de 1 int (0.0 a 99.99 v) 10 nudos a analizar maximo tama¤o total: 3200x10x2=64000 bytes o 32000 int */ /* ------------------------------------------------------------------------ */ /* Variables globales entre funciones */ /* ------------------------------------------------------------------------ */ char fichero[13]; /* nombre del fichero a tratar */ /* ------------------------------------------------------------------------ */ /* Funcion principal */ /* ------------------------------------------------------------------------ */ void main (int argc, char *argv[]) { char a=0; char ch=0; char err=0; /*indica si ha habido error al asignar memoria */ /* Reservamos memoria */ if ((circuito = (unsigned int*) calloc (32000,sizeof(unsigned int)))==NULL) err=1; if ((nudos_ant = (unsigned int*) calloc (32000,sizeof(unsigned int)))==NULL) err=1; if ((nudos_pos = (unsigned int*) calloc (32000,sizeof(unsigned int)))==NULL) err=1; if ((tabla = (unsigned int*) calloc (4608,sizeof(unsigned int)))==NULL) err=1; if ((muestras = (unsigned int*) calloc (32000,sizeof(unsigned int)))==NULL) err=1; /* LOGOTIPO */ printf ("\n\rSimulador de Circuitos Digitales V0.1a beta FREEWARE\n\rMAMR 2001 Jaen España\n\r\n\r"); /* Lectura de la linea de comandos */ if (argc==1) { error(1); err=2; } if (err==0) { for (a=0;a<13;++a) fichero[a]=NULL; for (a=0;ch!=46 && a<8;++a) /* 46 es el punto */ { ch=argv[1][a]; fichero[a]=ch; } if (fichero[a-1]!=46) /* evitamos nombres >8 caracteres */ { fichero[a]=46; ++a; } } /* Llamadas a subrutinas */ if (err==0) { if (lee_fichero(a)==0) { if (analiza_tabla==1) analisis_tabla(); if (analiza_tiempo==1) analisis_tiempo(); graba_fichero(a); } } if (err==1) error(0); /* Liberacion de memoria y cierre del programa */ free (muestras); free (tabla); free (nudos_pos); free (nudos_ant); free (circuito); return; } /* ------------------------------------------------------------------------ */ /* Lectura de fichero .SCD */ /* ------------------------------------------------------------------------ */ char lee_fichero(char b) { /* Variables empleadas en la funcion */ unsigned int a=0; /* uso general */ unsigned int c=0; /* uso general */ char tension=0; /* indica si el operando es un valor de tension */ FILE *pf; /* fichero a abrir */ char ch=0; /* caracter del fichero en lectura */ char titulo=0; /* indica si el comentario es el titulo (0) */ char tipo=0; /* indica el tipo de dato que se est  leyendo 0 comentario/titulo 1 componente del circuito 2 elemento de analisis 3 libreria */ char reconocido=0; /* indica si se ha reconocido un elemento y lo que es: 0 no reconocido 1 elemento: LESS 2 elemento: TMP TABLE 3 elemento: AND TIME 4 elemento: OR IN 5 elemento: NOT OUT 6 elemento: NAND ANA 7 elemento: NOR 8 elemento: XOR 9 elemento: BUFFER 10 elemento: CLK 11 elemento: VDC */ unsigned int elemento=0; /* indica el elemento que se esta introduciendo en el circuito */ char lectura[10]; /* elemento a reconocer */ char ok=0; /* indica si hay un dato disponible */ unsigned int num=0; /* nudo/dato leido */ char punto=0; /* dato con punto en esta posicion */ unsigned char dato=0; /* indica dato/nudo que se esta leyendo */ char ff=0; /* para introducir el titulo */ /* Ponemos a cero las variables globales */ vhh=100; vhl=32000; vll=0; vlh=32000; total_entradas=0; total_salidas1=0; total_salidas2=0; total_elementos=0; analiza_tabla=0; analiza_tiempo=0; tiempo_analisis[0]=0; tiempo_analisis[1]=0; for (a=0;a<80;++a) titulo_circuito[a]=32; for (a=0;a<10;++a) { /* nudo 32000 es no empleado */ if (a<8) entradas_tabla[a]=32000; salidas_tabla[a]=32000; salidas_analisis[a]=32000; lectura[a]=32; } /* Preparamos la extension y abrimos el fichero */ /* extension .SCD */ fichero[b]=115; fichero[b+1]=99; fichero[b+2]=100; /* apertura */ pf=fopen(fichero,"r"); if (pf==NULL) { error(2); return(1); } /* MENSAJE DE ESTADO */ printf("Leyendo circuito: %s\n\r", fichero); /* lectura del fichero */ while ((ch=fgetc (pf))!=EOF) { /* SE RECONOCE LO QUE SE VA A LEER ---------------------------------*/ if (ch==58) /* comentario/titulo ":" */ { /* el primer comentario es el titulo */ while (ch!=EOF && ch!='\n') { ch=fgetc(pf); if (titulo==0) { printf ("%c",ch); if (ff<79) titulo_circuito[ff]=ch; ++ff; } } if (titulo==0) { titulo=1; printf("\n\r"); titulo_circuito[ff]=NULL; } dato=0; tipo=0; c=0; tension=0; } if (ch==42) /* elemento del circuito "*" */ { reconocido=0; dato=0; tipo=1; ++elemento; /*if (elemento>32000) error();*/ for (a=0;a<10;++a) lectura[a]=32; c=0; tension=0; } if (ch==35) /* libreria a incluir "#" */ { reconocido=1; dato=0; tipo=3; for (a=0;a<10;++a) lectura[a]=32; c=0; tension=0; } if (ch==43) /* elemento de analisis "+" */ { reconocido=0; dato=0; tipo=2; for (a=0;a<10;++a) lectura[a]=32; c=0; tension=0; } /* LECTURA DE LOS DATOS RECONOCIDOS --------------------------------*/ if (tipo==1 || tipo==2) /* SUBRUTINAS COMUNES */ { if (reconocido==0 && ch!=32 && ch!='\n') { if (c<10) lectura[c]=ch; ++c; } /* Vemos si se ha leido un dato */ if (reconocido!=0 && ch!=32 && ch!='\n') { /* lectura del dato */ if (c<10 && ch>47 && ch<58) lectura[c]=(ch-48); if (c<10 && ch>103 && ch<118) { if (ch==112) lectura[c]=0; if (ch==110) lectura[c]=1; if (ch==117) lectura[c]=2; if (ch==109) lectura[c]=3; if (ch==115) lectura[c]=4; if (ch==116) lectura[c]=5; if (ch==104) lectura[c]=6; } if (ch==46) punto=c; /* punto */ ++c; } if (reconocido!=0 && c!=0) if (ch==32 || ch=='\n') { num=32000; ok=1; /* convertimos cadena a numero */ /*if (punto!=0 && tension==0) error();*/ if (punto==0 && tension==0) /* sin punto (nudo) */ { /* numero a introducir */ if (c==1) num=lectura[0]; if (c==2) num=(lectura[0]*10+lectura[1]); if (c==3) num=(lectura[0]*100+lectura[1]*10+lectura[2]); if (c==4) num=(lectura[0]*1000+lectura[1]*100+lectura[2]*10+lectura[3]); if (c==5) num=(lectura[0]*10000+lectura[1]*1000+lectura[2]*100+lectura[3]*10+lectura[4]); } if (punto==0 && tension==1) /* sin punto (tension) */ { /* numero a introducir */ if (c==1) num=lectura[0]*100; if (c==2) num=(lectura[0]*1000+lectura[1]*100); /*if (c>2) error ();*/ } if (punto==1 && tension==1) /* con punto */ { /* numero a introducir */ if (c==3) num=lectura[0]*100+lectura[2]; if (c==4) num=(lectura[0]*100+lectura[2]*10+lectura[3]); /*if (c>2) error ();*/ } if (punto==2 && tension==1) /* con punto */ { /* numero a introducir */ if (c==4) num=lectura[0]*1000+lectura[1]*100+lectura[3]; if (c==5) num=(lectura[0]*1000+lectura[1]*100+lectura[3]*10+lectura[4]); /*if (c>2) error ();*/ } if (num!=32000) ++dato; else ok=0; punto=0; c=0; } } if (tipo==1) /* COMPONENTE DEL CIRCUITO --------------------*/ { /* Intentamos reconocer el elemento */ if (reconocido==0) if (ch==32 || ch=='\n') { lectura[c]=32; strlwr (lectura); /* convertimos a minusculas */ if (strstr (lectura,"less ")) reconocido=1; if (strstr (lectura,"tmp ")) reconocido=2; if (strstr (lectura,"and ")) reconocido=3; if (strstr (lectura,"or ")) reconocido=4; if (strstr (lectura,"not ")) reconocido=5; if (strstr (lectura,"nand ")) reconocido=6; if (strstr (lectura,"nor ")) reconocido=7; if (strstr (lectura,"xor ")) reconocido=8; if (strstr (lectura,"buffer ")) reconocido=9; if (strstr (lectura,"clk ")) reconocido=10; if (strstr (lectura,"vdc ")) reconocido=11; if (reconocido!=0) { c=0; dato=0; num=32000; punto=0; } } /* Leemos los datos/nudos del elemento */ if (ok==1) { circuito[(elemento-1)*4]=reconocido; switch (reconocido) { case 0: break; /* no reconocido */ case 1: /* LESS */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ if (dato==2) tension=1; break; case 2: /* TMP */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 3: /* AND */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 4: /* OR */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 5: /* NOT */ if (dato<3) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 6: /* NAND */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 7: /* NOR */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 8: /* XOR */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 9: /* BUFFER */ if (dato<4) circuito[(elemento-1)*4+dato]=num; /* else error(); */ break; case 10: /* CLK */ if (dato<4) circuito[(elemento-1)*4+dato]=num; break; case 11: /* VDC */ if (dato<3) circuito[(elemento-1)*4+dato]=num; if (dato==1) tension=1; /* else error(); */ break; } ok=0; } } if (tipo==2) /* ELEMENTO DE ANALISIS -----------------------*/ { /* Intentamos reconocer el elemento */ if (reconocido==0) if (ch==32 || ch=='\n') { lectura[c]=32; strlwr (lectura); /* convertimos a minusculas */ if (strstr (lectura,"table ")) { reconocido=2; analiza_tabla=1; } if (strstr (lectura,"time ")) reconocido=3; if (strstr (lectura,"in ")) reconocido=4; if (strstr (lectura,"out ")) reconocido=5; if (strstr (lectura,"ana ")) reconocido=6; if (strstr (lectura,"vhh ")) { reconocido=7; tension=1; } if (strstr (lectura,"vhl ")) { reconocido=8; tension=1; } if (strstr (lectura,"vlh ")) { reconocido=9; tension=1; } if (strstr (lectura,"vll ")) { reconocido=10; tension=1; } if (reconocido!=0) { c=0; dato=0; num=32000; punto=0; } } /* Leemos los datos/nudos del analisis */ if (ok==1) { switch (reconocido) { case 0: break; /* no reconocido */ case 1: break; /* no empleado */ case 2: /* TABLE */ break; case 3: /* TIME */ analiza_tiempo=1; if (dato<3) tiempo_analisis[dato-1]=num; /* else error(); */ break; case 4: /* IN */ if (dato<9) { entradas_tabla[dato-1]=num; ++total_entradas; } /* else error(); */ break; case 5: /* OUT */ if (dato<11) { salidas_tabla[dato-1]=num; ++total_salidas1; } /* else error(); */ break; case 6: /* ANA */ if (dato<11) { salidas_analisis[dato-1]=num; ++total_salidas2; } /* else error(); */ break; case 7: /* VHH */ if (dato<2) vhh=num; /* else error(); */ break; case 8: /* VHL */ if (dato<2) vhl=num; /* else error(); */ break; case 9: /* VLH */ if (dato<2) vlh=num; /* else error(); */ break; case 10: /* VLL */ if (dato<2) vll=num; /* else error(); */ break; } ok=0; } } if (tipo==3) /* NOMBRE DE LIBRERIA -------------------------*/ { } } if (vhl==32000) vhl=vhh; if (vlh==32000) vlh=vll; /* cerramos el fichero y retornamos */ fclose(pf); total_elementos=elemento; printf ("%d componente(s) en el circuito.\n\r\n\r",total_elementos); return(0); } /* ------------------------------------------------------------------------ */ /* Mensajes de error */ /* ------------------------------------------------------------------------ */ void error (char err) { switch (err) { case 0: printf ("Error #0: memoria insuficiente para ejecutar el programa.\n\r"); break; case 1: printf ("Error #1: no se ha especificado el fichero a tratar (.SCD)\n\r"); break; case 2: printf ("Error #2: no se puede abrir el fichero %s\n\r", fichero); break; case 3: printf ("Error #3: no se puede crear el fichero %s\n\r", fichero); break; } } /* ------------------------------------------------------------------------ */ /* Creacion de fichero de salida .OUT */ /* ------------------------------------------------------------------------ */ void graba_fichero(char b) { /* Variables empleadas en la funcion */ struct date d; /* fecha */ struct time t; /* hora */ unsigned int a=0; /* uso general */ unsigned int c=0; /* uso general */ unsigned int e=0; /* uso general */ unsigned int e1,e2; /* para sacar enteros y decimales */ FILE *pf; /* fichero a abrir */ /* Preparamos la extension y abrimos el fichero */ /* extension .OUT */ fichero[b]=111; fichero[b+1]=117; fichero[b+2]=116; /* apertura */ pf=fopen(fichero,"w"); if (pf==NULL) { error(3); return; } /* MENSAJE DE ESTADO */ printf("Generando fichero de salida: %s\n\r",fichero); /* Cabecera del fichero */ getdate(&d); /* recoge la fecha */ gettime(&t); /* recoge la hora */ fprintf(pf, " ----------------------------------------------------------------------------\n"); fprintf(pf, "| Simulador de circuitos digitales V0.1a beta |\n"); fprintf(pf, "| MAMR 1997/98 Ja‚n Espa¤a |\n"); fprintf(pf, " ----------------------------------------------------------------------------\n\n"); fprintf(pf, "Titulo del circuito:\n%s\n",titulo_circuito); fprintf(pf, "Fecha y hora del analisis: %d/%d/%d ",d.da_day,d.da_mon,d.da_year); fprintf(pf, "%2d:%02d:%02d\n",t.ti_hour, t.ti_min, t.ti_sec); /* GRABACION DE LA TABLA DE VERDAD */ if (analiza_tabla==1) { fprintf(pf, "\n******************************* TABLA DE VERDAD ******************************\n\n"); c=1; for (a=0;a9 && e2<10) fprintf(pf, " "); if (e1<10 && e2>9) fprintf(pf, " "); if (e1>9 && e2>9) fprintf(pf, " "); ++c; } fprintf(pf, "\n"); } } /* cerramos el fichero y retornamos */ fclose(pf); return; } /* ------------------------------------------------------------------------ */ /* Creacion de la tabla de verdad */ /* ------------------------------------------------------------------------ */ void analisis_tabla() { /* Variables de esta funcion */ unsigned int a=0,b=0,c=1,d[9],e=0; /* variables generales */ /* Borramos el estado de los nudos */ for (a=0;a<32000;++a) nudos_ant[a]=vll; /* MENSAJE DE ESTADO */ printf("Creando tabla de verdad:\n\r"); printf("%d entrada(s).\n\r%d salida(s).\n\r\n\r",total_entradas,total_salidas1); for (a=0;a0;--duracion) { if (c0) if ( ((float)(((int)duracion)/((int)temp))) == (duracion/temp) ) { if (nudos_ant[nd1]0) if ( ((float)(((int)duracion)/((int)temp))) == (duracion/temp) ) { nudos_pos[nd2]=nudos_ant[nd1]; igual=1; /* indica si ha variado algun nudo */ } } ++a; } return(igual); } void analisis_nudos() /* NO TIENE EN CUENTA LOS TMP */ { /* Variables de esta funcion */ unsigned int a=0; /* variables generales */ unsigned int nd1=0,nd2=0,nd3=0; /* valores del elemento */ unsigned int elemento=0; /* indica el elemento que se est  simulando */ /* Borramos el nuevo estado de los nudos */ for (a=0;a<32000;++a) nudos_pos[a]=vll; a=0; /* ANALISIS */ while ((elemento=circuito[a*4])!=0) { /* recogemos los nudos y datos */ nd1=circuito[(a*4)+1]; nd2=circuito[(a*4)+2]; nd3=circuito[(a*4)+3]; switch (elemento) { case 0: /* no reconocido */ break; case 1: /* LESS */ if (nudos_ant[nd1]>=nd3) nudos_pos[nd2]=nudos_ant[nd1]-nd3; else nudos_pos[nd2]=0; break; case 2: /* TMP */ nudos_pos[nd2]=nudos_ant[nd2]; break; case 3: /* AND */ if (nudos_ant[nd1]>=vhl && nudos_ant[nd2]>=vhl) nudos_pos[nd3]=vhh; break; case 4: /* OR */ if (nudos_ant[nd1]>=vhl || nudos_ant[nd2]>=vhl) nudos_pos[nd3]=vhh; break; case 5: /* NOT */ if (nudos_ant[nd1]