/* cif2ps is based on the program 'cifp' originally written by Arthur Simoneau, The Aerospace Corporation, El Segundo, Calif Modified by Marc Lesure, Arizona State University, Tempe, AZ Changes to 'cifp' include support of cmos-pw layers, scaling factors to spread output over several pages of 8.5 x 11 paper, printing multiple layers. Modified by Gordon W Ross, The MITRE Corporation, Bedford, MA Designed new PostScript routines to reduce output file size. Added automatic style selection and run-time customization. Added rotation option. (June 1989) Please honor the authors by not removing their attributions. */ #include #ifdef sun extern char *sprintf(); /* missing from stdio.h on Sun! */ #endif #include #include "define.h" int maxwidth = 5; int maxlength = 5; int depth_lim, depth_now; main(argc, argv) int argc; char *argv[]; { char *s,*cifname,*plotname,*sym_name; /* Initialize */ ciffile=stdin; cifname="(stdin)"; sym_name=0; /* default (see below) */ depth_lim=0; length = width = 1; totpages = 0; font_points = DEFPOINTS; no_lines = 0; layer = 0; last_symbol = -1; identity_matrix(top_matrix); /* need for "-r" option */ while (--argc && ++argv && **argv == '-') { s = argv[0] + 1; switch (*s) { case 'c': sym_name = *++argv; argc--; break; case 'd': depth_lim = atoi(*++argv); argc--; break; case 'f': font_points = atoi(*++argv); argc--; break; case 'h': length = atoi(*++argv); argc--; break; case 'w': width = atoi(*++argv); argc--; break; case 'r': /* rotate by 90 degrees */ { float rotate[3][3]; identity_matrix(rotate); rotate[0][0] = 0; rotate[0][1] = -1; rotate[1][0] = 1; rotate[1][1] = 0; hit_matrix(rotate, top_matrix, top_matrix); } break; case 's': set_style(*++argv); argc--; break; default: printf("cif2ps: unknown flag - %s\n",*s); exit(0); } } if (argc) { /* input file name supplied? */ cifname = *argv++; argc--; if (!freopen(cifname, "r", stdin)) { fprintf(stderr, "%s: can't read\n", cifname); exit(1); } } if (argc) { /* output file name supplied? */ plotname = *argv++; argc--; if (!freopen(plotname, "w", stdout)) { fprintf(stderr, "%s: can't write\n", plotname); exit(1); } } if (argc) { /* extra args must be errors */ fprintf(stderr, "Usage: cif2ps [-w width] [-h height] [input [output]]\n"); exit(0); } if (width <= 0) { printf("-w exceeds lower limit - setting to 1\n"); width = 1; } if (length <= 0) { printf("-l exceeds lower limit - setting to 1\n"); length = 1; } if (width > maxwidth) { printf("-w exceeds upper limit - setting to %d\n",maxwidth); width = maxwidth; } if (length > maxlength) { printf("-l exceeds upper limit - setting to %d\n",maxlength); length = maxlength; } copy_matrix(top_matrix, matrix); ds("DS 0", DSTYPE); /* cell 0 is predefined. Yech! -GWR */ nine("9 top_level"); do_cif(); /* parse input */ style_sort(); /* determine plot order for layers */ plot_symbol(sym_name); } /*main*/ plot_symbol(sym_name) char *sym_name; { pointpairtype ll, ur; int sym_index = 0; /* get the symbol number */ if (sym_name) { if (isdigit(*sym_name)) { sym_index = get_index(atoi(sym_name)); } else { sym_index = sym_lookup(sym_name); } if (sym_index < 0) { fprintf(stderr, "%s: symbol not found\n", sym_name); output_all_symbolnums(stderr); exit(1); } } else { /* use default choice of symbol */ /* usually want "1" if it exists, else "0" */ sym_index = get_index(1); if (sym_index < 0) sym_index = 0; } ll.x = BIGINT; ur.x = -BIGINT; ll.y = BIGINT; ur.y = -BIGINT; get_bounds(sym_index, &ll, &ur); if ((ll.x == BIGINT) || (ll.y == BIGINT)) { fprintf(stderr, "cell number %s is empty\n", sym_name); exit(1); } get_pair(ll.x, ll.y, &ll); get_pair(ur.x, ur.y, &ur); fix_bbox(&ll, &ur); /* transformed? */ get_window(&ll, &ur); init_cif(); putHeader(); for(pagey=0; pagey < length; pagey++) { for(pagex=0; pagex < width; pagex++) { startPage(); plot_boxes(symbol_table[sym_index].pointer); plot_textes(symbol_table[sym_index].pointer); finishPage(); } } putTrailer(); } /*plotcif*/ int sym_lookup(sym_name) /* return symbol table index */ char *sym_name; { int i; for(i = 0; i <= last_symbol; i++) { if (symbol_table[i].name && !strcmp(symbol_table[i].name, sym_name)) return(i); } return(-1); } get_window(ll, ur) pointpairtype *ll, *ur; { /* assigns global variables: scale, trans_x, trans_y */ /* Note: scale maps from CIF coordinates to 72'nds of inches */ float scalex, scaley; float deltax, deltay; int newsize; trans_x = - ll->x; trans_y = - ll->y; deltax = ur->x - ll->x; scalex = width * PAGEWIDTH / deltax; deltay = ur->y - ll->y; scaley = length * PAGELENGTH / deltay; if (scalex < scaley) { scale = scalex; newsize = ((deltay * scale) / PAGELENGTH) + 1; if (newsize != length) { printf("output length changed from %d to %d\n", length, newsize); length = newsize; } } else { scale = scaley; newsize = ((deltax * scale) / PAGEWIDTH) + 1; if (newsize != width) { printf("output width changed from %d to %d\n", newsize,length); width = newsize; } } } /*get_window*/ plot_boxes(symbol) symboltype *symbol; { int i; /* first we plot all the opaque (gray fill) styles */ for (i=0; ityper) { case BOXTYPE: plot_box(symbol->primitive.box); break; case NGONTYPE: plot_ngon(symbol->primitive.ngon); break; case ROUNDTYPE: plot_round(symbol->primitive.round); break; case WIRETYPE: plot_wire(symbol->primitive.wire); break; case CALLTYPE: /* if at depth_lim, skip calls */ if (depth_lim && (depth_lim <= (depth_now + 1))) break; depth_now++; copy_matrix(matrix, temp_matrix); hit_matrix(matrix, symbol->primitive.call->matrix, matrix); plot_boxes_sub( symbol_table[symbol->primitive.call->symbol].pointer); copy_matrix(temp_matrix, matrix); depth_now--; break; case DSTYPE: case NINETY_FOURTYPE: break; default: fprintf(stderr, "ERROR Not known %d in plot boxes\n", symbol->typer); break; } symbol = symbol->next; } return; } /*plot_boxes_sub*/ plot_textes(symbol) symboltype *symbol; { ninety_fourtype *ninety_four; puts("0 setgray"); while(symbol != NULL) { switch(symbol->typer) { case CALLTYPE: /* only plots text in top level */ case DSTYPE: case BOXTYPE: case NGONTYPE: case ROUNDTYPE: case WIRETYPE: break; case NINETY_FOURTYPE: ninety_four = symbol->primitive.ninety_four; plot_text(ninety_four); break; default: fprintf(stderr, "ERROR unknown %d in plot_textes\n", symbol->typer); break; } symbol = symbol->next; } } /*plot_textes*/ bound_point(ll,ur,x,y) pointpairtype *ll, *ur; int x,y; { if (ll->x > x) ll->x = x; if (ll->y > y) ll->y = y; if (ur->x < x) ur->x = x; if (ur->y < y) ur->y = y; } bound_box(ll,ur,box) pointpairtype *ll, *ur; boxtype *box; { bound_point(ll,ur,box->llx,box->lly); bound_point(ll,ur,box->urx,box->ury); } bound_ngon(ll,ur,ngon) pointpairtype *ll, *ur; ngontype *ngon; { int n = ngon->numPoints; int *a = ngon->ptrPoints; do { bound_point(ll,ur,a[0],a[1]); n--; a += 2; } while (n); } bound_round(ll,ur,round) pointpairtype *ll, *ur; roundtype *round; { bound_point(ll,ur, round->x - round->r, round->y - round->r); bound_point(ll,ur, round->x + round->r, round->y + round->r); } bound_wire(ll,ur,wire) pointpairtype *ll, *ur; wiretype *wire; { int n = wire->numPoints; int *a = wire->ptrPoints; do { bound_point(ll,ur,a[0],a[1]); n--; a += 2; } while (n); ll->x -= wire->width; ll->y -= wire->width; ur->x += wire->width; ur->y += wire->width; } get_bounds(sym, ll, ur) int sym; pointpairtype *ll, *ur; { int local_sym; symboltype *symbol; pointpairtype local_ll, local_ur; float temp_matrix[3][3]; symbol = symbol_table[sym].pointer; while(symbol != NULL) { switch(symbol->typer) { case DSTYPE: case NINETY_FOURTYPE: break; case BOXTYPE: bound_box(ll,ur,symbol->primitive.box); break; case NGONTYPE: bound_ngon(ll,ur,symbol->primitive.ngon); break; case ROUNDTYPE: bound_round(ll,ur,symbol->primitive.round); break; case WIRETYPE: bound_wire(ll,ur,symbol->primitive.wire); break; case CALLTYPE: local_sym = symbol->primitive.call->symbol; if (symbol_table[local_sym].ll.x == BIGINT) { get_bounds(local_sym, &(symbol_table[local_sym].ll), &(symbol_table[local_sym].ur)); } copy_matrix(matrix, temp_matrix); copy_matrix(symbol->primitive.call->matrix, matrix); get_pair(symbol_table[local_sym].ll.x, symbol_table[local_sym].ll.y, &local_ll); get_pair(symbol_table[local_sym].ur.x, symbol_table[local_sym].ur.y, &local_ur); copy_matrix(temp_matrix, matrix); /* local_ll and local_ur may be transformed * such that left>right or lower>upper ... */ fix_bbox(&local_ll, &local_ur); if (ll->x > local_ll.x) ll->x = local_ll.x; if (ll->y > local_ll.y) ll->y = local_ll.y; if (ur->x < local_ur.x) ur->x = local_ur.x; if (ur->y < local_ur.y) ur->y = local_ur.y; break; default: fprintf(stderr, "ERROR Not known %d in get_bounds\n", symbol->typer); break; } symbol = symbol->next; } } /*get_bounds*/ get_pair(x, y, pair) int x, y; pointpairtype *pair; { pair->x = (x * matrix[0][0]) + (y * matrix[0][1]) + matrix[0][2]; pair->y = (x * matrix[1][0]) + (y * matrix[1][1]) + matrix[1][2]; } /*get_pair*/ call_symbol(cif) char *cif; { int last_read, callnum; char token[MAXTOKEN]; char ciftemp[MAXLINE]; int rotate_x, rotate_y; float multi_matrix[3][3]; float temp_a_over_b, translate_x, translate_y; calltype *call, *alloccall(); bang_symbol(); present_symbol->typer = CALLTYPE; call = alloccall(); present_symbol->primitive.call = call; last_read = get_token(cif, 2, token); if (last_read == -1) { fprintf(stderr, "no symbol in CALL\n"); cif_output(stderr, cif); return; } (void) sscanf(token, "%d", &callnum); call->symbol = get_index(callnum); if (call->symbol == -1) { sprintf(ciftemp, "DS %d", callnum); temp_a_over_b = a_over_b; ds(ciftemp, CALLTYPE); a_over_b = temp_a_over_b; call->symbol = get_index(callnum); if (call->symbol == -1) { fprintf(stderr, "Error in call cif\n"); cif_output(stderr, cif); } } identity_matrix(multi_matrix); while(1) { last_read = get_token(cif, last_read, token); if (last_read == -1) break; if (token[0] == 'M') { switch(token[1]) { case 'X': multi_matrix[0][0] = -1; hit_matrix(multi_matrix, call->matrix, call->matrix); multi_matrix[0][0] = 1; break; case 'Y': multi_matrix[1][1] = -1; hit_matrix(multi_matrix, call->matrix, call->matrix); multi_matrix[1][1] = 1; break; default: fprintf(stderr, "Error in mirror %c\n", token[1]); cif_output(stderr, cif); break; } /*switch mirror*/ } /*if mirror*/ else if (token[0] == 'R') { last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "error in rotate\n"); cif_output(stderr, cif); break; } (void) sscanf(token, "%d", &rotate_x); rotate_x = sign(rotate_x); last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "error2 in rotate\n"); cif_output(stderr, cif); break; } (void) sscanf(token, "%d", &rotate_y); rotate_y = sign(rotate_y); switch(rotate_x) { case 1: if (rotate_y != 0) fprintf(stderr, "Bad rotation x %d y %d\n", rotate_x, rotate_y); break; case -1: if (rotate_y != 0) { fprintf(stderr, "Bad rotation x %d y %d\n", rotate_x, rotate_y); break; } multi_matrix[0][0] = -1; multi_matrix[1][1] = -1; hit_matrix(multi_matrix, call->matrix, call->matrix); identity_matrix(multi_matrix); break; case 0: switch(rotate_y) { case 1: multi_matrix[0][0] = 0; multi_matrix[1][1] = 0; multi_matrix[0][1] = -1; multi_matrix[1][0] = 1; hit_matrix(multi_matrix, call->matrix, call->matrix); identity_matrix(multi_matrix); break; case -1: multi_matrix[0][0] = 0; multi_matrix[1][1] = 0; multi_matrix[0][1] = 1; multi_matrix[1][0] = -1; hit_matrix(multi_matrix, call->matrix, call->matrix); identity_matrix(multi_matrix); break; default: fprintf(stderr, "Bad rotation x %d y %d\n", rotate_x, rotate_y); break; } /*switch y*/ break; default: fprintf(stderr, "Bad rotation x %d y %d\n", rotate_x, rotate_y); break; } /*switch rotation*/ } /*if rotate*/ else if (token[0] == 'T') { last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "error in translate\n"); cif_output(stderr, cif); break; } (void) sscanf(token, "%f", &translate_x); translate_x *= a_over_b; last_read = get_token(cif, last_read, token); if (last_read == -1) { fprintf(stderr, "error2 in translate\n"); cif_output(stderr, cif); break; } (void) sscanf(token, "%f", &translate_y); translate_y *= a_over_b; if ((translate_x != 0) || (translate_y != 0)) { multi_matrix[0][2] = translate_x; multi_matrix[1][2] = translate_y; hit_matrix(multi_matrix, call->matrix, call->matrix); identity_matrix(multi_matrix); } } /*if translate*/ else { fprintf(stderr, "error---out of calls\n"); cif_output(stderr, cif); fprintf(stderr, "\ttoken %s\n", token); break; } } /* while(1) */ } /*call_symbol*/ sign(x) int x; { int z; z = 0; if (x > 0) z = 1; if (x < 0) z = -1; return(z); } identity_matrix(matrix) float matrix[3][3]; { matrix[0][0] = 1; matrix[0][1] = 0; matrix[0][2] = 0; matrix[1][0] = 0; matrix[1][1] = 1; matrix[1][2] = 0; matrix[2][0] = 0; matrix[2][1] = 0; matrix[2][2] = 1; } /*identity_matrix*/ hit_matrix(left_matrix, right_matrix, to_matrix) float left_matrix[3][3], right_matrix[3][3], to_matrix[3][3]; { int i, j; float temp[3][3]; for(i = 0; i < 3; i++) for(j = 0; j < 3; j++) temp[i][j] = left_matrix[i][0] * right_matrix[0][j] + left_matrix[i][1] * right_matrix[1][j] + left_matrix[i][2] * right_matrix[2][j]; copy_matrix(temp, to_matrix); } /*hit_matrix*/ copy_matrix(from_matrix, to_matrix) float from_matrix[3][3], to_matrix[3][3]; { int i, j; for(i = 0; i < 3; i++) { for(j = 0; j < 3; j++) to_matrix[i][j] = from_matrix[i][j]; } } /*copy_matrix*/ fix_bbox(ll, ur) pointpairtype *ll, *ur; { float temp; if (ll->x > ur->x) { /* swap */ temp = ll->x; ll->x = ur->x; ur->x = temp; } if (ll->y > ur->y) { /* swap */ temp = ll->y; ll->y = ur->y; ur->y = temp; } }