Professional Documents
Culture Documents
/*=======================================================================
A simple parser for "self" format
The circuit format (called "self" format) is based on outputs of
a ISCAS 85 format translator written by Dr. Sandeep Gupta.
The format uses only integers to represent circuit information.
The format is as follows:
1
-----0 GATE
2
------outline
3
4
5
6 ...
------- ----------------------0 IPT
#_of_fout
#_of_fin
inlines
1 BRCH
2 XOR(currently not implemented)
3 OR
4 NOR
5 NOT
6 NAND
7 AND
1 PI
2 FB
3 PO
outline
outline
outline
0
1 BRCH
2 - 7
#_of_fout
inline
0
0
#_of_fin
inlines
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
#include <stdlib.h>
#define MAXLINE 81
#define MAXNAME 31
e_com
e_state
e_ntype
e_gtype
struct cmdstruc {
char name[MAXNAME];
int (*fptr)();
enum e_state state;
};
/* command syntax */
/* function pointer of the commands */
/* execution state sequence */
/*
/*
/*
/*
/*
/*
/*
/*
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
output: nothing
called by: shell
description:
This is the main program of the simulator. It displays the prompt, reads
and parses the user command, and calls the corresponding routines.
Commands not reconized by the parser are passed along to the shell.
The command is executed according to some pre-determined sequence.
For example, we have to read in the circuit description file before any
action commands. The code uses "Gstate" to check the execution
sequence.
Pointers to functions are used to make function calls which makes the
code short and clean.
-----------------------------------------------------------------------*/
main()
{
enum e_com com;
char cline[MAXLINE], wstr[MAXLINE], *cp;
while(!Done) {
printf("\nCommand>");
fgets(cline, MAXLINE, stdin);
if(sscanf(cline, "%s", wstr) != 1) continue;
cp = wstr;
while(*cp){
*cp= Upcase(*cp);
cp++;
}
cp = cline + strlen(wstr);
com = READ;
while(com < NUMFUNCS && strcmp(wstr, command[com].name)) com++;
if(com < NUMFUNCS) {
if(command[com].state <= Gstate) (*command[com].fptr)(cp);
else printf("Execution out of sequence!\n");
}
else system(cline);
}
}
/*----------------------------------------------------------------------input: circuit description file name
output: nothing
called by: main
description:
This routine reads in the circuit description file and set up all the
required data structure. It first checks if the file exists, then it
sets up a mapping table, determines the number of nodes, PI's and PO's,
allocates dynamic data arrays, and fills in the structural information
of the circuit. In the ISCAS circuit description format, only upstream
nodes are specified. Downstream nodes are implied. However, to facilitate
forward implication, they are also built up in the data structure.
To have the maximal flexibility, three passes through the circuit file
are required: the first pass to determine the size of the mapping table
, the second to fill in the mapping table, and the third to actually
set up the circuit information. These procedures may be simplified in
-3-
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
the future.
-----------------------------------------------------------------------*/
cread(cp)
char *cp;
{
char buf[MAXLINE];
int ntbl, *tbl, i, j, k, nd, tp, fo, fi, ni = 0, no = 0;
FILE *fd;
NSTRUC *np;
sscanf(cp, "%s", buf);
if((fd = fopen(buf,"r")) == NULL) {
printf("File %s does not exist!\n", buf);
return;
}
if(Gstate >= CKTLD) clear();
Nnodes = Npi = Npo = ntbl = 0;
while(fgets(buf, MAXLINE, fd) != NULL) {
if(sscanf(buf,"%d %d", &tp, &nd) == 2) {
if(ntbl < nd) ntbl = nd;
Nnodes ++;
if(tp == PI) Npi++;
else if(tp == PO) Npo++;
}
}
tbl = (int *) malloc(++ntbl * sizeof(int));
fseek(fd, 0L, 0);
i = 0;
while(fgets(buf, MAXLINE, fd) != NULL) {
if(sscanf(buf,"%d %d", &tp, &nd) == 2) tbl[nd] = i++;
}
allocate();
fseek(fd, 0L, 0);
while(fscanf(fd, "%d %d", &tp, &nd) != EOF) {
np = &Node[tbl[nd]];
np->num = nd;
if(tp == PI) Pinput[ni++] = np;
else if(tp == PO) Poutput[no++] = np;
switch(tp) {
case PI:
case PO:
case GATE:
fscanf(fd, "%d %d %d", &np->type, &np->fout, &np->fin);
break;
case FB:
np->fout = np->fin = 1;
fscanf(fd, "%d", &np->type);
break;
default:
printf("Unknown node type!\n");
-4-
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
exit(-1);
}
np->unodes = (NSTRUC **) malloc(np->fin * sizeof(NSTRUC *));
np->dnodes = (NSTRUC **) malloc(np->fout * sizeof(NSTRUC *));
for(i = 0; i < np->fin; i++) {
fscanf(fd, "%d", &nd);
np->unodes[i] = &Node[tbl[nd]];
}
for(i = 0; i < np->fout; np->dnodes[i++] = NULL);
}
for(i = 0; i < Nnodes; i++) {
for(j = 0; j < Node[i].fin; j++) {
np = Node[i].unodes[j];
k = 0;
while(np->dnodes[k] != NULL) k++;
np->dnodes[k] = &Node[i];
}
}
fclose(fd);
Gstate = CKTLD;
printf("==> OK\n");
}
/*-----------------------input: level
output: nothing
called by: main
prints levels of all the nodes of the ckt
------------------------------*/
level(cp)
char *cp;
{
char buf[MAXLINE];
int i = 0,j, tp, max;
FILE *fd;
NSTRUC *np;
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
{
for (j = 0; j<np->fin; j++)
{
if(j == 0){
max = np->unodes[j]->level; }
else if((np->unodes[j]->level) > max)
{
max = np->unodes[j]->level;
}
}
np->level = max+1;
}
else if(tp == FB)
{
np->level = np->unodes[0]->level + 1;
}
i++;
}
}
}
/*----------------------------------------------------------------------input: nothing
output: nothing
called by: main
description:
The routine prints out the circuit description from previous READ command.
-----------------------------------------------------------------------*/
pc(cp)
char *cp;
{
int i, j;
NSTRUC *np;
char *gname();
printf(" Node
Type \tIn
\t\t\tOut
\t\t\tLevel\n");
printf("------ ------\t-------\t\t\t-------\t\t\t------\n");
for(i = 0; i<Nnodes; i++) {
np = &Node[i];
// printf(\"%d",np->level);
printf("\t\t\t\t\t");
// printf("%d",np->level);
-6-
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
-7-
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
/*======================================================================*/
/*----------------------------------------------------------------------input: nothing
output: nothing
called by: cread
description:
This routine clears the memory space occupied by the previous circuit
before reading in new one. It frees up the dynamic arrays Node.unodes,
Node.dnodes, Node.flist, Node, Pinput, Poutput, and Tap.
-----------------------------------------------------------------------*/
clear()
{
int i;
for(i = 0; i<Nnodes; i++) {
free(Node[i].unodes);
free(Node[i].dnodes);
}
free(Node);
free(Pinput);
free(Poutput);
Gstate = EXEC;
}
/*----------------------------------------------------------------------input: nothing
output: nothing
called by: cread
description:
This routine allocatess the memory space required by the circuit
description data structure. It allocates the dynamic arrays Node,
Node.flist, Node, Pinput, Poutput, and Tap. It also set the default
tap selection and the fanin and fanout to 0.
-----------------------------------------------------------------------*/
allocate()
{
int i;
Node = (NSTRUC *) malloc(Nnodes * sizeof(NSTRUC));
Pinput = (NSTRUC **) malloc(Npi * sizeof(NSTRUC *));
Poutput = (NSTRUC **) malloc(Npo * sizeof(NSTRUC *));
for(i = 0; i<Nnodes; i++) {
Node[i].indx = i;
Node[i].fin = Node[i].fout = 0;
}
}
/*----------------------------------------------------------------------input: gate type
output: string of the gate type
called by: pc
description:
The routine receive an integer gate type and return the gate type in
-8-
C:\Users\saurav\Desktop\EE658\HW3\readckt.c
character string.
-----------------------------------------------------------------------*/
char *gname(tp)
int tp;
{
switch(tp) {
case 0: return("PI");
case 1: return("BRANCH");
case 2: return("XOR");
case 3: return("OR");
case 4: return("NOR");
case 5: return("NOT");
case 6: return("NAND");
case 7: return("AND");
}
}
/*========================= End of program ============================*/
-9-