gnetlist
|
00001 /* mk_verilog_syms.c: 00002 * 00003 * Create a set of n-input gate symbols for the geda verilog netlister. 00004 * 00005 * symbols created: and[2-9], nand[2-9], nor[2-9], or[2-9], nor[2-9], 00006 * xor[2-9], xnor[2-9]. 00007 * 00008 * Copyright (C) 1999-2010 Mike Jarabek 00009 * 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 00023 * MA 02111-1301 USA. 00024 * 00025 */ 00026 00027 #ifdef HAVE_CONFIG_H 00028 #include "config.h" 00029 #endif 00030 00031 #include <stdio.h> 00032 #include <math.h> 00033 00034 #ifdef HAVE_LIBDMALLOC 00035 #include <dmalloc.h> 00036 #endif 00037 00038 /* local defines */ 00039 00040 /* gEDA colour, these should probably come from somewhere else */ 00041 #define BLACK 0 00042 #define WHITE 1 00043 #define RED 2 00044 #define GREEN 3 00045 #define BLUE 4 00046 #define YELLOW 5 00047 #define CYAN 6 00048 #define GREY 7 00049 00050 /* external prototypes */ 00051 int GetStringDisplayLength(char *str,int font_size); /* char_width.c */ 00052 00053 00054 00055 /* local prototypes */ 00056 int MakeSymbol(FILE *fp, unsigned int pins, int inputBubbles, 00057 int outputBubbles, 00058 int (*body)(FILE *, int, int, unsigned int, unsigned int)); 00059 00060 int AndBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour); 00061 int OrBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour); 00062 int XorBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour); 00063 int Pin(FILE *fp, int x1, int y1, int x2, int y2, int bubble); 00064 int PinAttribute(FILE *fp, int x, int y, unsigned int n, char *value); 00065 int WidenBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour); 00066 00067 /* globals */ 00068 unsigned int PinSpacing = 200; 00069 unsigned int PinLength = 300; 00070 00071 struct Table 00072 { 00073 char *name; /* base name of part */ 00074 unsigned int suffix; /* suffix for part, 1 for normal, 2 for deMorgan.. */ 00075 int (*body)(FILE *, int, int, unsigned int, unsigned int); /* body style */ 00076 int inputBubbles; /* where to draw bubbles */ 00077 int outputBubbles; 00078 }; 00079 00080 00081 struct Table generate[] = { 00082 {"and", 1, AndBody, 0, 0}, 00083 {"and", 2, OrBody, 1, 1}, 00084 {"nand", 1, AndBody, 0, 1}, 00085 {"nand", 2, OrBody, 1, 0}, 00086 {"or", 1, OrBody, 0, 0}, 00087 {"or", 2, AndBody, 1, 1}, 00088 {"nor", 1, OrBody, 0, 1}, 00089 {"nor", 2, AndBody, 1, 0}, 00090 {"xor", 1, XorBody, 0, 0}, 00091 {"xnor", 1, XorBody, 0, 1} 00092 }; 00093 00094 unsigned int nGenerate = sizeof(generate)/sizeof(struct Table); 00095 00096 int 00097 main(int argc, char **argv) 00098 { 00099 int i,j; 00100 int rc; 00101 char name[127]; 00102 00103 FILE *fp; 00104 00105 printf("Making verilog symbols\n"); 00106 00107 for(i=0; i<nGenerate; i++) /* loop over table entries */ 00108 for(j=2; j<10; j++) /* loop over number of pins */ 00109 { 00110 /* build file name */ 00111 sprintf(name, "sym/%s%u-%u.sym", 00112 generate[i].name, j, generate[i].suffix); 00113 printf("Working on:%s\n",name); 00114 fp = fopen(name, "wb"); 00115 if(fp == NULL) 00116 { 00117 fprintf(stderr,"Error: Unable to create file `%s' in %s()\n", 00118 name, __func__); 00119 return 1; 00120 } 00121 00122 rc = MakeSymbol(fp, j, 00123 generate[i].inputBubbles, generate[i].outputBubbles, 00124 generate[i].body); 00125 if(rc) 00126 { 00127 fprintf(stderr,"Error: Symbol creation failed in %s()\n", 00128 __func__); 00129 return 1; 00130 } 00131 00132 /* and finally add the device attribute */ 00133 fprintf(fp,"T 400 100 5 8 0 0 0 0\ndevice=%s\n",generate[i].name); 00134 /* and the positional pin directive */ 00135 fprintf(fp,"T 400 200 5 8 0 0 0 0\nVERILOG_PORTS=POSITIONAL"); 00136 fclose(fp); 00137 } 00138 00139 return 0; 00140 } 00141 00142 /* output a complete symbol having the desired body 00143 * and requested number of pins. Draw bubbles on the input and/or 00144 * output pins. 00145 */ 00146 int 00147 MakeSymbol(FILE *fp, unsigned int pins, int inputBubbles, int outputBubbles, 00148 int (*body)(FILE *, int, int, unsigned int, unsigned int)) 00149 { 00150 unsigned int i; 00151 int rc; 00152 00153 int bodyx, bodyy; /* origin of body */ 00154 int outputx, outputy; /* origin of output pin */ 00155 int firstx, firsty; /* first end of first input pin */ 00156 int totalHeight; 00157 00158 int pinx, piny; 00159 00160 int bodyWidth = 700; 00161 int bodyHeight = 600; 00162 unsigned int pinCount = 1; 00163 00164 char pinName[20]; /* temp for pinnname */ 00165 00166 if(fp == NULL) 00167 { 00168 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00169 __func__); 00170 return 1; 00171 } 00172 00173 if(body == NULL) 00174 { 00175 fprintf(stderr, "Error: NULL body drawing function pointer passed " 00176 "to %s()\n", 00177 __func__); 00178 return 1; 00179 } 00180 00181 /* do special pin spacing for 2 pins */ 00182 if(pins == 2) 00183 PinSpacing = 400; 00184 else 00185 PinSpacing = 200; 00186 00187 00188 /* first, compute locations needed */ 00189 totalHeight = bodyHeight; 00190 if(pins >= 3) /* do we need to add to the height ? */ 00191 totalHeight += (pins-3) * PinSpacing; 00192 00193 00194 bodyx = PinLength; 00195 bodyy = totalHeight/2; 00196 00197 outputx = bodyx+bodyWidth; 00198 outputy = bodyy; 00199 00200 firstx = PinLength; 00201 firsty = 100; 00202 00203 /* draw the body */ 00204 rc = (*body)(fp, bodyx, bodyy, pins, GREEN); 00205 if(rc) 00206 { 00207 fprintf(stderr, "Error: Body function failed in %s()\n", 00208 __func__); 00209 return 1; 00210 } 00211 00212 /* draw the pins and attach appropriate attributes */ 00213 rc = Pin(fp, outputx, outputy, outputx+PinLength, outputy, outputBubbles); 00214 if(rc) 00215 { 00216 fprintf(stderr, "Error: Pin drawing function failed in %s() " 00217 "for output pin\n", 00218 __func__); 00219 return 1; 00220 } 00221 /* attach pin attribute */ 00222 rc = PinAttribute(fp, outputx, outputy, pinCount++, "OUT"); 00223 if(rc) 00224 { 00225 fprintf(stderr, "Error: Pin Attribute function failed for output pin " 00226 "in %s()\n",__func__); 00227 return 1; 00228 } 00229 00230 /* do input pins */ 00231 for(i=0; i<pins; i++) 00232 { 00233 /* calculate the position of the pin */ 00234 pinx = firstx; 00235 piny = firsty+i*PinSpacing; 00236 /* output a pin */ 00237 rc = Pin(fp, pinx, piny, pinx-PinLength, piny, inputBubbles); 00238 if(rc) 00239 { 00240 fprintf(stderr,"Error: Pin drawing function failed for pin %u " 00241 "in %s()\n", 00242 i, __func__); 00243 return 1; 00244 } 00245 /* output the attributes */ 00246 sprintf(pinName,"IN%u",i); 00247 rc = PinAttribute(fp, pinx, piny, pinCount++, pinName); 00248 if(rc) 00249 { 00250 fprintf(stderr,"Error: Pin Attributes function failed for pin %u " 00251 "in %s()\n", i, __func__); 00252 return 1; 00253 } 00254 00255 } 00256 00257 00258 /* drop on a template uref attribute */ 00259 fprintf(fp,"T %d %d 5 10 1 1 0 2\nrefdes=U?\n", 00260 bodyx+100, 00261 bodyy-400); 00262 00263 00264 return 0; 00265 } 00266 00267 00268 00269 00270 /* produce an and shaped body at the given offset. 00271 * The origin is along the horizontal midline of the shape. 00272 */ 00273 int 00274 AndBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour) 00275 { 00276 00277 if(fp == NULL) 00278 { 00279 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00280 __func__); 00281 return 1; 00282 } 00283 00284 /* top and bottom lines */ 00285 fprintf(fp, "L %d %d %d %d %u\n", 00286 x, y+300, x+400, y+300, colour); 00287 fprintf(fp, "L %d %d %d %d %u\n", 00288 x, y-300, x+400, y-300, colour); 00289 00290 /* left line */ 00291 fprintf(fp, "L %d %d %d %d %u\n", 00292 x, y-300, x, y+300, colour); 00293 00294 /* arc at right */ 00295 fprintf(fp, "A %d %d %d %d %d %u\n", 00296 x+400, y, 300, -90, 180, colour); 00297 00298 return WidenBody(fp, x, y, pins, colour); 00299 } 00300 00301 /* produce a or shaped body at the given offset. 00302 * The origin is along the horizontal midline of the shape. 00303 */ 00304 int OrBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour) 00305 { 00306 if(fp == NULL) 00307 { 00308 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00309 __func__); 00310 return 1; 00311 } 00312 00313 /* top and bottom lines */ 00314 fprintf(fp, "L %d %d %d %d %u\n", 00315 x, y+300, x+300, y+300, colour); 00316 fprintf(fp, "L %d %d %d %d %u\n", 00317 x, y-300, x+300, y-300, colour); 00318 00319 /* left arc */ 00320 fprintf(fp, "A %d %d %d %d %d %u\n", 00321 x-260, y, 400, -48, 97, colour); 00322 00323 /* right top and bottom arcs */ 00324 fprintf(fp, "A %d %d %d %d %d %u\n", 00325 x+300, y+100, 400, 270, 76, colour); 00326 fprintf(fp, "A %d %d %d %d %d %u\n", 00327 x+300, y-100, 400, 90, -76, colour); 00328 00329 return WidenBody(fp, x, y, pins, colour); 00330 } 00331 00332 /* produce a xor shaped body at the given offset. 00333 * The origin is along the horizontal midline of the shape. 00334 */ 00335 int XorBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour) 00336 { 00337 if(fp == NULL) 00338 { 00339 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00340 __func__); 00341 return 1; 00342 } 00343 00344 /* top and bottom lines */ 00345 fprintf(fp, "L %d %d %d %d %u\n", 00346 x+100, y+300, x+300, y+300, colour); 00347 fprintf(fp, "L %d %d %d %d %u\n", 00348 x+100, y-300, x+300, y-300, colour); 00349 00350 /* left arc 1 */ 00351 fprintf(fp, "A %d %d %d %d %d %u\n", 00352 x-260, y, 400, -48, 97, colour); 00353 /* left arc 2 */ 00354 fprintf(fp, "A %d %d %d %d %d %u\n", 00355 x-160, y, 400, -48, 97, colour); 00356 00357 00358 /* right top and bottom arcs */ 00359 fprintf(fp, "A %d %d %d %d %d %u\n", 00360 x+300, y+100, 400, 270, 76, colour); 00361 fprintf(fp, "A %d %d %d %d %d %u\n", 00362 x+300, y-100, 400, 90, -76, colour); 00363 00364 return WidenBody(fp, x, y, pins, colour); 00365 } 00366 00367 00368 /* output two line segments that will serve to `widen' the 00369 * body of one of the above gates 00370 */ 00371 int 00372 WidenBody(FILE *fp, int x, int y, unsigned int pins, unsigned int colour) 00373 { 00374 unsigned int distanceNeeded; 00375 00376 if(fp == NULL) 00377 { 00378 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00379 __func__); 00380 return 1; 00381 } 00382 00383 /* only need to do work if the number of pins > 2 */ 00384 if(pins <= 3) 00385 return 0; 00386 00387 00388 /* Compute the amount needed to add to both top and bottom */ 00389 distanceNeeded = (pins-3) * PinSpacing/2; 00390 00391 /* output the line segments */ 00392 /* for the top */ 00393 fprintf(fp, "L %d %d %d %d %u\n", 00394 x, y+300, x, y+300+distanceNeeded, colour); 00395 /* for the bottom */ 00396 fprintf(fp, "L %d %d %d %d %u\n", 00397 x, y-300, x, y-300-distanceNeeded, colour); 00398 00399 return 0; 00400 } 00401 00402 00403 /* Draw a pin, optionally with a bubble 00404 */ 00405 int 00406 Pin(FILE *fp, int x1, int y1, int x2, int y2, int bubble) 00407 { 00408 int bx, by; /* bubble x and y locations */ 00409 int px1, py1, px2, py2; /* pin x and y locations */ 00410 int dx, dy; 00411 int br = 50; /* bubble radius */ 00412 00413 double x,y; /* unit vector in direction of line */ 00414 double denom; 00415 00416 if(fp == NULL) 00417 { 00418 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00419 __func__); 00420 return 1; 00421 } 00422 00423 /* figure where pin ends are */ 00424 if(bubble) /* is there a bubble? */ 00425 { /* yes there is a bubble */ 00426 00427 /* compute a unit vector */ 00428 dx = x2-x1; 00429 dy = y2-y1; 00430 denom = sqrt( dx*dx + dy*dy); 00431 if(denom < 1e-6) 00432 { 00433 fprintf(stderr, "Error: Length of pin too small in %s()\n", 00434 __func__); 00435 return 1; 00436 } 00437 00438 x = dx / denom; 00439 y = dy / denom; 00440 00441 /* figure center of bubble */ 00442 bx = x1 + x * br; 00443 by = y1 + y * br; 00444 00445 /* figure location of first line end */ 00446 px1 = x1 + x * 2 * br; 00447 py1 = y1 + y * 2 * br; 00448 00449 px2 = x2; 00450 py2 = y2; 00451 00452 00453 /* draw the bubble */ 00454 fprintf(fp, "V %d %d %d %d\n", 00455 (int) bx, (int) by, br, CYAN); 00456 00457 } 00458 else 00459 { /* no bubble, nothing special to do */ 00460 00461 px1 = x1; py1 = y1; 00462 px2 = x2; py2 = y2; 00463 00464 } 00465 00466 /* draw the pin */ 00467 fprintf(fp, "P %d %d %d %d %d\n", 00468 px1, py1, px2, py2, WHITE); 00469 00470 return 0; 00471 } 00472 00473 int 00474 PinAttribute(FILE *fp, int x, int y, unsigned int n, char *value) 00475 { 00476 if(fp == NULL) 00477 { 00478 fprintf(stderr, "Error: NULL file pointer passed to %s()\n", 00479 __func__); 00480 return 1; 00481 } 00482 00483 if(value == NULL) 00484 { 00485 fprintf(stderr, "Error: NULL value pointer passed to %s()\n", 00486 __func__); 00487 return 1; 00488 } 00489 00490 fprintf(fp, "{\n"); 00491 fprintf(fp, "T %d %d %u %u 0 0 0 0\n",x, y, YELLOW, 8); 00492 fprintf(fp, "pin%u=%s\n",n, value); 00493 fprintf(fp, "}\n"); 00494 00495 return 0; 00496 }