// CleanUpBdnet // // Revision 0, version 1 2006-11-11: First release by Steve Beccue // Revision 1, version 1.1 2008-07-09: Modifications by Tim Edwards // Revision 2, version 1.2 2009-07-13: Minor cleanups by Philipp Klaus Krause. // // This program is written in ISO C99. #include #include #include #include #include #include #include #define EXIT_SUCCESS 0 #define EXIT_FAILURE 1 #define EXIT_HELP 2 #define TRUE 1 #define FALSE 0 #define NMOS 1 #define PMOS 0 #define LengthOfNodeName 100 #define LengthOfLine 200 #define LengthOfInOutString 10000 #define NumberOfUniqueConnections 6 #define VERSIONSTRING "1.2" #define VERSIONDATE "2009-07-13" typedef struct _node *nodeptr; typedef struct _node { char *pair[2]; nodeptr next; } node; nodeptr InputNodes = NULL; nodeptr OutputNodes = NULL; /* getopt stuff */ extern int optind, getopt(); extern char *optarg; struct Vect { struct Vect *next; char name[LengthOfLine]; char direction[LengthOfNodeName]; int Max; }; void ReadNetlistAndConvert(FILE *, FILE *, int); void CleanupString(char text[]); void ToLowerCase( char *text); float getnumber(char *strpntbegin); int getlineloc( char s[], int lim, FILE *fp); void helpmessage(); int ParseNumber( char *test); struct Vect *VectorAlloc(void); int BussesLeftAlone = FALSE; int main(int argc, char *argv[]) { FILE *NET1, *NET2, *OUT; struct Resistor *ResistorData; int i, AllMatched, NetsEqual, CleanUpInternal; char Net1name[LengthOfNodeName]; CleanUpInternal = FALSE; while ((i = getopt(argc, argv, "bvfhH")) != EOF ) { switch (i) { case 'v': fprintf(stderr, "Version %s date:%s\n", VERSIONSTRING, VERSIONDATE); exit(0); break; case 'f': CleanUpInternal = TRUE; break; case 'b': BussesLeftAlone = TRUE; break; case 'h': case 'H': helpmessage(); break; default: fprintf(stderr, "\nbad switch %d\n", i ); helpmessage(); break; } } if (optind < argc) { strcpy(Net1name, argv[optind]); optind++; } else { fprintf(stderr, "Couldn't find a filename as input\n"); exit(EXIT_FAILURE); } optind++; NET1 = fopen(Net1name, "r"); if (NET1 == NULL) { fprintf(stderr, "Couldn't open %s for read\n", Net1name); exit(EXIT_FAILURE); } OUT = stdout; ReadNetlistAndConvert(NET1, OUT, CleanUpInternal); return 0; } /* main() */ /*--------------------------------------------------------------*/ /* C ReadNetlistAndConvert */ /* */ /* ARGS: */ /* RETURNS: 1 to OS */ /* SIDE EFFECTS: */ /*--------------------------------------------------------------*/ void ReadNetlistAndConvert(FILE *NETFILE, FILE *OUT, int CleanUpInternal) { struct Vect *Vector, *VectorPresent; nodeptr newnode; int i, Found, NumberOfInstances; int First, VectorIndex, ItIsAnInput, ItIsAnOutput, Done, DoneIO; int EndOfInput, EndOfOutput, termPending; float length, width, Value; char *node2pnt,*lengthpnt,*widthpnt,*FirstblankafterNode2, *Weirdpnt; char *charpnt; char line[LengthOfLine]; char allinputs[LengthOfInOutString]; char alloutputs[LengthOfInOutString]; char InputName[LengthOfNodeName], InputEquivalent[LengthOfNodeName]; char OutputName[LengthOfNodeName], OutputEquivalent[LengthOfNodeName]; char MainSubcktName[LengthOfNodeName], node1[LengthOfNodeName]; char InstanceName[LengthOfNodeName], InstancePortName[LengthOfNodeName]; char InstancePortWire[LengthOfNodeName]; char node2[LengthOfNodeName], nodelabel[LengthOfNodeName]; char body[LengthOfNodeName], model[LengthOfNodeName]; char temp[LengthOfNodeName]; /* Read in line by line */ NumberOfInstances = 0; First = TRUE; Vector = VectorAlloc(); Vector->next = NULL; Done = FALSE; while ((getlineloc(line, sizeof(line), NETFILE) > 0) && (!Done)) { if (strstr(line, "MODEL") != NULL ) { fprintf(OUT, "%s", line); } if (strstr(line, "TECHNOLOGY") != NULL ) { fprintf(OUT, "%s", line); } if (strstr(line, "VIEWTYPE") != NULL ) { fprintf(OUT, "%s", line); } if (strstr(line, "EDITSTYLE") != NULL ) { fprintf(OUT, "%s", line); } if (strstr(line, "INPUT") != NULL ) { fprintf(OUT, "%s", line); EndOfInput = FALSE; termPending = FALSE; while ((getlineloc(line, sizeof(line), NETFILE) > 1) && (strstr(line,"OUTPUT") == NULL)) { if (sscanf(line,"%s : %s", &InputName, &InputEquivalent) == 2) { /* Ignore lines like "[0]" : "[0]"; which get */ /* generated by sis for no good reason that I can */ /* see, appeart be superfluous, and only cause */ /* trouble. */ if (InputName[0] == '\"' && InputName[1] == '[') { if (strchr(InputEquivalent,';') != NULL) fprintf(OUT,";\n\n"); continue; } if (termPending) { fprintf(OUT,"\n"); termPending = FALSE; } CleanupString(InputName); if (strchr(InputEquivalent,';') != NULL) EndOfInput = TRUE; CleanupString(InputEquivalent); newnode = (nodeptr)malloc(sizeof(node)); newnode->pair[0] = strdup(InputName); newnode->pair[1] = strdup(InputEquivalent); newnode->next = InputNodes; InputNodes = newnode; fprintf(OUT, "\t%s\t:\t%s", InputName, InputEquivalent); if (EndOfInput) fprintf(OUT, ";\n\n"); else termPending = TRUE; } } } if (strstr(line,"OUTPUT") != NULL ) { fprintf(OUT, "%s", line); EndOfOutput = FALSE; while ((getlineloc(line, sizeof(line), NETFILE) > 1) && (strstr(line,"INSTANCE") == NULL)) { if (sscanf(line, "%s : %s", &OutputName, &OutputEquivalent) == 2) { CleanupString(OutputName); if (strchr(OutputEquivalent,';') != NULL) EndOfOutput = TRUE; CleanupString(OutputEquivalent); newnode = (nodeptr)malloc(sizeof(node)); newnode->pair[0] = strdup(OutputName); newnode->pair[1] = strdup(OutputEquivalent); newnode->next = OutputNodes; OutputNodes = newnode; fprintf(OUT, "\t%s\t:\t%s", OutputName, OutputEquivalent); if (EndOfOutput) fprintf(OUT, ";\n\n"); else fprintf(OUT, "\n"); } } } if (strstr(line,"INSTANCE") != NULL ) { fprintf(OUT, "%s", line); NumberOfInstances++; while ((getlineloc(line, sizeof(line), NETFILE) > 0) && (strstr(line,"ENDMODEL") == NULL)) { if (sscanf(line,"%s : %s;", &InstancePortName, &InstancePortWire) == 2) { ItIsAnInput = FALSE; ItIsAnOutput = FALSE; strcpy(temp, InstancePortWire); CleanupString(temp); DoneIO = FALSE; if ((charpnt=strchr(temp,';')) != NULL) *charpnt='\0'; for (newnode = InputNodes; newnode != NULL && !DoneIO; newnode = newnode->next) { if (strcmp(temp, newnode->pair[1]) == 0) { DoneIO = TRUE; ItIsAnInput = TRUE; fprintf(OUT, "\t%s\t:\t%s;\n", InstancePortName, newnode->pair[1]); } } Done = FALSE; for (newnode = OutputNodes; newnode != NULL && !DoneIO; newnode = newnode->next) { if (strcmp(temp, newnode->pair[1]) == 0) { DoneIO = TRUE; ItIsAnOutput = TRUE; fprintf(OUT, "\t%s\t:\t%s;\n", InstancePortName, newnode->pair[1]); } } if (!ItIsAnInput && !ItIsAnOutput) { if (CleanUpInternal) { charpnt = strrchr(InstancePortWire,'"'); if (charpnt != NULL) { // This assumes the end looks like ..."; if (*(charpnt-1) == '0') { *(charpnt-1) = '"'; *(charpnt) = ';'; *(charpnt+1) = '\0'; } } charpnt = strrchr(InstancePortWire, '<'); if (charpnt != NULL && !BussesLeftAlone) *(charpnt) = '_'; charpnt = strrchr(InstancePortWire, '>'); if (charpnt != NULL) if (!BussesLeftAlone ) *(charpnt) = '_'; } fprintf(OUT, "\t%s\t:\t%s\n", InstancePortName, InstancePortWire); } } else fprintf(OUT, "%s", line); } Done = TRUE; fprintf(OUT, "ENDMODEL;\n"); } } } /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ int ParseNumber(char *text) { char *begin, *end; // Assumes *text is a '[' begin = (text+1); end = strchr(begin,']'); *end = '\0'; *text = '\0'; return atoi(begin); } /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ void ToLowerCase(char *text) { int i = 0; while (text[i] != '\0') { text[i] = tolower(text[i]); i++; } } /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ void CleanupString(char text[LengthOfNodeName]) { char *CitationPnt, *Weirdpnt; CitationPnt = strrchr(text, '"'); if (CitationPnt != NULL) { if (*(CitationPnt-1) == '0') { *(CitationPnt - 1) = '"'; *(CitationPnt) = '\0'; } else if (*(CitationPnt+1) == ';') *(CitationPnt+1) = '\0'; /* Handle buffered inputs */ if ((strlen(text) > 5) && !strcmp(CitationPnt - 5, "0_ext")) { sprintf(CitationPnt - 5, "_ext"); } } Weirdpnt = strchr(text, '<'); if (Weirdpnt != NULL && !BussesLeftAlone) *Weirdpnt='_'; Weirdpnt = strchr(text, '>'); if (Weirdpnt != NULL && !BussesLeftAlone) *Weirdpnt='_'; } /*--------------------------------------------------------------*/ /* C getnumber - gets number pointed by strpntbegin */ /* */ /* ARGS: strpntbegin - number expected after '=' */ /* RETURNS: 1 to OS */ /* SIDE EFFECTS: */ /*--------------------------------------------------------------*/ float getnumber(char *strpntbegin) { int i; char *strpnt, magn1, magn2; float number; strpnt = strpntbegin; strpnt = strchr(strpntbegin, '='); if (strpnt == NULL) { fprintf(stderr,"Error: getnumber: Didn't find '=' in string %s\n", strpntbegin); return DBL_MAX; } strpnt++; if (sscanf(strpnt, "%f%c%c", &number, &magn1, &magn2) !=3) { if (sscanf(strpnt, "%f%c", &number, &magn1) !=2) { fprintf (stderr,"Error: getnumber : Couldn't read number in %s %s\n", strpntbegin, strpnt); return DBL_MAX; } } /* if (*strpntbegin == 'm') */ switch (magn1) { case 'f': number *= 1e-15; break; case 'p': number *= 1e-12; break; case 'n': number *= 1e-9; break; case 'u': number *= 1e-6; break; case 'm': if(magn2='e') number *= 1e6; else number *= 1e-3; break; case 'k': number *= 1e3; break; case 'g': number *= 1e9; break; case ' ': default: return number; } return number; } /*--------------------------------------------------------------*/ /*C getlineloc: read a line, return length */ /* */ /* ARGS: */ /* RETURNS: 1 to OS */ /* SIDE EFFECTS: */ /*--------------------------------------------------------------*/ int getlineloc( char s[], int lim, FILE *fp) { int c, i; i = 0; while (--lim > 0 && (c = getc(fp)) != EOF && c != '\n') s[i++] = c; if (c == '\n'); s[i++] = c; s[i] = '\0'; if (c == EOF) i = 0; return i; } /*--------------------------------------------------------------*/ /*--------------------------------------------------------------*/ struct Vect *VectorAlloc(void) { return (struct Vect *)malloc(sizeof(struct Vect)); } /*--------------------------------------------------------------*/ /* C helpmessage - tell user how to use the program */ /* */ /* ARGS: */ /* RETURNS: 1 to OS */ /* SIDE EFFECTS: */ /*--------------------------------------------------------------*/ void helpmessage() { fprintf(stderr, "CleanUpBdnet [-options] netlist \n"); fprintf(stderr, "\n"); fprintf(stderr, "CleanUpBdnet removes superfluous 0's and replaces" " <> with _ in the bdnet netlist\n"); fprintf(stderr, "\n"); fprintf(stderr, "option, -b leave busses alone. (busses stay busses.)\n"); fprintf(stderr, "option, -f also cleans up internal nets\n"); fprintf(stderr, "option, -h this message\n"); exit( EXIT_HELP ); } /* helpmessage() */