diff ueda/uschem-utils/check.c @ 0:cd92449fdb51

initial import of ueda and ifctf-part-lib from ifctfvax CVS
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 20 Jul 2015 00:24:37 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ueda/uschem-utils/check.c	Mon Jul 20 00:24:37 2015 +0000
@@ -0,0 +1,298 @@
+/*
+ * 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);
+}