2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* extcheck.c --
|
|
|
|
|
*
|
|
|
|
|
* Program to check .ext files for consistency without producing
|
|
|
|
|
* any output. Checks for disconnected global nodes as well as
|
|
|
|
|
* for version consistency. Counts the number of interesting
|
|
|
|
|
* things in the circuit (devices, capacitors, resistors, nodes).
|
|
|
|
|
*
|
|
|
|
|
* Flattens the tree rooted at file.ext, reading in additional .ext
|
|
|
|
|
* files as specified by "use" lines in file.ext.
|
|
|
|
|
*
|
2020-05-23 23:13:14 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
* * Copyright (C) 1985, 1990 Regents of the University of California. *
|
|
|
|
|
* * Permission to use, copy, modify, and distribute this *
|
|
|
|
|
* * software and its documentation for any purpose and without *
|
|
|
|
|
* * fee is hereby granted, provided that the above copyright *
|
|
|
|
|
* * notice appear in all copies. The University of California *
|
|
|
|
|
* * makes no representations about the suitability of this *
|
|
|
|
|
* * software for any purpose. It is provided "as is" without *
|
|
|
|
|
* * express or implied warranty. Export of this software outside *
|
|
|
|
|
* * of the United States of America may require an export license. *
|
2017-04-25 14:41:48 +02:00
|
|
|
* *********************************************************************
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#ifndef lint
|
2025-07-18 19:38:13 +02:00
|
|
|
static const char rcsid[] = "$Header: /usr/cvsroot/magic-8.0/extcheck/extcheck.c,v 1.1.1.1 2008/02/03 20:43:50 tim Exp $";
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* not lint */
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
|
|
|
|
|
#include "utils/magic.h"
|
|
|
|
|
#include "utils/paths.h"
|
|
|
|
|
#include "utils/geometry.h"
|
|
|
|
|
#include "utils/hash.h"
|
|
|
|
|
#include "utils/utils.h"
|
|
|
|
|
#include "utils/pathvisit.h"
|
|
|
|
|
#include "extflat/extflat.h"
|
|
|
|
|
#include "utils/runstats.h"
|
2025-07-18 23:00:55 +02:00
|
|
|
#include "extflat/EFint.h" /* HierContext */
|
2017-04-25 14:41:48 +02:00
|
|
|
|
|
|
|
|
int ecNumDevs;
|
|
|
|
|
int ecNumCaps;
|
|
|
|
|
int ecNumResists;
|
|
|
|
|
int ecNumThreshCaps;
|
|
|
|
|
int ecNumThreshResists;
|
|
|
|
|
int ecNumNodes;
|
|
|
|
|
int ecNumGlobalNodes;
|
|
|
|
|
int ecNumNodeCaps;
|
|
|
|
|
int ecNumNodeResists;
|
|
|
|
|
|
|
|
|
|
/* Forward declarations */
|
2025-07-18 23:00:55 +02:00
|
|
|
int nodeVisit(EFNode *node, int res, double cap, ClientData cdata); /* @typedef cb_extflat_visitnodes_t (UNUSED) */
|
|
|
|
|
int devVisit(Dev *dev, HierContext *hc, float scale, Transform *trans, ClientData cdata); /* @typedef cb_extflat_visitdevs_t (UNUSED) */
|
|
|
|
|
int capVisit(HierName *hn1, HierName *hn2, double cap, ClientData cdata); /* @typedef cb_extflat_visitcaps_t (UNUSED) */
|
2025-07-20 17:09:08 +02:00
|
|
|
int resistVisit(const HierName *hn1, const HierName *hn2, float res, ClientData cdata); /* @typedef cb_extflat_visitresists_t (UNUSED) */
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* main --
|
|
|
|
|
*
|
|
|
|
|
* Top level of extcheck.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
2025-07-18 19:37:44 +02:00
|
|
|
int
|
|
|
|
|
main(int argc, char *argv[])
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
char *inName;
|
|
|
|
|
|
|
|
|
|
/* Process command line arguments */
|
|
|
|
|
EFInit();
|
|
|
|
|
inName = EFArgs(argc, argv, NULL, (int (*)()) NULL, (ClientData) NULL);
|
|
|
|
|
if (inName == NULL)
|
|
|
|
|
exit (1);
|
|
|
|
|
|
|
|
|
|
/* Read the hierarchical description of the input circuit */
|
2023-07-28 15:40:41 +02:00
|
|
|
EFReadFile(inName, FALSE, FALSE, FALSE, FALSE);
|
2017-04-25 14:41:48 +02:00
|
|
|
if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
|
|
|
|
|
if (EFScale == 0.0) EFScale = 1.0;
|
|
|
|
|
|
|
|
|
|
/* Convert the hierarchical description to a flat one */
|
|
|
|
|
EFFlatBuild(inName, EF_FLATNODES|EF_FLATCAPS|EF_FLATRESISTS);
|
|
|
|
|
|
|
|
|
|
EFVisitDevs(devVisit, (ClientData) NULL);
|
|
|
|
|
if (IS_FINITE_F(EFCapThreshold))
|
|
|
|
|
EFVisitCaps(capVisit, (ClientData) NULL);
|
|
|
|
|
if (EFResistThreshold != INFINITE_THRESHOLD)
|
2025-07-20 17:09:08 +02:00
|
|
|
EFVisitResists(resistVisit, PTR2CD(NULL));
|
2017-04-25 14:41:48 +02:00
|
|
|
EFVisitNodes(nodeVisit, (ClientData) NULL);
|
|
|
|
|
|
|
|
|
|
#ifdef free_all_mem
|
2022-02-23 21:02:40 +01:00
|
|
|
EFFlatDone(NULL);
|
2024-09-30 00:00:00 +02:00
|
|
|
EFDone(NULL);
|
2017-04-25 14:41:48 +02:00
|
|
|
#endif /* free_all_mem */
|
|
|
|
|
|
|
|
|
|
printf("Memory used: %s\n", RunStats(RS_MEM, NULL, NULL));
|
|
|
|
|
printf("%d devices\n", ecNumDevs);
|
|
|
|
|
printf("%d nodes (%d global, %d local)\n",
|
|
|
|
|
ecNumNodes, ecNumGlobalNodes, ecNumNodes - ecNumGlobalNodes);
|
|
|
|
|
printf("%d nodes above capacitance threshold\n", ecNumNodeCaps);
|
|
|
|
|
printf("%d nodes above resistance threshold\n", ecNumNodeResists);
|
|
|
|
|
printf("%d internodal capacitors (%d above threshold)\n",
|
|
|
|
|
ecNumCaps, ecNumThreshCaps);
|
|
|
|
|
printf("%d explicit resistors (%d above threshold)\n",
|
|
|
|
|
ecNumResists, ecNumThreshResists);
|
|
|
|
|
exit (0);
|
|
|
|
|
}
|
2020-05-23 23:13:14 +02:00
|
|
|
|
2017-04-25 14:41:48 +02:00
|
|
|
/*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*
|
|
|
|
|
* nodeVisit --
|
|
|
|
|
* devVisit --
|
|
|
|
|
* capVisit --
|
|
|
|
|
* resistVisit --
|
|
|
|
|
*
|
|
|
|
|
* Called once for each of the appropriate type of object.
|
|
|
|
|
* Each updates various counts.
|
|
|
|
|
*
|
|
|
|
|
* Results:
|
|
|
|
|
* Returns 0 always.
|
|
|
|
|
*
|
|
|
|
|
* Side effects:
|
|
|
|
|
* See above.
|
|
|
|
|
*
|
|
|
|
|
* ----------------------------------------------------------------------------
|
|
|
|
|
*/
|
|
|
|
|
|
2025-07-18 23:00:55 +02:00
|
|
|
/* @typedef cb_extflat_visitnodes_t (UNUSED) */
|
2017-04-25 14:41:48 +02:00
|
|
|
int
|
2025-07-18 19:37:44 +02:00
|
|
|
nodeVisit(
|
|
|
|
|
EFNode *node,
|
|
|
|
|
int res,
|
2025-07-18 23:00:55 +02:00
|
|
|
double cap,
|
|
|
|
|
ClientData cdata) /* unused */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
cap = (cap + 500) / 1000;
|
|
|
|
|
res = (res + 500) / 1000;
|
|
|
|
|
|
|
|
|
|
ecNumNodes++;
|
|
|
|
|
if (EFHNIsGlob(node->efnode_name->efnn_hier))
|
|
|
|
|
ecNumGlobalNodes++;
|
|
|
|
|
if (res > EFResistThreshold) ecNumNodeResists++;
|
|
|
|
|
if (cap > (double) EFCapThreshold) ecNumNodeCaps++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 23:00:55 +02:00
|
|
|
/*ARGSUSED*/
|
|
|
|
|
/* @typedef cb_extflat_visitdevs_t (UNUSED) */
|
2017-04-25 14:41:48 +02:00
|
|
|
int
|
2025-07-18 23:00:55 +02:00
|
|
|
devVisit(
|
|
|
|
|
Dev *dev,
|
|
|
|
|
HierContext *hc,
|
|
|
|
|
float scale,
|
|
|
|
|
Transform *trans,
|
|
|
|
|
ClientData cdata) /* UNUSED */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
ecNumDevs++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 23:00:55 +02:00
|
|
|
/*ARGSUSED*/
|
|
|
|
|
/* @typedef cb_extflat_visitcaps_t (UNUSED) */
|
2017-04-25 14:41:48 +02:00
|
|
|
int
|
2025-07-18 19:37:44 +02:00
|
|
|
capVisit(
|
|
|
|
|
HierName *hn1,
|
|
|
|
|
HierName *hn2, /* UNUSED */
|
2025-07-18 23:00:55 +02:00
|
|
|
double cap,
|
|
|
|
|
ClientData cdata) /* UNUSED */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
ecNumCaps++;
|
|
|
|
|
if ((cap / 1000.) > (double) EFCapThreshold) ecNumThreshCaps++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2025-07-18 23:00:55 +02:00
|
|
|
/*ARGSUSED*/
|
|
|
|
|
/* @typedef cb_extflat_visitresists_t (UNUSED) */
|
2017-04-25 14:41:48 +02:00
|
|
|
int
|
2025-07-18 19:37:44 +02:00
|
|
|
resistVisit(
|
2025-07-20 17:09:08 +02:00
|
|
|
const HierName *hn1,
|
|
|
|
|
const HierName *hn2,/* UNUSED */
|
2025-07-18 23:00:55 +02:00
|
|
|
float res,
|
|
|
|
|
ClientData cdata) /* UNUSED */
|
2017-04-25 14:41:48 +02:00
|
|
|
{
|
|
|
|
|
ecNumResists++;
|
|
|
|
|
if ((res / 1000.) > EFResistThreshold) ecNumThreshResists++;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|