Compare commits

..

9 Commits

Author SHA1 Message Date
R. Timothy Edwards 8a2bbe0723 Updated version to go along with PR #105 from user jalcim on github. 2026-04-27 09:50:37 -04:00
jalcim a0c49a026a
fix(netcmp): correct signal handler type for K&R declaration
netcmp.c:55 declares oldinthandler with empty parameter list:
    void (*oldinthandler)() = SIG_DFL;

In K&R / pre-C23, this means 'function with unspecified parameters'.
GCC 14+ infers void(*)(void), which is incompatible with signal(2)'s
expected void(*)(int) handler. The signal(SIGINT, oldinthandler) calls
at lines 8777 and 8784 then fail with -Wincompatible-pointer-types
(now a default error in GCC 14+).

This 1-line fix matches the actual usage as a SIGINT handler with int
signum parameter, and restores tclnetgen.so build on Fedora 41+ /
Debian 13+ / Ubuntu 24.04+ (any system with GCC 14+).

Tested: tclnetgen.so now builds successfully and 'netgen -batch lvs'
mode works again.
2026-04-26 22:06:07 +02:00
R. Timothy Edwards 665203bba1 Corrected genhash() after Mitch Bailey pointed out that the function
was no longer hashing on both values passed to the function, as it
is supposed to.
2026-04-03 08:48:34 -04:00
R. Timothy Edwards 0192558d4b Updated version corresponding to the last commit. 2026-04-02 21:30:01 -04:00
R. Timothy Edwards 21d329b22d Modified the hash algorithm used by netgen after a discussion with
ChatGPT about hash implementations.  Switched from SDBM to FNV-1a,
which should be a better/stronger hash algorithm.  Could do
something more sophisticated, but this change can be done in a few
minutes.
2026-04-02 21:29:04 -04:00
R. Timothy Edwards 37b1a2a07d Cleaned up some errors (most minor, some not so minor) in the
code that were surfaced by Stefan Thiede running clang on Mac
OS.  Function prototype warnings have not been fixed yet, as
that is a more involved fix, although it needs to be done.
2026-02-02 20:53:13 -05:00
R. Timothy Edwards 777f7ef095 Found a counting issue with netcmp output that will overrun the
output string buffer if the size of the copied string is just
the wrong amount, due to the use of strcpy() instead of
strncpy() in at least one place.  Just hacked a solution by
allocating more space for the string, but this should be fixed
properly.  Also:  Discovered that the "zero valued resistor"
routine looks for shorted ports in the wrong place, and if it
finds shorted ports it wrongly decides that the device it's
looking at is a zero-valued resistor whether or not it really
is zero-valued.
2026-01-15 16:39:18 -05:00
R. Timothy Edwards 9b4185fe62 Reverted a change from a long time ago regarding removal of zero
valued resistors connecting two ports.  I do not recall exactly
why I put that in but it appears to cause incorrect behavior.
2025-12-28 14:54:07 -05:00
R. Timothy Edwards ddd95c4fe6 Added a few lines to the setup file parser so that if there is a
missing brace in the file (a common error), then the fact that
there is an unevaluated command when the file has finished being
read will trigger an evaluation of the unfinished code and emit
an error.  Previously, the command and anything after the
unterminated brace would just silently get ignored, which was not
helpful for debugging setup syntax errors.
2025-12-11 12:08:31 -05:00
10 changed files with 64 additions and 30 deletions

View File

@ -1 +1 @@
1.5.312
1.5.319

View File

@ -91,7 +91,7 @@ char *ActelName(char *Name)
/* strip physical-pin information, if it exists */
if ((nm = strrchr(name,PHYSICALPIN[0])) != NULL) *nm = '\0';
if (strlen(name) > 13) {
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
/* format the value of the hashed value of the string */
sprintf(ActelNames[ActelIndex], "$%lX", ActelNameHash(name));
if (Debug)
@ -102,7 +102,7 @@ Printf("ActelNameHash returns %s on name %s\n",ActelNames[ActelIndex], name);
NeedsQuoting = 0;
if (NULL != strpbrk(name, ".,:; \t\"'\n\r")) NeedsQuoting = 1;
ActelIndex = (++ActelIndex) % ACTELNAMESIZE;
ActelIndex = (ActelIndex + 1) % ACTELNAMESIZE;
if (!NeedsQuoting) {
strcpy(ActelNames[ActelIndex], name);
return(ActelNames[ActelIndex]);

View File

@ -2018,8 +2018,11 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
break;
}
}
if (found) break;
}
/* Do NOT remove shorting devices that */
if (found) {
/* Beware remove shorting devices that */
/* connect two ports. Otherwise the */
/* port lists get screwed up. It is */
/* better in that case to force the */
@ -2027,6 +2030,10 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
/* This is ignored for a top-level cell */
/* because it will just show up as a */
/* port mismatch error as it should. */
/* (12/12/2025---disabling this worked; */
/* may need to go back to a failing */
/* example and determine how pin */
/* matching gets scrambled.) */
if ((not_top == TRUE) &&
(ecomp->cell1->class != CLASS_ISOURCE)) {
@ -2039,14 +2046,18 @@ PrematchLists(char *name1, int file1, char *name2, int file2)
else if (ob2->node == node2)
found2 = TRUE;
if (found1 && found2) {
found = FALSE;
Fprintf(stdout, "Warning: "
"zero-valued device connects "
"port %s to another port; pin "
"matching may be affected.\n",
ob2->name);
// found = FALSE;
break;
}
}
}
if (found) break;
}
if (found) {
Fprintf(stdout, "Removing zero-valued device "
"%s from cell %s (%d) makes a better "

View File

@ -137,32 +137,39 @@ static unsigned char uppercase[] = {
// horrible things can happen, as, for example, names AOI12 and OAI12
// have exactly the same hash result. Lousy for binning and even
// lousier for generating class magic numbers.
//
// Updated again 4/2/2026 to the FNV-1a hash, which is better than
// SDBM for this application, according to ChatGPT.
unsigned long hashnocase(char *s, int hashsize)
{
unsigned long hashval;
for (hashval = 0; *s != '\0'; )
hashval = uppercase[*s++]
+ (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
for (; *s != '\0'; s++) {
hashval ^= uppercase[*s];
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
unsigned long hashcase(char *s, int hashsize)
{
unsigned long hashval;
for (hashval = 0; *s != '\0'; )
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}
unsigned long genhash(char *s, int c, int hashsize)
{
unsigned long hashval;
for (hashval = (unsigned long)c; *s != '\0'; )
hashval = (*s++) + (hashval << 6) + (hashval << 16) - hashval;
unsigned long hashval = 2166136261ul;
hashval ^= (unsigned long)c;
hashval *= 16777619ul;
for (; *s != '\0'; s++) {
hashval ^= (unsigned char)(*s);
hashval *= 16777619ul;
}
return (hashsize == 0) ? hashval : (hashval % hashsize);
}

View File

@ -52,7 +52,7 @@ the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#ifdef TCL_NETGEN
int InterruptPending = 0;
void (*oldinthandler)() = SIG_DFL;
void (*oldinthandler)(int) = SIG_DFL;
extern Tcl_Interp *netgeninterp;
extern int check_interrupt();
#endif
@ -1622,8 +1622,8 @@ void FormatIllegalElementClasses()
char *permcount;
int bytesleft;
permname = CALLOC(right_col_end + 2, sizeof(char));
permcount = CALLOC(right_col_end + 2, sizeof(char));
permname = CALLOC(right_col_end + 100, sizeof(char));
permcount = CALLOC(right_col_end + 100, sizeof(char));
ostr = output_string_init();
found = 0;

View File

@ -685,6 +685,7 @@ void SpiceSkipNewLine(void)
ungetc(contline, infile);
}
#if 0 /* Commented with "#if 0" due to comment characters in the comment */
/*----------------------------------------------------------------------*/
/* Function similar to strtok() for token parsing. The difference is */
/* that it takes two sets of delimiters. The first is whitespace */
@ -705,6 +706,7 @@ void SpiceSkipNewLine(void)
/* the first character of the delimiter string in addition to marking */
/* the boundary between two-character and one-character delimiters. */
/*----------------------------------------------------------------------*/
#endif
char *strdtok0(char *pstring, char *delim1, char *delim2, char isverilog)
{

View File

@ -449,6 +449,7 @@ int removeshorted(struct hashlist *p, int file)
ob = nob;
}
}
return 1;
}
/* Remove shorted instances of class "class" from the database */
@ -539,6 +540,7 @@ int deleteclass(struct hashlist *p, int file)
}
}
FREE(checknodes);
return 1;
}
/* Remove all instances of class "class" from the database */
@ -576,6 +578,7 @@ int renameinstances(struct hashlist *p, int file)
}
}
}
return 1;
}
void InstanceRename(char *from, char *to, int file)
@ -598,9 +601,10 @@ int freeprop(struct hashlist *p)
struct property *prop;
prop = (struct property *)(p->ptr);
if (prop->type == PROP_STRING)
if (prop->type == PROP_STRING) {
if (prop->pdefault.string != NULL)
FREE(prop->pdefault.string);
}
else if (prop->type == PROP_EXPRESSION) {
struct tokstack *stackptr, *nptr;
stackptr = prop->pdefault.stack;

View File

@ -319,7 +319,7 @@ void Fanout(char *cell, char *node, int filter)
while (ob != NULL) {
char *obname = ob->name;
if (*obname == '/') obname++;
if (ob->node == nodenum)
if (ob->node == nodenum) {
if (filter == ALLOBJECTS) {
Printf(" %s (", obname);
PrintObjectType(ob->type);
@ -331,6 +331,7 @@ void Fanout(char *cell, char *node, int filter)
else if (ob->type == filter) {
Printf(" %s\n", obname);
}
}
ob = ob->next;
}
}
@ -933,7 +934,7 @@ static int PrintLeavesInCellHash(struct hashlist *p)
struct nlist *ptr;
ptr = (struct nlist *)(p->ptr);
if ((ptr->class == CLASS_SUBCKT)) PrintLeavesInCell(ptr->name, ptr->file);
if (ptr->class == CLASS_SUBCKT) PrintLeavesInCell(ptr->name, ptr->file);
return(0);
}

View File

@ -196,7 +196,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@ -216,7 +216,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@ -236,7 +236,7 @@ void SpiceSubCell(struct nlist *tp, int IsSubCell)
if (ob->type == PROPERTY) {
struct valuelist *vl;
int i;
for (i == 0;; i++) {
for (i = 0;; i++) {
vl = &(ob->instance.props[i]);
if (vl->type == PROP_ENDLIST) break;
else if (vl->type == PROP_VALUE) {
@ -399,7 +399,7 @@ int renamepins(struct hashlist *p, int file)
ptr = (struct nlist *)(p->ptr);
if (ptr->file != file)
return 1;
return 0;
for (ob = ptr->cell; ob != NULL; ob = ob->next) {
if (ob->type == FIRSTPIN) {
@ -426,6 +426,7 @@ int renamepins(struct hashlist *p, int file)
}
}
}
return 1;
}
/* If any pins are marked unconnected, see if there are */

View File

@ -516,6 +516,14 @@ proc netgen::lvs { name1 name2 {setupfile setup.tcl} {logfile comp.out} args} {
}
}
close $fsetup
if {$command != {}} {
# Incomplete command. Evaluate it to get a meaningful error message
if {[catch {uplevel 1 [list namespace eval netgen $command]} msg]} {
set msg [string trimright $msg "\n"]
puts stderr "Error $setupfile:$sline (ignoring), $msg"
incr perrors
}
}
} else {
puts stdout "Error: Cannot read the setup file $setupfile"
}