FreeCalypso > hg > ueda-linux
view ueda/uschem-utils/check.c @ 142:7bdce91da1a5
unet-excise utility added
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 19 Sep 2020 22:50:24 +0000 |
parents | cd92449fdb51 |
children |
line wrap: on
line source
/* * This program (uschem-check) reads a uschem schematic into core, exercising * libuschem reading code. * It then performs the most basic DRC, or more specifically, the check is * focused on matching the graphical info with the netlist info - no attempt * is made to guess the sensibility of the actual electrical circuit. */ #include <sys/types.h> #include <stdio.h> #include <strings.h> #include "../libuschem/schemstruct.h" #include "../libuschem/graphsym.h" extern int optind; extern char *optarg; extern char *MCLfile; extern struct schem *read_schem(); struct schem *schem; int domcl, dosymbols, checkhash, donets; main(argc, argv) char **argv; { register int c; char **avp; while ((c = getopt(argc, argv, "hI:mM:s")) != EOF) switch (c) { case 'h': checkhash++; break; case 'I': add_symfile_dir(optarg); break; case 'm': domcl++; break; case 'M': MCLfile = optarg; break; case 's': dosymbols++; break; default: usage: fprintf(stderr, "usage: %s [-hImMs] schemfile...\n", argv[0]); exit(1); } if (!argv[optind]) goto usage; if (domcl) { read_MCL(); hash_MCL(); if (checkhash) report_mclhash_quality(); } if (dosymbols) set_default_sympath(); for (avp = argv + optind; *avp; avp++) { schem = read_schem(*avp); hash_component_instances(schem); if (checkhash) report_compinst_hash_quality(schem); if (domcl) match_schem_to_mcl(schem); if (dosymbols) { load_graphsyms(schem); instantiate_graphsym_pins(schem, 1); if (checkhash) report_pininst_hash_quality(schem); } donets = 1; check_schem_objects(); if (preen_graphnets(schem, 1, dosymbols, 1, 0) < 0) donets = 0; if (donets && (!schem->is_graph || dosymbols)) check_exclusive_nets(); } report_exclusive_net_violations(); if (checkhash && dosymbols) report_graphsym_hash_quality(); exit(0); } check_schem_objects() { register struct schemobj *obj; for (obj = schem->obj_next; obj != (struct schemobj *)schem; obj = obj->obj_next) { switch (obj->obj_type) { case OBJTYPE_COMPINST: if (obj->compobj_isgraph && !schem->is_graph) fprintf(stderr, "%s: line %d: graphical symbol used in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); if (obj->compobj_isgraph && dosymbols && obj->compobj_graphsym->gs_forcenets) fprintf(stderr, "%s: line %d: symbol \"%s\" on %s: forcenets won't have the desired effect\n", schem->orig_filename, obj->obj_lineno, obj->compobj_graph_symname, obj->compobj_instname); break; case OBJTYPE_GRAPHSYM: if (!schem->is_graph) fprintf(stderr, "%s: line %d: GraphSym object in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); break; case OBJTYPE_GRAPHNET: if (!schem->is_graph) { fprintf(stderr, "%s: line %d: GraphNet object in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); donets = 0; } break; case OBJTYPE_NETLINE: if (!schem->is_graph) fprintf(stderr, "%s: line %d: NetLine object in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); break; case OBJTYPE_BUSSEG: if (!schem->is_graph) fprintf(stderr, "%s: line %d: BusSeg object in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); break; case OBJTYPE_GRAPHBLOCK: if (!schem->is_graph) fprintf(stderr, "%s: line %d: graphics block in a non-graphical schematic\n", schem->orig_filename, obj->obj_lineno); break; } check_obj_decors(obj); } } check_obj_decors(obj) register struct schemobj *obj; { register struct decoration *decor; for (decor = obj->obj_decorations; decor; decor = decor->decor_next) switch (decor->decor_type) { case DECOR_TYPE_DISPLAYATTR: if (!is_graphical_obj(obj)) fprintf(stderr, "%s: line %d: DisplayAttr on a non-graphical object\n", schem->orig_filename, decor->decor_lineno); continue; case DECOR_TYPE_DISPLAYNETNAME: if (obj->obj_type != OBJTYPE_GRAPHNET) fprintf(stderr, "%s: line %d: DisplayNetName invalid in objects other than GraphNet\n", schem->orig_filename, decor->decor_lineno); continue; case DECOR_TYPE_GRAPHBLOCK: if (!is_graphical_obj(obj)) fprintf(stderr, "%s: line %d: graphics block decoration on a non-graphical object\n", schem->orig_filename, decor->decor_lineno); break; case DECOR_TYPE_PINTONET: if (obj->obj_type != OBJTYPE_COMPINST) { fprintf(stderr, "%s: line %d: PinToNet invalid in objects other than components\n", schem->orig_filename, decor->decor_lineno); continue; } record_netname_reference(decor->decorpincon_netname, 0, schem->orig_filename, decor->decor_lineno); if (obj->compobj_isgraph && dosymbols) check_pintonet_graph(obj, decor); continue; case DECOR_TYPE_SYMONPIN: if (obj->obj_type != OBJTYPE_COMPINST) { fprintf(stderr, "%s: line %d: SymOnPin invalid in objects other than components\n", schem->orig_filename, decor->decor_lineno); continue; } if (!obj->compobj_isgraph) { fprintf(stderr, "%s: line %d: SymOnPin invalid on a non-graphical component\n", schem->orig_filename, decor->decor_lineno); continue; } if (dosymbols) check_symonpin(obj, decor); } } is_graphical_obj(obj) register struct schemobj *obj; { switch (obj->obj_type) { case OBJTYPE_COMPINST: return(obj->compobj_isgraph); case OBJTYPE_GRAPHSYM: case OBJTYPE_GRAPHNET: case OBJTYPE_NETLINE: case OBJTYPE_BUSSEG: case OBJTYPE_GRAPHBLOCK: return(1); default: return(0); } } check_pintonet_graph(obj, condec) struct schemobj *obj; register struct decoration *condec; { register struct decoration *symdec; /* is this pin represented graphically? */ if (!is_pin_graphical(obj->compobj_graphsym, condec->decorpincon_pin)) return; /* it is graphical -- look for matching SymOnPin */ for (symdec = obj->obj_decorations; symdec; symdec = symdec->decor_next) if (symdec->decor_type == DECOR_TYPE_SYMONPIN && !strcmp(condec->decorpincon_pin, symdec->decorpinsym_pin)) break; if (!symdec) fprintf(stderr, "%s: line %d: pin %s of %s is connected with PinToNet, but not marked with SymOnPin\n", schem->orig_filename, condec->decor_lineno, condec->decorpincon_pin, obj->compobj_instname); } is_pin_graphical(gs, matchkey) struct graphsym *gs; register char *matchkey; { int bynum; register struct graphsym_pindef *pd; register char *pinid; if (matchkey[0] == '#') { bynum = 1; matchkey++; } else bynum = 0; for (pd = gs->gs_pins; pd; pd = pd->gspd_next) { pinid = bynum ? pd->gspd_pinnumber : pd->gspd_pinname; if (pinid && !strcmp(pinid, matchkey)) return(1); } return(0); } check_symonpin(obj, symdec) struct schemobj *obj; struct decoration *symdec; { struct graphsym *gs; struct graphsym_pindef *pindef; register struct decoration *ndec; gs = symdec->decorpinsym_gs; if (gs->gs_npins > 1) { fprintf(stderr, "%s: line %d: SymOnPin symbols may not have more than 1 pin\n", schem->orig_filename, symdec->decor_lineno); return; } pindef = gs->gs_pins; if (!pindef->gspd_forcenet) return; /* look for matching PinToNet */ for (ndec = obj->obj_decorations; ndec; ndec = ndec->decor_next) if (ndec->decor_type == DECOR_TYPE_PINTONET && !strcmp(ndec->decorpincon_pin, symdec->decorpinsym_pin)) break; if (!ndec) { fprintf(stderr, "%s: line %d: SymOnPin implies connection to %s, but no matching PinToNet\n", schem->orig_filename, symdec->decor_lineno, pindef->gspd_forcenet); return; } if (strcmp(ndec->decorpincon_netname, pindef->gspd_forcenet)) fprintf(stderr, "%s: SymOnPin (line %d) and PinToNet (line %d) call for different nets!\n", schem->orig_filename, symdec->decor_lineno, ndec->decor_lineno); }