2020-08-08 15:47:34 +02:00
|
|
|
/* File: netlist.c
|
2020-10-12 13:13:31 +02:00
|
|
|
*
|
2020-08-08 15:47:34 +02:00
|
|
|
* This file is part of XSCHEM,
|
2020-10-12 13:13:31 +02:00
|
|
|
* a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit
|
2020-08-08 15:47:34 +02:00
|
|
|
* simulation.
|
2022-06-24 00:36:12 +02:00
|
|
|
* Copyright (C) 1998-2022 Stefan Frederik Schippers
|
2020-08-08 15:47:34 +02:00
|
|
|
*
|
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "xschem.h"
|
|
|
|
|
|
|
|
|
|
static void instdelete(int n, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instentry *saveptr, **prevptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
prevptr = &xctx->inst_spatial_table[x][y];
|
2020-11-17 01:29:47 +01:00
|
|
|
while( (*prevptr)->n != n) prevptr = &(*prevptr)->next;
|
|
|
|
|
saveptr = (*prevptr)->next;
|
|
|
|
|
my_free(821, prevptr);
|
|
|
|
|
*prevptr = saveptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void instinsert(int n, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instentry *ptr, *newptr;
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr=xctx->inst_spatial_table[x][y];
|
2021-12-28 01:33:01 +01:00
|
|
|
newptr=my_malloc(236, sizeof(Instentry));
|
2020-08-08 15:47:34 +02:00
|
|
|
newptr->next=ptr;
|
|
|
|
|
newptr->n=n;
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->inst_spatial_table[x][y]=newptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "instinsert(): inserting object %d at %d,%d\n",n,x,y);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-28 01:33:01 +01:00
|
|
|
static Instentry *delinstentry(Instentry *t)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instentry *tmp;
|
2020-08-08 15:47:34 +02:00
|
|
|
while( t ) {
|
|
|
|
|
tmp = t->next;
|
|
|
|
|
my_free(822, &t);
|
|
|
|
|
t = tmp;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void del_inst_table(void)
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<NBOXES;i++)
|
|
|
|
|
for(j=0;j<NBOXES;j++)
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->inst_spatial_table[i][j] = delinstentry(xctx->inst_spatial_table[i][j]);
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_hash_inst=0;
|
2020-11-16 02:25:43 +01:00
|
|
|
dbg(1, "del_inst_table(): cleared object hash table\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
/* what:
|
2020-08-08 15:47:34 +02:00
|
|
|
* 0, XINSERT : add to hash
|
|
|
|
|
* 1, XDELETE : remove from hash
|
|
|
|
|
*/
|
|
|
|
|
void hash_inst(int what, int n) /* 20171203 insert object bbox in spatial hash table */
|
|
|
|
|
{
|
|
|
|
|
int tmpi,tmpj, counti,countj,i,j;
|
|
|
|
|
double tmpd;
|
|
|
|
|
double x1, y1, x2, y2;
|
|
|
|
|
int x1a, x2a, y1a, y2a;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
x1=xctx->inst[n].x1;
|
|
|
|
|
x2=xctx->inst[n].x2;
|
|
|
|
|
y1=xctx->inst[n].y1;
|
|
|
|
|
y2=xctx->inst[n].y2;
|
2020-08-08 15:47:34 +02:00
|
|
|
/* ordered bbox */
|
|
|
|
|
if( x2 < x1) { tmpd=x2;x2=x1;x1=tmpd;}
|
|
|
|
|
if( y2 < y1) { tmpd=y2;y2=y1;y1=tmpd;}
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* calculate square 4 1st bbox point of object[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x1a=(int)floor(x1/BOXSIZE);
|
|
|
|
|
y1a=(int)floor(y1/BOXSIZE);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* calculate square 4 2nd bbox point of object[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x2a=(int)floor(x2/BOXSIZE);
|
|
|
|
|
y2a=(int)floor(y2/BOXSIZE);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/*loop thru all squares that intersect bbox of object[k] */
|
|
|
|
|
counti=0;
|
|
|
|
|
for(i=x1a; i<=x2a && counti < NBOXES; i++)
|
|
|
|
|
{
|
|
|
|
|
counti++;
|
|
|
|
|
tmpi=i%NBOXES; if(tmpi<0) tmpi+=NBOXES;
|
|
|
|
|
countj=0;
|
|
|
|
|
for(j=y1a; j<=y2a && countj < NBOXES; j++)
|
|
|
|
|
{
|
|
|
|
|
countj++;
|
|
|
|
|
tmpj=j%NBOXES; if(tmpj<0) tmpj+=NBOXES;
|
|
|
|
|
/* insert object_ptr[n] in region [tmpi, tmpj] */
|
2020-10-12 13:13:31 +02:00
|
|
|
if(what == XINSERT) instinsert(n, tmpi, tmpj);
|
2020-08-08 15:47:34 +02:00
|
|
|
else instdelete(n, tmpi, tmpj);
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
void hash_instances(void) /* 20171203 insert object bbox in spatial hash table */
|
|
|
|
|
{
|
|
|
|
|
int n;
|
|
|
|
|
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->prep_hash_inst) return;
|
2020-08-08 15:47:34 +02:00
|
|
|
del_inst_table();
|
2020-10-15 17:39:21 +02:00
|
|
|
for(n=0; n<xctx->instances; n++) {
|
2020-08-08 15:47:34 +02:00
|
|
|
hash_inst(XINSERT, n);
|
|
|
|
|
}
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_hash_inst=1;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
static void instpindelete(int n,int pin, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instpinentry *saveptr, **prevptr, *ptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
prevptr = &xctx->instpin_spatial_table[x][y];
|
2020-08-08 15:47:34 +02:00
|
|
|
ptr = *prevptr;
|
|
|
|
|
while(ptr) {
|
|
|
|
|
if(ptr->n == n && ptr->pin == pin) {
|
|
|
|
|
saveptr = ptr->next;
|
|
|
|
|
my_free(823, &ptr);
|
|
|
|
|
*prevptr = saveptr;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
prevptr = &ptr->next;
|
|
|
|
|
ptr = *prevptr;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* --pin coordinates-- -square coord- */
|
|
|
|
|
static void instpininsert(int n,int pin, double x0, double y0, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instpinentry *ptr, *newptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr=xctx->instpin_spatial_table[x][y];
|
2021-12-28 01:33:01 +01:00
|
|
|
newptr=my_malloc(237, sizeof(Instpinentry));
|
2020-08-08 15:47:34 +02:00
|
|
|
newptr->next=ptr;
|
|
|
|
|
newptr->n=n;
|
|
|
|
|
newptr->x0=x0;
|
|
|
|
|
newptr->y0=y0;
|
|
|
|
|
newptr->pin=pin;
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->instpin_spatial_table[x][y]=newptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "instpininsert(): inserting inst %d at %d,%d\n",n,x,y);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2022-02-19 14:31:55 +01:00
|
|
|
static Instpinentry *delinstpinentry(Instpinentry *t)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Instpinentry *tmp;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
while(t) {
|
|
|
|
|
tmp = t->next;
|
|
|
|
|
my_free(824, &t);
|
|
|
|
|
t = tmp;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void del_inst_pin_table(void)
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<NBOXES;i++)
|
|
|
|
|
for(j=0;j<NBOXES;j++)
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->instpin_spatial_table[i][j] = delinstpinentry(xctx->instpin_spatial_table[i][j]);
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-11-17 01:29:47 +01:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
static void wiredelete(int n, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *saveptr, **prevptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
prevptr = &xctx->wire_spatial_table[x][y];
|
2020-11-17 01:29:47 +01:00
|
|
|
while( (*prevptr)->n != n) prevptr = &(*prevptr)->next;
|
|
|
|
|
saveptr = (*prevptr)->next;
|
|
|
|
|
my_free(825, prevptr);
|
|
|
|
|
*prevptr = saveptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void wireinsert(int n, int x, int y)
|
|
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *ptr, *newptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr=xctx->wire_spatial_table[x][y];
|
2021-12-28 01:33:01 +01:00
|
|
|
newptr=my_malloc(238, sizeof(Wireentry));
|
2020-08-08 15:47:34 +02:00
|
|
|
newptr->next=ptr;
|
|
|
|
|
newptr->n=n;
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->wire_spatial_table[x][y]=newptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "wireinsert(): inserting wire %d at %d,%d\n",n,x,y);
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-28 01:33:01 +01:00
|
|
|
static Wireentry *delwireentry(Wireentry *t)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *tmp;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
while( t ) {
|
|
|
|
|
tmp = t->next;
|
|
|
|
|
my_free(826, &t);
|
|
|
|
|
t = tmp;
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void del_wire_table(void)
|
|
|
|
|
{
|
|
|
|
|
int i,j;
|
|
|
|
|
|
|
|
|
|
for(i=0;i<NBOXES;i++)
|
|
|
|
|
for(j=0;j<NBOXES;j++)
|
2021-11-23 15:03:51 +01:00
|
|
|
xctx->wire_spatial_table[i][j] = delwireentry(xctx->wire_spatial_table[i][j]);
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_hash_wires=0;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
void get_square(double x, double y, int *xx, int *yy)
|
|
|
|
|
{
|
|
|
|
|
int xa, xb, ya, yb;
|
|
|
|
|
|
2022-04-27 13:18:45 +02:00
|
|
|
xa=(int)floor(x/BOXSIZE) ;
|
2020-08-08 15:47:34 +02:00
|
|
|
xb=xa % NBOXES; if(xb<0) xb+=NBOXES;
|
2022-04-27 13:18:45 +02:00
|
|
|
ya=(int)floor(y/BOXSIZE) ;
|
2020-08-08 15:47:34 +02:00
|
|
|
yb=ya % NBOXES; if(yb<0) yb+=NBOXES;
|
|
|
|
|
|
|
|
|
|
*xx=xb;
|
|
|
|
|
*yy=yb;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
/* what:
|
2020-08-08 15:47:34 +02:00
|
|
|
* 0, XINSERT : add to hash
|
|
|
|
|
* 1, XDELETE : remove from hash
|
|
|
|
|
*/
|
2021-12-07 20:40:33 +01:00
|
|
|
static void hash_inst_pin(int for_netlist, int what, int i, int j)
|
|
|
|
|
/* inst pin */
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
xRect *rct;
|
2020-08-08 15:47:34 +02:00
|
|
|
char *prop_ptr;
|
|
|
|
|
double x0, y0, rx1, ry1;
|
2020-12-05 03:16:01 +01:00
|
|
|
short rot, flip;
|
|
|
|
|
int sqx, sqy;
|
2020-08-08 15:47:34 +02:00
|
|
|
int rects;
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
rects=(xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER] ;
|
2020-08-08 15:47:34 +02:00
|
|
|
if(j>=rects) /* generic pins */
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
rct=(xctx->inst[i].ptr+ xctx->sym)->rect[GENERICLAYER];
|
2020-10-12 13:13:31 +02:00
|
|
|
x0=(rct[j-rects].x1+rct[j-rects].x2)/2;
|
|
|
|
|
y0=(rct[j-rects].y1+rct[j-rects].y2)/2;
|
|
|
|
|
prop_ptr = rct[j-rects].prop_ptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
rct=(xctx->inst[i].ptr+ xctx->sym)->rect[PINLAYER];
|
2020-10-12 13:13:31 +02:00
|
|
|
x0=(rct[j].x1+rct[j].x2)/2;
|
|
|
|
|
y0=(rct[j].y1+rct[j].y2)/2;
|
|
|
|
|
prop_ptr = rct[j].prop_ptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2021-12-07 20:40:33 +01:00
|
|
|
if(for_netlist && j<rects &&
|
|
|
|
|
(!prop_ptr || !get_tok_value(prop_ptr, "name",0)[0] || !get_tok_value(prop_ptr, "dir",0)[0]) ) {
|
2020-08-08 15:47:34 +02:00
|
|
|
char str[2048];
|
2020-11-30 17:33:15 +01:00
|
|
|
my_snprintf(str, S(str), "symbol %s: missing all or name or dir attributes on pin %d\n %s",
|
|
|
|
|
xctx->inst[i].name, j, prop_ptr);
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2021-10-26 00:04:13 +02:00
|
|
|
if(!xctx->netlist_count) {
|
2021-01-07 16:35:57 +01:00
|
|
|
xctx->inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
rot=xctx->inst[i].rot;
|
|
|
|
|
flip=xctx->inst[i].flip;
|
2020-11-03 12:10:55 +01:00
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
2020-10-15 17:39:21 +02:00
|
|
|
x0=xctx->inst[i].x0+rx1;
|
|
|
|
|
y0=xctx->inst[i].y0+ry1;
|
2020-08-08 15:47:34 +02:00
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
|
|
|
|
if( what == XINSERT ) instpininsert(i, j, x0, y0, sqx, sqy);
|
|
|
|
|
else instpindelete(i, j, sqx, sqy);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
/* what:
|
2020-08-08 15:47:34 +02:00
|
|
|
* 0, XINSERT : add to hash
|
|
|
|
|
* 1, XDELETE : remove from hash
|
|
|
|
|
*/
|
2020-10-16 16:34:15 +02:00
|
|
|
void hash_wire(int what, int n, int incremental)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
int tmpi,tmpj, counti,countj,i,j;
|
|
|
|
|
double tmpd;
|
|
|
|
|
double x1, y1, x2, y2;
|
|
|
|
|
int x1a, x2a, y1a, y2a;
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *wptr;
|
2020-10-16 16:34:15 +02:00
|
|
|
xWire * const wire = xctx->wire;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
wire[n].end1 = wire[n].end2=-1;
|
|
|
|
|
x1=wire[n].x1;
|
|
|
|
|
x2=wire[n].x2;
|
|
|
|
|
y1=wire[n].y1;
|
|
|
|
|
y2=wire[n].y2;
|
2020-08-08 15:47:34 +02:00
|
|
|
/* ordered bbox */
|
|
|
|
|
if( x2 < x1) { tmpd=x2;x2=x1;x1=tmpd;}
|
|
|
|
|
if( y2 < y1) { tmpd=y2;y2=y1;y1=tmpd;}
|
|
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/* calculate square 4 1st bbox point of wire[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x1a=(int)floor(x1/BOXSIZE) ;
|
|
|
|
|
y1a=(int)floor(y1/BOXSIZE) ;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/* calculate square 4 2nd bbox point of wire[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x2a=(int)floor(x2/BOXSIZE);
|
|
|
|
|
y2a=(int)floor(y2/BOXSIZE);
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/*loop thru all squares that intersect bbox of wire[k] */
|
2020-08-08 15:47:34 +02:00
|
|
|
counti=0;
|
|
|
|
|
for(i=x1a; i<=x2a && counti < NBOXES; i++)
|
|
|
|
|
{
|
|
|
|
|
counti++;
|
|
|
|
|
tmpi=i%NBOXES; if(tmpi<0) tmpi+=NBOXES;
|
|
|
|
|
countj=0;
|
|
|
|
|
for(j=y1a; j<=y2a && countj < NBOXES; j++)
|
|
|
|
|
{
|
|
|
|
|
countj++;
|
|
|
|
|
tmpj=j%NBOXES; if(tmpj<0) tmpj+=NBOXES;
|
2020-10-16 16:34:15 +02:00
|
|
|
/* insert wire[n] in region [tmpi, tmpj] */
|
2020-08-08 15:47:34 +02:00
|
|
|
if(what==XINSERT) wireinsert(n, tmpi, tmpj);
|
|
|
|
|
else wiredelete(n, tmpi, tmpj);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/* reset ends of all wires that *could* touch wire[n] */
|
2021-11-23 15:03:51 +01:00
|
|
|
if(incremental) for(wptr = xctx->wire_spatial_table[tmpi][tmpj] ; wptr ; wptr = wptr->next) {
|
2020-10-16 16:34:15 +02:00
|
|
|
wire[wptr->n].end1 = wire[wptr->n].end2 = -1;
|
2020-10-11 13:08:32 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hash_wires(void)
|
|
|
|
|
{
|
|
|
|
|
int n;
|
2020-12-02 15:10:47 +01:00
|
|
|
if(xctx->prep_hash_wires) return;
|
2020-08-08 15:47:34 +02:00
|
|
|
del_wire_table();
|
2020-10-16 16:34:15 +02:00
|
|
|
|
|
|
|
|
for(n=0; n<xctx->wires; n++) hash_wire(XINSERT, n, 0);
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_hash_wires=1;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* return 0 if library path of s matches any lib name in tcl variable $xschem_libs */
|
2021-06-15 01:15:32 +02:00
|
|
|
/* what: 1: netlist exclude lib, 2: hierarchical print exclude lib */
|
|
|
|
|
int check_lib(int what, const char *s)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
int range,i, found;
|
2021-06-15 01:15:32 +02:00
|
|
|
char str[PATH_MAX + 512]; /* overflow safe 20161122 */
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
found=0;
|
2021-06-15 01:15:32 +02:00
|
|
|
if(what & 1) tcleval("llength $xschem_libs");
|
|
|
|
|
if(what & 2) tcleval("llength $noprint_libs");
|
2020-08-16 03:34:45 +02:00
|
|
|
range = atoi(tclresult());
|
2021-06-14 08:42:19 +02:00
|
|
|
dbg(1, "check_lib(): s=%s, range=%d\n", s, range);
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
for(i=0;i<range;i++){
|
2021-06-15 01:15:32 +02:00
|
|
|
if(what & 1 ) my_snprintf(str, S(str), "lindex $xschem_libs %d",i);
|
|
|
|
|
if(what & 2 ) my_snprintf(str, S(str), "lindex $noprint_libs %d",i);
|
2020-08-08 15:47:34 +02:00
|
|
|
tcleval(str);
|
2021-06-15 01:15:32 +02:00
|
|
|
dbg(1, "check_lib(): %s -> %s\n", str, tclresult());
|
2021-06-14 08:42:19 +02:00
|
|
|
my_snprintf(str, S(str), "regexp {%s} %s", tclresult(), s);
|
2021-06-15 01:23:17 +02:00
|
|
|
dbg(1, "check_lib(): str=%s\n", str);
|
2021-06-14 08:42:19 +02:00
|
|
|
tcleval(str);
|
|
|
|
|
if( tclresult()[0] == '1') found=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
if(found) return 0;
|
|
|
|
|
else return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-12 13:13:31 +02:00
|
|
|
void netlist_options(int i)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
const char * str;
|
2020-10-15 17:39:21 +02:00
|
|
|
str = get_tok_value(xctx->inst[i].prop_ptr, "bus_replacement_char", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
if(str[0] && str[1] && strlen(str) ==2) {
|
2020-12-02 19:35:42 +01:00
|
|
|
bus_char[0] = str[0];
|
|
|
|
|
bus_char[1] = str[1];
|
2020-08-08 15:47:34 +02:00
|
|
|
/* tclsetvar("bus_replacement_char", str); */
|
|
|
|
|
}
|
2020-12-02 19:35:42 +01:00
|
|
|
/* fprintf(errfp, "netlist_options(): bus_char=%s\n", str); */
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
str = get_tok_value(xctx->inst[i].prop_ptr, "top_subckt", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
if(str[0]) {
|
2020-10-15 17:39:21 +02:00
|
|
|
/* fprintf(errfp, "netlist_options(): prop_ptr=%s\n", xctx->inst[i].prop_ptr); */
|
2021-11-10 13:43:08 +01:00
|
|
|
if(!strcmp(str, "true")) tclsetintvar("top_subckt", 1);
|
|
|
|
|
else tclsetintvar("top_subckt", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
str = get_tok_value(xctx->inst[i].prop_ptr, "spiceprefix", 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
if(str[0]) {
|
2020-10-15 17:39:21 +02:00
|
|
|
/* fprintf(errfp, "netlist_options(): prop_ptr=%s\n", xctx->inst[i].prop_ptr); */
|
2021-11-10 13:43:08 +01:00
|
|
|
if(!strcmp(str, "false")) tclsetvar("spiceprefix", "0");
|
|
|
|
|
else tclsetvar("spiceprefix", "1");
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-11-24 02:54:45 +01:00
|
|
|
|
|
|
|
|
str = get_tok_value(xctx->inst[i].prop_ptr, "hiersep", 0);
|
|
|
|
|
if(str[0]) {
|
2021-10-25 17:05:43 +02:00
|
|
|
my_snprintf(xctx->hiersep, S(xctx->hiersep), "%s", str);
|
2020-11-24 02:54:45 +01:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* used only for debug */
|
2022-02-19 14:31:55 +01:00
|
|
|
#if 0
|
|
|
|
|
static void print_wires(void)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
int i,j;
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *ptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
for(i=0;i<NBOXES;i++) {
|
|
|
|
|
for(j=0;j<NBOXES;j++)
|
|
|
|
|
{
|
|
|
|
|
dbg(1, "print_wires(): %4d%4d :\n",i,j);
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr=xctx->wire_spatial_table[i][j];
|
2020-08-08 15:47:34 +02:00
|
|
|
while(ptr)
|
|
|
|
|
{
|
|
|
|
|
dbg(1, "print_wires(): %6d\n", ptr->n);
|
|
|
|
|
ptr=ptr->next;
|
|
|
|
|
}
|
|
|
|
|
dbg(1, "print_wires(): \n");
|
|
|
|
|
}
|
|
|
|
|
}
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr=xctx->wire_spatial_table[0][1];
|
2020-08-08 15:47:34 +02:00
|
|
|
while(ptr)
|
|
|
|
|
{
|
|
|
|
|
select_wire(ptr->n,SELECTED, 1);
|
|
|
|
|
rebuild_selected_array();
|
|
|
|
|
ptr=ptr->next;
|
|
|
|
|
}
|
|
|
|
|
draw();
|
|
|
|
|
}
|
2022-02-19 14:31:55 +01:00
|
|
|
#endif
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
static void signal_short( char *n1, char *n2)
|
|
|
|
|
{
|
|
|
|
|
char str[2048];
|
|
|
|
|
if( n1 && n2 && strcmp( n1, n2) )
|
|
|
|
|
{
|
|
|
|
|
my_snprintf(str, S(str), "shorted: %s - %s", n1, n2);
|
|
|
|
|
dbg(1, "signal_short(): signal_short: shorted: %s - %s", n1, n2);
|
|
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2021-10-26 00:04:13 +02:00
|
|
|
if(!xctx->netlist_count) {
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_hilight_hash_lookup(n1, xctx->hilight_color, XINSERT);
|
2021-11-10 13:43:08 +01:00
|
|
|
if(tclgetboolvar("incr_hilight")) incr_hilight_color();
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_hilight_hash_lookup(n2, xctx->hilight_color, XINSERT);
|
2021-11-10 13:43:08 +01:00
|
|
|
if(tclgetboolvar("incr_hilight")) incr_hilight_color();
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-19 14:31:55 +01:00
|
|
|
static void wirecheck(int k) /* recursive routine */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
int tmpi,tmpj, counti,countj,i,j;
|
|
|
|
|
int touches;
|
|
|
|
|
double x1, y1, x2, y2;
|
|
|
|
|
int x1a, x2a, y1a, y2a;
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *ptr2;
|
2020-10-16 16:34:15 +02:00
|
|
|
xWire * const wire = xctx->wire;
|
2021-01-08 03:09:29 +01:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
x1=wire[k].x1;
|
|
|
|
|
x2=wire[k].x2;
|
|
|
|
|
y1=wire[k].y1;
|
|
|
|
|
y2=wire[k].y2;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* ordered bbox */
|
|
|
|
|
RECTORDER(x1, y1, x2, y2);
|
2020-10-16 16:34:15 +02:00
|
|
|
/* calculate square 4 1st bbox point of wire[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x1a=(int)floor(x1/BOXSIZE) ;
|
|
|
|
|
y1a=(int)floor(y1/BOXSIZE) ;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/* calculate square 4 2nd bbox point of wire[k] */
|
2022-04-27 13:18:45 +02:00
|
|
|
x2a=(int)floor(x2/BOXSIZE);
|
|
|
|
|
y2a=(int)floor(y2/BOXSIZE);
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/*loop thru all squares that intersect bbox of wire[k] */
|
2020-08-08 15:47:34 +02:00
|
|
|
counti=0;
|
|
|
|
|
for(i=x1a; i<=x2a && counti < NBOXES; i++)
|
|
|
|
|
{
|
|
|
|
|
counti++;
|
|
|
|
|
tmpi=i%NBOXES; if(tmpi<0) tmpi+=NBOXES;
|
|
|
|
|
countj=0;
|
|
|
|
|
for(j=y1a; j<=y2a && countj < NBOXES; j++)
|
|
|
|
|
{
|
|
|
|
|
countj++;
|
|
|
|
|
tmpj=j%NBOXES; if(tmpj<0) tmpj+=NBOXES;
|
2020-10-16 16:34:15 +02:00
|
|
|
/*check if wire[k] touches wires in square [tmpi, tmpj] */
|
2021-11-23 15:03:51 +01:00
|
|
|
ptr2=xctx->wire_spatial_table[tmpi][tmpj];
|
2020-08-08 15:47:34 +02:00
|
|
|
while(ptr2)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if(wire[ptr2->n].node) {ptr2=ptr2->next; continue;} /* 20171207 net already checked. Move on */
|
2020-08-08 15:47:34 +02:00
|
|
|
if(ptr2->n != k) { /* 20171204 avoid checking wire against itself */
|
2020-10-16 16:34:15 +02:00
|
|
|
touches = touch(wire[k].x1,wire[k].y1,wire[k].x2,wire[k].y2,
|
|
|
|
|
wire[ptr2->n].x1,wire[ptr2->n].y1) ||
|
|
|
|
|
touch(wire[k].x1,wire[k].y1,wire[k].x2,wire[k].y2,
|
|
|
|
|
wire[ptr2->n].x2,wire[ptr2->n].y2) ||
|
|
|
|
|
touch(wire[ptr2->n].x1,wire[ptr2->n].y1,wire[ptr2->n].x2,
|
|
|
|
|
wire[ptr2->n].y2, wire[k].x1,wire[k].y1) ||
|
|
|
|
|
touch(wire[ptr2->n].x1,wire[ptr2->n].y1,wire[ptr2->n].x2,
|
|
|
|
|
wire[ptr2->n].y2, wire[k].x2,wire[k].y2);
|
2020-08-08 15:47:34 +02:00
|
|
|
if( touches )
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(239, &wire[ptr2->n].node, wire[k].node);
|
|
|
|
|
my_strdup(240, &wire[ptr2->n].prop_ptr,
|
|
|
|
|
subst_token(wire[ptr2->n].prop_ptr, "lab", wire[ptr2->n].node));
|
2020-08-08 15:47:34 +02:00
|
|
|
wirecheck(ptr2->n); /* recursive check */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
ptr2=ptr2->next;
|
|
|
|
|
}
|
|
|
|
|
dbg(2, "wirecheck(): %d/%d\n", tmpi,tmpj );
|
|
|
|
|
}
|
|
|
|
|
dbg(2, "wirecheck(): \n");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-17 01:12:55 +01:00
|
|
|
void set_tcl_netlist_type(void)
|
|
|
|
|
{
|
2022-08-31 10:47:16 +02:00
|
|
|
if(xctx->netlist_type == CAD_SPICE_NETLIST) {
|
|
|
|
|
tclsetvar("netlist_type", "spice");
|
|
|
|
|
} else if(xctx->netlist_type == CAD_VERILOG_NETLIST) {
|
|
|
|
|
tclsetvar("netlist_type", "verilog");
|
|
|
|
|
} else if(xctx->netlist_type == CAD_VHDL_NETLIST) {
|
|
|
|
|
tclsetvar("netlist_type", "vhdl");
|
|
|
|
|
} else if(xctx->netlist_type == CAD_TEDAX_NETLIST) {
|
|
|
|
|
tclsetvar("netlist_type", "tedax");
|
|
|
|
|
} else if(xctx->netlist_type == CAD_SYMBOL_ATTRS) {
|
|
|
|
|
tclsetvar("netlist_type", "symbol");
|
|
|
|
|
} else {
|
|
|
|
|
tclsetvar("netlist_type", "unknown");
|
|
|
|
|
}
|
2021-11-17 01:12:55 +01:00
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* what==0 -> initialize */
|
|
|
|
|
/* what==1 -> get new node name, net## */
|
|
|
|
|
/* what==2 -> update multiplicity */
|
|
|
|
|
/* what==3 -> get node multiplicity */
|
|
|
|
|
int get_unnamed_node(int what, int mult,int node)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
dbg(2, "get_unnamed_node(): what=%d mult=%d node=%d\n", what, mult, node);
|
|
|
|
|
if (what==0) /* initialize unnamed node data structures */
|
|
|
|
|
{
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->new_node=0;
|
|
|
|
|
my_free(828, &xctx->node_mult);
|
|
|
|
|
xctx->node_mult_size=0;
|
2020-08-08 15:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else if (what==1) /* get a new unique unnamed node */
|
|
|
|
|
{
|
2020-12-06 02:10:53 +01:00
|
|
|
++xctx->new_node;
|
|
|
|
|
if (xctx->new_node>= xctx->node_mult_size) /* enlarge array and zero it */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->node_mult_size += CADCHUNKALLOC;
|
|
|
|
|
my_realloc(242, &xctx->node_mult, sizeof(int) * xctx->node_mult_size );
|
|
|
|
|
for (i=xctx->node_mult_size-CADCHUNKALLOC;i<xctx->node_mult_size;i++) xctx->node_mult[i]=0;
|
2022-10-06 11:48:22 +02:00
|
|
|
}
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->node_mult[xctx->new_node]=mult;
|
|
|
|
|
return xctx->new_node;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
else if(what==2) /* update node multiplicity if given mult is lower */
|
|
|
|
|
{
|
2020-12-06 02:10:53 +01:00
|
|
|
if (xctx->node_mult[node]==0) xctx->node_mult[node]=mult;
|
|
|
|
|
else if (mult<xctx->node_mult[node]) xctx->node_mult[node]=mult;
|
2020-08-08 15:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
else /* what=3 , return node multiplicity */
|
|
|
|
|
{
|
2020-12-06 02:10:53 +01:00
|
|
|
dbg(2, "get_unnamed_node(): returning mult=%d\n", xctx->node_mult[node]);
|
|
|
|
|
return xctx->node_mult[node];
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
/*------------ */
|
|
|
|
|
|
|
|
|
|
/* store list of global nodes (global=1 set in symbol props) to be printed in netlist 28032003 */
|
|
|
|
|
/* what: */
|
|
|
|
|
/* 0: print list of global nodes and delete list */
|
|
|
|
|
/* 1: add entry */
|
|
|
|
|
/* 2: delete list only, no print */
|
|
|
|
|
/* 3: look if node is a global */
|
|
|
|
|
int record_global_node(int what, FILE *fp, char *node)
|
|
|
|
|
{
|
2021-11-20 02:37:56 +01:00
|
|
|
static int max_globals=0; /* safe to keep even with multiple schematics, netlist code always resets data */
|
|
|
|
|
static int size_globals=0; /* safe to keep even with multiple schematics, netlist code always resets data */
|
|
|
|
|
static char **globals=NULL; /* safe to keep even with multiple schematics, netlist code always resets data */
|
2020-08-08 15:47:34 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if( what==1 || what==3) {
|
|
|
|
|
if(!node) return 0;
|
2020-10-12 13:13:31 +02:00
|
|
|
if(!strcmp(node, "0")) return 1;
|
2020-08-08 15:47:34 +02:00
|
|
|
for(i=0;i<max_globals;i++) {
|
|
|
|
|
if( !strcmp(node, globals[i] )) return 1; /* node is a global */
|
|
|
|
|
}
|
|
|
|
|
if(what == 3) return 0; /* node is not a global */
|
|
|
|
|
if(max_globals>=size_globals) {
|
|
|
|
|
size_globals+=CADCHUNKALLOC;
|
|
|
|
|
my_realloc(243, &globals, size_globals*sizeof(char *) );
|
|
|
|
|
}
|
|
|
|
|
globals[max_globals]=NULL;
|
|
|
|
|
my_strdup(244, &globals[max_globals], node);
|
|
|
|
|
max_globals++;
|
|
|
|
|
} else if(what == 0 || what == 2) {
|
|
|
|
|
for(i=0;i<max_globals;i++) {
|
2021-11-16 22:28:10 +01:00
|
|
|
if(what == 0 && xctx->netlist_type == CAD_SPICE_NETLIST) fprintf(fp, ".GLOBAL %s\n", globals[i]);
|
|
|
|
|
if(what == 0 && xctx->netlist_type == CAD_TEDAX_NETLIST) fprintf(fp, "__GLOBAL__ %s\n", globals[i]);
|
2020-08-08 15:47:34 +02:00
|
|
|
my_free(829, &globals[i]);
|
|
|
|
|
}
|
|
|
|
|
my_free(830, &globals);
|
|
|
|
|
size_globals=max_globals=0;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-04 12:34:09 +02:00
|
|
|
|
|
|
|
|
/* name nets that are attached to symbols with duplicated pins.
|
|
|
|
|
* if another duplicated pin is attached to a named net/label/pin get name from there */
|
2022-10-06 11:48:22 +02:00
|
|
|
static void name_pass_through_nets(int for_netlist)
|
2022-10-04 12:34:09 +02:00
|
|
|
{
|
2022-10-06 11:48:22 +02:00
|
|
|
int i, j, k, rects, rot, flip, sqx, sqy, changed = 0;
|
2022-10-04 12:34:09 +02:00
|
|
|
double x0, y0, rx1, ry1;
|
|
|
|
|
char *type = NULL, *type2 = NULL;
|
|
|
|
|
xRect *rct;
|
|
|
|
|
Wireentry *wptr;
|
|
|
|
|
Instpinentry *iptr;
|
|
|
|
|
xInstance * const inst = xctx->inst;
|
|
|
|
|
int const instances = xctx->instances;
|
2022-10-05 01:18:45 +02:00
|
|
|
Str_hashtable table = {NULL, 0};
|
2022-10-04 12:34:09 +02:00
|
|
|
Str_hashentry *entry;
|
2022-10-06 11:48:22 +02:00
|
|
|
int *symtable = NULL;
|
2022-10-04 12:34:09 +02:00
|
|
|
const char *pin_name;
|
2022-10-04 15:39:45 +02:00
|
|
|
int *pt_symbol = NULL; /* pass-through symbols, symbols with duplicated ports */
|
|
|
|
|
int there_are_pt = 0;
|
2022-10-06 11:48:22 +02:00
|
|
|
int lev = 1;
|
|
|
|
|
|
|
|
|
|
dbg(1, "name_pass_through_nets() start...\n");
|
2022-10-05 01:18:45 +02:00
|
|
|
pt_symbol = my_calloc(973, xctx->symbols, sizeof(int));
|
2022-10-06 11:48:22 +02:00
|
|
|
symtable = my_calloc(1581, xctx->symbols, sizeof(int));
|
|
|
|
|
/* we can not loop over xctx->symbols since we keep symbols of parent circuit while netlisting */
|
|
|
|
|
for(i = 0; i < xctx->instances; i++) {
|
|
|
|
|
k = xctx->inst[i].ptr;
|
|
|
|
|
if( k < 0 || symtable[k] ) continue;
|
|
|
|
|
symtable[k] =1;
|
|
|
|
|
dbg(lev, "name_pass_through_nets(): inst=%s sym=%s\n", xctx->inst[i].instname, xctx->sym[k].name);
|
|
|
|
|
|
2022-10-05 16:47:34 +02:00
|
|
|
str_hash_init(&table, 37);
|
2022-10-06 11:48:22 +02:00
|
|
|
for(j = 0; j < xctx->sym[k].rects[PINLAYER]; j++) {
|
|
|
|
|
const char *pin_name = get_tok_value(xctx->sym[k].rect[PINLAYER][j].prop_ptr, "name", 0);
|
2022-10-05 01:18:45 +02:00
|
|
|
entry = str_hash_lookup(&table, pin_name, "1", XINSERT_NOREPLACE);
|
2022-10-04 15:39:45 +02:00
|
|
|
if(entry) {
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(lev, " pass thru symbol found\n");
|
|
|
|
|
pt_symbol[k] = 1;
|
2022-10-04 15:39:45 +02:00
|
|
|
there_are_pt = 1;
|
2022-10-06 11:48:22 +02:00
|
|
|
break;
|
2022-10-04 15:39:45 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-10-05 01:18:45 +02:00
|
|
|
str_hash_free(&table);
|
2022-10-06 11:48:22 +02:00
|
|
|
if(pt_symbol[k]) dbg(1, "duplicated pins: %s\n", xctx->sym[i].name);
|
2022-10-04 15:39:45 +02:00
|
|
|
}
|
2022-10-06 11:48:22 +02:00
|
|
|
my_free(1582, &symtable);
|
2022-10-04 15:39:45 +02:00
|
|
|
if(!there_are_pt) { /* nothing to do: no pass through symbols */
|
|
|
|
|
my_free(1573, &pt_symbol);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2022-10-04 12:34:09 +02:00
|
|
|
do { /* keep looping until propagation of nets occurs */
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(lev, "name_pass_through_nets(): do loop\n");
|
2022-10-04 12:34:09 +02:00
|
|
|
changed = 0;
|
|
|
|
|
for (i=0;i<instances;i++) {
|
|
|
|
|
dbg(1, "instance %d: %s\n", i, inst[i].instname);
|
|
|
|
|
if(inst[i].ptr<0) continue;
|
2022-10-04 15:39:45 +02:00
|
|
|
if(!pt_symbol[ inst[i].ptr ]) continue;
|
2022-10-05 16:47:34 +02:00
|
|
|
str_hash_init(&table, 37);
|
2022-10-04 12:34:09 +02:00
|
|
|
my_strdup(1565, &type, (inst[i].ptr + xctx->sym)->type);
|
|
|
|
|
if (type && !IS_LABEL_OR_PIN(type) ) {
|
|
|
|
|
if ((rects = (inst[i].ptr+ xctx->sym)->rects[PINLAYER]) > 0) {
|
|
|
|
|
/* 1st loop: hash symbol pins that are attached to named nets/pins/labels */
|
|
|
|
|
for (j=0;j<rects;j++) {
|
|
|
|
|
rct=(inst[i].ptr+ xctx->sym)->rect[PINLAYER];
|
|
|
|
|
x0=(rct[j].x1+rct[j].x2)/2;
|
|
|
|
|
y0=(rct[j].y1+rct[j].y2)/2;
|
|
|
|
|
rot=inst[i].rot;
|
|
|
|
|
flip=inst[i].flip;
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
|
|
|
|
x0=inst[i].x0+rx1;
|
|
|
|
|
y0=inst[i].y0+ry1;
|
|
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
|
|
|
|
pin_name = get_tok_value(rct[j].prop_ptr, "name", 0);
|
|
|
|
|
/* find attached nets */
|
|
|
|
|
wptr = xctx->wire_spatial_table[sqx][sqy];
|
|
|
|
|
while(wptr) {
|
|
|
|
|
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
|
|
|
|
|
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0)) {
|
|
|
|
|
if(xctx->wire[wptr->n].node) {
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(1, "pin_name=%s, node=%s\n", pin_name, xctx->wire[wptr->n].node);
|
|
|
|
|
entry = str_hash_lookup(&table, pin_name, NULL, XLOOKUP);
|
|
|
|
|
if(entry) {
|
|
|
|
|
if(entry->value[0] != '#') {
|
|
|
|
|
if(xctx->wire[wptr->n].node[0] != '#') {
|
|
|
|
|
/* named net attached and another named net on duplicated pin -> check short */
|
|
|
|
|
if(for_netlist) signal_short(xctx->wire[wptr->n].node, entry->value);
|
|
|
|
|
}
|
|
|
|
|
} else { /* pin begins with '#' */
|
|
|
|
|
if(xctx->wire[wptr->n].node[0] != '#') {
|
|
|
|
|
/* named net has precedence over auto-named net */
|
|
|
|
|
str_hash_lookup(&table, pin_name, xctx->wire[wptr->n].node, XINSERT);
|
|
|
|
|
} else { /* pin and wire both begin with '#' */
|
|
|
|
|
int n, p;
|
|
|
|
|
sscanf(xctx->wire[wptr->n].node, "#net%d", &n);
|
|
|
|
|
sscanf(entry->value, "#net%d", &p);
|
|
|
|
|
if(n < p) { /* lower numbered #nets have precedence */
|
|
|
|
|
dbg(lev, "inst: %s pin %s <--- net %s\n",
|
|
|
|
|
inst[i].instname, entry->value, xctx->wire[wptr->n].node);
|
|
|
|
|
str_hash_lookup(&table, pin_name, xctx->wire[wptr->n].node, XINSERT);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
/* pin unconnected. Assign from net */
|
|
|
|
|
entry = str_hash_lookup(&table, pin_name, xctx->wire[wptr->n].node, XINSERT);
|
|
|
|
|
}
|
2022-10-04 12:34:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
wptr=wptr->next;
|
|
|
|
|
}
|
|
|
|
|
/* find attached pins/labels */
|
|
|
|
|
iptr=xctx->instpin_spatial_table[sqx][sqy];
|
|
|
|
|
while (iptr) {
|
|
|
|
|
if (iptr->n == i || inst[iptr->n].ptr < 0) {
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
my_strdup(1566, &type2, (inst[iptr->n].ptr + xctx->sym)->type);
|
|
|
|
|
if (!type2 || !IS_LABEL_OR_PIN(type2) ) {
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((iptr->x0==x0) && (iptr->y0==y0)) {
|
|
|
|
|
if(xctx->inst[iptr->n].node[0]) {
|
|
|
|
|
dbg(1, "pin_name=%s, node=%s\n", pin_name, xctx->inst[iptr->n].node[0]);
|
2022-10-06 11:48:22 +02:00
|
|
|
entry = str_hash_lookup(&table, pin_name, xctx->inst[iptr->n].node[0], XLOOKUP);
|
|
|
|
|
if(entry && entry->value[0] != '#') {
|
|
|
|
|
if(for_netlist) signal_short(xctx->inst[iptr->n].node[0], entry->value);
|
|
|
|
|
} else {
|
|
|
|
|
str_hash_lookup(&table, pin_name, xctx->inst[iptr->n].node[0], XINSERT);
|
|
|
|
|
}
|
2022-10-04 12:34:09 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
}
|
|
|
|
|
} /* for (j=0;j<rects;j++) */
|
|
|
|
|
/* 2nd loop: if unnamed nets, get name from duplicated pins */
|
|
|
|
|
for (j=0;j<rects;j++) {
|
|
|
|
|
rct=(inst[i].ptr+ xctx->sym)->rect[PINLAYER];
|
|
|
|
|
x0=(rct[j].x1+rct[j].x2)/2;
|
|
|
|
|
y0=(rct[j].y1+rct[j].y2)/2;
|
|
|
|
|
rot=inst[i].rot;
|
|
|
|
|
flip=inst[i].flip;
|
|
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
|
|
|
|
x0=inst[i].x0+rx1;
|
|
|
|
|
y0=inst[i].y0+ry1;
|
|
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
|
|
|
|
wptr = xctx->wire_spatial_table[sqx][sqy];
|
|
|
|
|
pin_name = get_tok_value(rct[j].prop_ptr, "name", 0);
|
|
|
|
|
while(wptr) {
|
2022-10-06 11:48:22 +02:00
|
|
|
int assign = 0;
|
2022-10-04 12:34:09 +02:00
|
|
|
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
|
|
|
|
|
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0)) {
|
2022-10-06 11:48:22 +02:00
|
|
|
entry = str_hash_lookup(&table, pin_name, NULL, XLOOKUP);
|
|
|
|
|
if(entry) {
|
|
|
|
|
if(xctx->wire[wptr->n].node) {
|
|
|
|
|
if(strcmp(xctx->wire[wptr->n].node, entry->value)) { /* net node name is different */
|
|
|
|
|
if(xctx->wire[wptr->n].node[0] == '#') { /* autonamed net */
|
|
|
|
|
if(entry->value[0] == '#') { /* autonamed pin */
|
|
|
|
|
int n, p;
|
|
|
|
|
sscanf(xctx->wire[wptr->n].node, "#net%d", &n);
|
|
|
|
|
sscanf(entry->value, "#net%d", &p);
|
|
|
|
|
dbg(lev, "2nd loop: net=%s pin=%s\n", xctx->wire[wptr->n].node, entry->value);
|
|
|
|
|
if(n > p) assign = 1; /* lower numbered #net names on pins have precedence */
|
|
|
|
|
} else { /* not autonamed pin */
|
|
|
|
|
assign = 1;
|
|
|
|
|
}
|
|
|
|
|
} else { /* not autonamed net */
|
|
|
|
|
if(entry->value[0] != '#') { /* not autonamed pin */
|
|
|
|
|
if(for_netlist) signal_short(xctx->wire[wptr->n].node, entry->value);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else { /* wire .node is NULL */
|
|
|
|
|
assign = 1;
|
|
|
|
|
}
|
2022-10-04 12:34:09 +02:00
|
|
|
}
|
2022-10-06 11:48:22 +02:00
|
|
|
|
|
|
|
|
if(assign) {
|
|
|
|
|
dbg(lev, "inst %s pin %s(%s) --> net %s\n",
|
|
|
|
|
inst[i].instname, entry->token, entry->value,
|
|
|
|
|
xctx->wire[wptr->n].node ? xctx->wire[wptr->n].node : "<NULL>");
|
|
|
|
|
my_strdup(1568, &xctx->wire[wptr->n].node, entry->value);
|
|
|
|
|
my_strdup(1569, &xctx->wire[wptr->n].prop_ptr,
|
|
|
|
|
subst_token(xctx->wire[wptr->n].prop_ptr, "lab", entry->value));
|
|
|
|
|
wirecheck(wptr->n);
|
|
|
|
|
changed = 1;
|
|
|
|
|
}
|
|
|
|
|
} /* if(touch...) */
|
2022-10-04 12:34:09 +02:00
|
|
|
wptr=wptr->next;
|
|
|
|
|
}
|
|
|
|
|
} /* for (j=0;j<rects;j++) */
|
|
|
|
|
} /* if ((rects = (inst[i].ptr+ xctx->sym)->rects[PINLAYER]) > 0) */
|
|
|
|
|
} /* if (type && !IS_LABEL_OR_PIN(type) ) */
|
2022-10-05 01:18:45 +02:00
|
|
|
str_hash_free(&table);
|
2022-10-04 12:34:09 +02:00
|
|
|
} /* for (i=0;i<instances;i++) */
|
|
|
|
|
} while(changed);
|
|
|
|
|
my_free(1570, &type);
|
|
|
|
|
my_free(1571, &type2);
|
2022-10-04 15:39:45 +02:00
|
|
|
my_free(1572, &pt_symbol);
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(lev, "name_pass_through_nets() end...\n");
|
2022-10-04 12:34:09 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
void prepare_netlist_structs(int for_netlist)
|
|
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
xRect *rct;
|
2020-08-08 15:47:34 +02:00
|
|
|
char tmp_str[30]; /* overflow safe */
|
|
|
|
|
char nn[PATH_MAX+30];
|
|
|
|
|
double x0, y0;
|
2020-12-05 03:16:01 +01:00
|
|
|
short rot = 0;
|
|
|
|
|
short flip = 0;
|
2020-08-08 15:47:34 +02:00
|
|
|
int sqx, sqy;
|
|
|
|
|
int port;
|
|
|
|
|
int touches=0;
|
|
|
|
|
int touches_unnamed=0;
|
|
|
|
|
double rx1,ry1;
|
2021-12-28 01:33:01 +01:00
|
|
|
Wireentry *wptr;
|
|
|
|
|
Instpinentry *iptr;
|
2020-08-08 15:47:34 +02:00
|
|
|
int i,j, rects, generic_rects;
|
|
|
|
|
char *dir=NULL;
|
|
|
|
|
char *type=NULL;
|
|
|
|
|
char *sig_type=NULL;
|
|
|
|
|
char *verilog_type=NULL;
|
|
|
|
|
char *value=NULL;
|
|
|
|
|
char *class=NULL;
|
|
|
|
|
char *global_node=NULL;
|
|
|
|
|
int inst_mult, pin_mult;
|
2020-10-06 16:19:52 +02:00
|
|
|
int print_erc;
|
2021-11-20 02:37:56 +01:00
|
|
|
static int startlevel = 0; /* safe to keep even with multiple schematic windows, netlist is not interruptable */
|
2020-10-16 16:34:15 +02:00
|
|
|
xInstance * const inst = xctx->inst;
|
|
|
|
|
int const instances = xctx->instances;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-12-02 15:10:47 +01:00
|
|
|
if (for_netlist>0 && xctx->prep_net_structs) return;
|
|
|
|
|
else if (!for_netlist && xctx->prep_hi_structs) return;
|
2020-10-18 23:58:40 +02:00
|
|
|
/* delete instance pins spatial hash, wires spatial hash, node_hash, wires and inst nodes.*/
|
2021-10-28 10:36:23 +02:00
|
|
|
delete_netlist_structs();
|
2021-10-27 22:56:33 +02:00
|
|
|
free_simdata(); /* invalidate simulation cache */
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(1, "prepare_netlist_structs(): extraction: %s\n", xctx->sch[xctx->currsch]);
|
2021-10-26 00:04:13 +02:00
|
|
|
if(xctx->netlist_count == 0 ) startlevel = xctx->currsch;
|
2021-11-20 02:37:56 +01:00
|
|
|
/* print_erc is 1 the first time prepare_netlist_structs() is called on top level while
|
|
|
|
|
* doing the netlist, when netlist of sub blocks is completed and toplevel is reloaded
|
|
|
|
|
* a second prepare_netlist_structs() is called to name unnamed nets, in this second call
|
|
|
|
|
* print_erc must be set to 0 to avoid double erc printing
|
|
|
|
|
*/
|
2021-12-02 13:28:40 +01:00
|
|
|
print_erc = (xctx->netlist_count == 0 || startlevel < xctx->currsch) && for_netlist;
|
|
|
|
|
if (for_netlist) {
|
2020-10-15 17:39:21 +02:00
|
|
|
my_snprintf(nn, S(nn), "-----------%s", xctx->sch[xctx->currsch]);
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(nn,2);
|
|
|
|
|
}
|
|
|
|
|
/* reset wire & inst node labels */
|
2022-10-04 12:34:09 +02:00
|
|
|
dbg(2, "prepare_netlist_structs(): rehashing wires and instance pins in spatial hash table\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
hash_wires();
|
2020-10-16 16:34:15 +02:00
|
|
|
for (i=0;i<instances;i++)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[i].ptr<0) continue;
|
2020-10-18 23:58:40 +02:00
|
|
|
/* delete_inst_node(i); */ /* done in delete_netlist_structs() */
|
2020-10-16 16:34:15 +02:00
|
|
|
rects=(inst[i].ptr+ xctx->sym)->rects[PINLAYER] +
|
|
|
|
|
(inst[i].ptr+ xctx->sym)->rects[GENERICLAYER];
|
2020-08-08 15:47:34 +02:00
|
|
|
if (rects > 0)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
inst[i].node = my_malloc(247, sizeof(char *) * rects);
|
2020-08-08 15:47:34 +02:00
|
|
|
for (j=0;j<rects;j++)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
inst[i].node[j]=NULL;
|
2021-12-07 20:40:33 +01:00
|
|
|
hash_inst_pin(for_netlist, XINSERT, i, j);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): naming pins from attrs\n");
|
2020-10-16 16:34:15 +02:00
|
|
|
for (i=0;i<instances;i++)
|
2020-10-12 13:13:31 +02:00
|
|
|
{
|
2020-08-08 15:47:34 +02:00
|
|
|
/* name ipin opin label node fields from prop_ptr attributes */
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[i].ptr<0) continue;
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(248, &type,(inst[i].ptr+ xctx->sym)->type);
|
|
|
|
|
if(print_erc && (!inst[i].instname || !inst[i].instname[0]) &&
|
|
|
|
|
!get_tok_value((inst[i].ptr+ xctx->sym)->templ, "name", 0)[0]
|
2020-10-15 01:43:53 +02:00
|
|
|
) {
|
2020-10-06 16:19:52 +02:00
|
|
|
char str[2048];
|
2020-10-15 19:20:55 +02:00
|
|
|
if( type &&
|
|
|
|
|
strcmp(type, "package") &&
|
2020-10-14 23:15:05 +02:00
|
|
|
strcmp(type, "port_attributes") &&
|
|
|
|
|
strcmp(type, "architecture") &&
|
|
|
|
|
strcmp(type, "arch_declarations") &&
|
|
|
|
|
strcmp(type, "attributes") &&
|
2020-11-24 02:54:45 +01:00
|
|
|
strcmp(type, "netlist_options") &&
|
2020-10-14 23:15:05 +02:00
|
|
|
strcmp(type, "use")) {
|
2020-10-16 16:34:15 +02:00
|
|
|
my_snprintf(str, S(str), "instance: %d (%s): no name attribute set", i, inst[i].name);
|
2020-10-14 23:15:05 +02:00
|
|
|
statusmsg(str,2);
|
2021-01-07 16:35:57 +01:00
|
|
|
inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-10-14 23:15:05 +02:00
|
|
|
}
|
2020-10-06 16:19:52 +02:00
|
|
|
}
|
|
|
|
|
if(print_erc && (!type || !type[0]) ) {
|
|
|
|
|
char str[2048];
|
2020-11-29 00:00:55 +01:00
|
|
|
my_snprintf(str, S(str), "Symbol: %s: no type attribute set", inst[i].name);
|
2020-10-06 16:19:52 +02:00
|
|
|
statusmsg(str,2);
|
2021-01-07 16:35:57 +01:00
|
|
|
inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-10-06 16:19:52 +02:00
|
|
|
}
|
2020-10-16 16:34:15 +02:00
|
|
|
if(type && inst[i].node && IS_LABEL_OR_PIN(type) ) { /* instance must have a pin! */
|
2020-08-08 15:47:34 +02:00
|
|
|
if (for_netlist>0) {
|
|
|
|
|
/* 20150918 skip labels / pins if ignore property specified on instance */
|
2021-11-16 22:28:10 +01:00
|
|
|
if( xctx->netlist_type == CAD_VERILOG_NETLIST &&
|
2020-10-16 16:34:15 +02:00
|
|
|
strcmp(get_tok_value(inst[i].prop_ptr,"verilog_ignore",0),"true")==0 ) continue;
|
2021-11-16 22:28:10 +01:00
|
|
|
if( xctx->netlist_type == CAD_SPICE_NETLIST &&
|
2020-10-16 16:34:15 +02:00
|
|
|
strcmp(get_tok_value(inst[i].prop_ptr,"spice_ignore",0),"true")==0 ) continue;
|
2021-11-16 22:28:10 +01:00
|
|
|
if( xctx->netlist_type == CAD_VHDL_NETLIST &&
|
2020-10-16 16:34:15 +02:00
|
|
|
strcmp(get_tok_value(inst[i].prop_ptr,"vhdl_ignore",0),"true")==0 ) continue;
|
2021-11-16 22:28:10 +01:00
|
|
|
if( xctx->netlist_type == CAD_TEDAX_NETLIST &&
|
2020-10-16 16:34:15 +02:00
|
|
|
strcmp(get_tok_value(inst[i].prop_ptr,"tedax_ignore",0),"true")==0 ) continue;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
port=0;
|
|
|
|
|
if (strcmp(type,"label")) { /* instance is a port (not a label) */
|
2020-10-12 13:13:31 +02:00
|
|
|
port=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
/* 20071204 only define a dir property if instance is not a label */
|
|
|
|
|
if (!for_netlist) my_strdup(249, &dir, "");
|
|
|
|
|
else
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(250, &dir, get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][0].prop_ptr, "dir",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* handle global nodes (global=1 set as symbol property) 28032003 */
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(251, &global_node,get_tok_value((inst[i].ptr+ xctx->sym)->prop_ptr,"global",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
/*20071204 if instance is a label dont define a dir property for more precise erc checking */
|
|
|
|
|
my_strdup(252, &dir,"none");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!dir) my_strdup(253, &dir,"none"); /* 20100422, define dir if not alrerady defined by */
|
|
|
|
|
/* previous code, to avoid nasty segfaults if pins not correctly defined */
|
|
|
|
|
|
|
|
|
|
/* obtain ipin/opin/label signal type (default: std_logic) */
|
|
|
|
|
if (!for_netlist) {
|
|
|
|
|
my_free(831, &sig_type);
|
|
|
|
|
my_free(832, &verilog_type);
|
|
|
|
|
my_free(833, &value);
|
|
|
|
|
my_free(834, &class);
|
|
|
|
|
} else {
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(258, &sig_type,get_tok_value(inst[i].prop_ptr,"sig_type",0));
|
|
|
|
|
my_strdup(259, &verilog_type,get_tok_value(inst[i].prop_ptr,"verilog_type",0));
|
2020-11-29 01:59:17 +01:00
|
|
|
my_strdup(260, &value,get_tok_value(inst[i].prop_ptr,"value",0));
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(261, &class,get_tok_value(inst[i].prop_ptr,"class",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-12-19 03:22:38 +01:00
|
|
|
my_strdup(262, &inst[i].node[0], inst[i].lab);
|
2020-10-16 16:34:15 +02:00
|
|
|
if (!(inst[i].node[0])) {
|
2020-11-29 00:00:55 +01:00
|
|
|
my_strdup(65, &inst[i].node[0], get_tok_value((inst[i].ptr+ xctx->sym)->templ, "lab",0));
|
2020-11-16 02:25:43 +01:00
|
|
|
dbg(1, "prepare_netlist_structs(): no lab attr on instance, pick from symbol: %s\n", inst[i].node[0]);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
/* handle global nodes (global=1 set as symbol property) 28032003 */
|
|
|
|
|
if (!strcmp(type,"label") && global_node && !strcmp(global_node, "true")) {
|
2020-10-16 16:34:15 +02:00
|
|
|
dbg(1, "prepare_netlist_structs(): global node: %s\n",inst[i].node[0]);
|
|
|
|
|
record_global_node(1,NULL, inst[i].node[0]);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* do not count multiple labels/pins with same name */
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[0], /* insert node in hash table */
|
2020-08-08 15:47:34 +02:00
|
|
|
dir, XINSERT, port, sig_type, verilog_type, value, class);
|
|
|
|
|
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): pin=%s\n",
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][0].prop_ptr, "name",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "prepare_netlist_structs(): dir=%s\n",
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][0].prop_ptr, "dir",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* name nets that touch ioin opin alias instances */
|
2020-10-16 16:34:15 +02:00
|
|
|
rct=(inst[i].ptr+ xctx->sym)->rect[PINLAYER];
|
2020-10-12 13:13:31 +02:00
|
|
|
x0=(rct[0].x1+rct[0].x2)/2;
|
|
|
|
|
y0=(rct[0].y1+rct[0].y2)/2;
|
2020-10-16 16:34:15 +02:00
|
|
|
rot=inst[i].rot;
|
|
|
|
|
flip=inst[i].flip;
|
2020-11-03 12:10:55 +01:00
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
2020-10-16 16:34:15 +02:00
|
|
|
x0=inst[i].x0+rx1;
|
|
|
|
|
y0=inst[i].y0+ry1;
|
2020-08-08 15:47:34 +02:00
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
2021-11-23 15:03:51 +01:00
|
|
|
wptr=xctx->wire_spatial_table[sqx][sqy];
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[i].node[0]) while(wptr)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
|
|
|
|
|
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
/* short circuit check */
|
2020-10-16 16:34:15 +02:00
|
|
|
if (for_netlist>0) signal_short(xctx->wire[wptr->n].node, inst[i].node[0]);
|
|
|
|
|
my_strdup(263, &xctx->wire[wptr->n].node, inst[i].node[0]);
|
2020-10-15 17:39:21 +02:00
|
|
|
my_strdup(264, &xctx->wire[wptr->n].prop_ptr,
|
|
|
|
|
subst_token(xctx->wire[wptr->n].prop_ptr, "lab", xctx->wire[wptr->n].node));
|
2020-08-08 15:47:34 +02:00
|
|
|
wirecheck(wptr->n);
|
|
|
|
|
}
|
|
|
|
|
wptr=wptr->next;
|
|
|
|
|
}
|
|
|
|
|
} /* if(type && ... */
|
2020-10-16 16:34:15 +02:00
|
|
|
} /* for(i=0;i<instances... */
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2022-08-19 10:56:26 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* name nets that do not touch ipin opin alias instances */
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): naming nets that dont touch labels\n");
|
|
|
|
|
get_unnamed_node(0,0,0); /*initializes node multiplicity data struct */
|
2020-10-15 17:39:21 +02:00
|
|
|
for (i=0;i<xctx->wires;i++)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
if(xctx->wire[i].node == NULL)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
my_snprintf(tmp_str, S(tmp_str), "#net%d", get_unnamed_node(1,0,0));
|
|
|
|
|
|
|
|
|
|
/* JL avoid autonamed nets clash with user defined 'net#' names */
|
2021-11-23 15:03:51 +01:00
|
|
|
while (bus_node_hash_lookup(&tmp_str[1], "", XLOOKUP, 0, "", "", "", "")!=NULL)
|
2020-08-08 15:47:34 +02:00
|
|
|
my_snprintf(tmp_str, S(tmp_str), "#net%d", get_unnamed_node(1, 0, 0));
|
|
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
my_strdup(265, &xctx->wire[i].node , tmp_str);
|
|
|
|
|
my_strdup(266, &xctx->wire[i].prop_ptr,
|
|
|
|
|
subst_token(xctx->wire[i].prop_ptr, "lab", xctx->wire[i].node));
|
2020-12-02 15:10:47 +01:00
|
|
|
/* insert unnamed wire name in hash table */
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(xctx->wire[i].node,"", XINSERT, 0,"","","","");
|
2020-08-08 15:47:34 +02:00
|
|
|
wirecheck(i);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-06 11:48:22 +02:00
|
|
|
name_pass_through_nets(for_netlist); /* name nets that are attached to symbols with duplicated pins. */
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* NAME GENERICS */
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* name generic pins from attached labels */
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): naming generics from attached labels\n");
|
2020-10-16 16:34:15 +02:00
|
|
|
if(for_netlist) for (i=0;i<instances;i++) { /* ... assign node fields on all (non label) instances */
|
|
|
|
|
if (inst[i].ptr<0) continue;
|
|
|
|
|
my_strdup(267, &type,(inst[i].ptr+ xctx->sym)->type);
|
2020-10-04 19:53:09 +02:00
|
|
|
if (type && !IS_LABEL_OR_PIN(type) ) {
|
2020-10-16 16:34:15 +02:00
|
|
|
if ((generic_rects = (inst[i].ptr+ xctx->sym)->rects[GENERICLAYER]) > 0)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
rects = (inst[i].ptr+ xctx->sym)->rects[PINLAYER];
|
2020-08-08 15:47:34 +02:00
|
|
|
for (j=rects;j<rects+generic_rects;j++)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[i].node[j]) continue; /* already named node */
|
|
|
|
|
rct=(inst[i].ptr+ xctx->sym)->rect[GENERICLAYER];
|
2020-10-12 13:13:31 +02:00
|
|
|
x0=(rct[j-rects].x1+rct[j-rects].x2)/2;
|
|
|
|
|
y0=(rct[j-rects].y1+rct[j-rects].y2)/2;
|
2020-10-16 16:34:15 +02:00
|
|
|
rot=inst[i].rot;
|
|
|
|
|
flip=inst[i].flip;
|
2020-11-03 12:10:55 +01:00
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
2020-10-16 16:34:15 +02:00
|
|
|
x0=inst[i].x0+rx1;
|
|
|
|
|
y0=inst[i].y0+ry1;
|
2020-08-08 15:47:34 +02:00
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
|
|
|
|
|
2021-11-23 15:03:51 +01:00
|
|
|
iptr=xctx->instpin_spatial_table[sqx][sqy];
|
2020-08-08 15:47:34 +02:00
|
|
|
while (iptr)
|
|
|
|
|
{
|
|
|
|
|
if (iptr->n == i)
|
|
|
|
|
{
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((iptr->x0==x0) && (iptr->y0==y0))
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if ((inst[iptr->n].ptr+ xctx->sym)->type && inst[iptr->n].node[iptr->pin] != NULL &&
|
|
|
|
|
!strcmp((inst[iptr->n].ptr+ xctx->sym)->type, "label"))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
dbg(2, "prepare_netlist_structs(): naming generic %s\n",
|
2020-10-16 16:34:15 +02:00
|
|
|
inst[iptr->n].node[iptr->pin]);
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-11-29 01:59:17 +01:00
|
|
|
my_strdup(268, &inst[i].node[j], get_tok_value(inst[iptr->n].prop_ptr,"value",0) );
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
/*my_strdup(269, &inst[i].node[j], inst[iptr->n].node[iptr->pin] ); */
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
if (!for_netlist) {
|
|
|
|
|
my_strdup(270, &sig_type,"");
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[iptr->n].node[iptr->pin],"none",
|
2020-08-08 15:47:34 +02:00
|
|
|
XINSERT, 1, sig_type,"", "","");
|
|
|
|
|
} else {
|
|
|
|
|
my_strdup(271, &sig_type,get_tok_value(
|
2020-10-16 16:34:15 +02:00
|
|
|
(inst[i].ptr+ xctx->sym)->rect[GENERICLAYER][j-rects].prop_ptr, "sig_type",0));
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* insert generic label in hash table as a port so it will not */
|
|
|
|
|
/* be declared as a signal in the vhdl netlist. this is a workaround */
|
|
|
|
|
/* that should be fixed 25092001 */
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[iptr->n].node[iptr->pin],
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value((inst[i].ptr+ xctx->sym)->rect[GENERICLAYER][j-rects].prop_ptr, "dir",0),
|
2020-08-08 15:47:34 +02:00
|
|
|
XINSERT, 1, sig_type,"", "","");
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-10-16 16:34:15 +02:00
|
|
|
} /* end if(inst[iptr->n].node[iptr->pin] != NULL) */
|
2020-08-08 15:47:34 +02:00
|
|
|
} /* end if( (iptr->x0==x0) && (iptr->y0==y0) ) */
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
}
|
|
|
|
|
} /* end for(j=0;j<rects;j++) */
|
|
|
|
|
} /* end if( rects=...>0) */
|
|
|
|
|
} /* end if(type not a label nor pin)... */
|
|
|
|
|
} /* end for(i...) */
|
|
|
|
|
|
|
|
|
|
/* END NAME GENERICS */
|
|
|
|
|
|
|
|
|
|
/* name instance pins of non (label,pin) instances */
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): assigning node names on instance pins\n");
|
2020-10-16 16:34:15 +02:00
|
|
|
for (i=0;i<instances;i++) /* ... assign node fields on all (non label) instances */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if(inst[i].ptr<0) continue;
|
|
|
|
|
expandlabel(inst[i].instname, &inst_mult);
|
|
|
|
|
my_strdup(272, &type,(inst[i].ptr+ xctx->sym)->type);
|
2020-10-04 19:53:09 +02:00
|
|
|
if (type && !IS_LABEL_OR_PIN(type) ) {
|
2020-10-16 16:34:15 +02:00
|
|
|
if ((rects = (inst[i].ptr+ xctx->sym)->rects[PINLAYER]) > 0)
|
2020-10-12 13:13:31 +02:00
|
|
|
{
|
2020-08-08 15:47:34 +02:00
|
|
|
for (j=0;j<rects;j++)
|
|
|
|
|
{
|
|
|
|
|
touches=0;
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[i].node[j]) continue; /* already named node */
|
|
|
|
|
rct=(inst[i].ptr+ xctx->sym)->rect[PINLAYER];
|
2020-10-12 13:13:31 +02:00
|
|
|
x0=(rct[j].x1+rct[j].x2)/2;
|
|
|
|
|
y0=(rct[j].y1+rct[j].y2)/2;
|
2020-10-16 16:34:15 +02:00
|
|
|
rot=inst[i].rot;
|
|
|
|
|
flip=inst[i].flip;
|
2020-11-03 12:10:55 +01:00
|
|
|
ROTATION(rot, flip, 0.0,0.0,x0,y0,rx1,ry1);
|
2020-10-16 16:34:15 +02:00
|
|
|
x0=inst[i].x0+rx1;
|
|
|
|
|
y0=inst[i].y0+ry1;
|
2020-08-08 15:47:34 +02:00
|
|
|
get_square(x0, y0, &sqx, &sqy);
|
|
|
|
|
/* name instance nodes that touch named nets */
|
2021-11-23 15:03:51 +01:00
|
|
|
wptr=xctx->wire_spatial_table[sqx][sqy];
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "prepare_netlist_structs(): from attached nets\n");
|
|
|
|
|
while (wptr)
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
if (touch(xctx->wire[wptr->n].x1, xctx->wire[wptr->n].y1,
|
|
|
|
|
xctx->wire[wptr->n].x2, xctx->wire[wptr->n].y2, x0,y0))
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
/* short circuit check */
|
|
|
|
|
if (touches)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if (for_netlist>0) signal_short(inst[i].node[j], xctx->wire[wptr->n].node);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
if (!touches)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(273, &inst[i].node[j], xctx->wire[wptr->n].node );
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[j],
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr, "dir",0),
|
2020-08-08 15:47:34 +02:00
|
|
|
XINSERT, 0,"","","","");
|
2020-10-12 13:13:31 +02:00
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
if (xctx->wire[wptr->n].node[0]=='#') /* unnamed node, update its multiplicity */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
expandlabel(get_tok_value(
|
2020-10-16 16:34:15 +02:00
|
|
|
(inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr,"name",0),&pin_mult);
|
2020-08-08 15:47:34 +02:00
|
|
|
|
2020-10-16 16:34:15 +02:00
|
|
|
get_unnamed_node(2, pin_mult * inst_mult, atoi((inst[i].node[j])+4) );
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
} /* end if(!touches) */
|
|
|
|
|
touches=1;
|
|
|
|
|
}
|
|
|
|
|
wptr=wptr->next;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(2, "prepare_netlist_structs(): from other instances\n");
|
|
|
|
|
touches_unnamed=0;
|
2021-11-23 15:03:51 +01:00
|
|
|
iptr=xctx->instpin_spatial_table[sqx][sqy];
|
2020-08-08 15:47:34 +02:00
|
|
|
while (iptr)
|
|
|
|
|
{
|
|
|
|
|
if (iptr->n == i)
|
|
|
|
|
{
|
|
|
|
|
iptr=iptr->next;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if ((iptr->x0==x0) && (iptr->y0==y0))
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if (inst[iptr->n].node[iptr->pin] != NULL)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
/* short circuit check */
|
|
|
|
|
if (touches)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
if (for_netlist>0) signal_short(inst[i].node[j], inst[iptr->n].node[iptr->pin]);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
if (!touches)
|
|
|
|
|
{
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(274, &inst[i].node[j], inst[iptr->n].node[iptr->pin] );
|
2020-08-08 15:47:34 +02:00
|
|
|
if (!for_netlist) {
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[j],"none", XINSERT, 0,"","","","");
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[j],
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr, "dir",0),
|
2020-08-08 15:47:34 +02:00
|
|
|
XINSERT, 0,"","","","");
|
|
|
|
|
}
|
2020-10-16 16:34:15 +02:00
|
|
|
if ((inst[i].node[j])[0] == '#')
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
expandlabel(get_tok_value(
|
2020-10-16 16:34:15 +02:00
|
|
|
(inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr,"name",0),&pin_mult );
|
2020-08-08 15:47:34 +02:00
|
|
|
/* done at beginning of for(i) loop 20171210 */
|
|
|
|
|
/* expandlabel(get_tok_value( */
|
2020-10-16 16:34:15 +02:00
|
|
|
/* inst[i].prop_ptr,"name",0), &inst_mult); */
|
|
|
|
|
get_unnamed_node(2, pin_mult * inst_mult, atoi((inst[i].node[j])+4));
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
touches=1;
|
2020-10-16 16:34:15 +02:00
|
|
|
} /* end if(inst[iptr->n].node[iptr->pin] != NULL) */
|
2020-08-08 15:47:34 +02:00
|
|
|
else /* touches instance with unnamed pins */
|
|
|
|
|
{
|
|
|
|
|
touches_unnamed=1;
|
|
|
|
|
}
|
|
|
|
|
} /* end if( (iptr->x0==x0) && (iptr->y0==y0) ) */
|
|
|
|
|
iptr=iptr->next;
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
|
|
|
|
|
/* pin did not touch named pins or nets so we name it now */
|
|
|
|
|
dbg(2, "prepare_netlist_structs(): naming the other pins\n");
|
2022-01-11 14:40:43 +01:00
|
|
|
if (!touches) { /* pin does not touch any other instance pin with non NULL node[] field ...*/
|
|
|
|
|
if (touches_unnamed) /* ... but touches some other instance pin, so create unnamed net */
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
expandlabel(get_tok_value(
|
2020-10-16 16:34:15 +02:00
|
|
|
(inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr,"name",0), &pin_mult);
|
2020-08-08 15:47:34 +02:00
|
|
|
/* done at beginning of for(i) loop 20171210 */
|
|
|
|
|
/* expandlabel(get_tok_value( */
|
2020-10-16 16:34:15 +02:00
|
|
|
/* inst[i].prop_ptr,"name",0), &inst_mult); */
|
2020-08-08 15:47:34 +02:00
|
|
|
my_snprintf( tmp_str, S(tmp_str), "#net%d", get_unnamed_node(1, pin_mult * inst_mult, 0));
|
2020-10-16 16:34:15 +02:00
|
|
|
my_strdup(275, &inst[i].node[j], tmp_str );
|
2020-08-08 15:47:34 +02:00
|
|
|
if (!for_netlist) {
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[j],"none", XINSERT, 0,"","","","");
|
2020-08-08 15:47:34 +02:00
|
|
|
} else {
|
2021-11-23 15:03:51 +01:00
|
|
|
bus_node_hash_lookup(inst[i].node[j],
|
2020-10-16 16:34:15 +02:00
|
|
|
get_tok_value( (inst[i].ptr+ xctx->sym)->rect[PINLAYER][j].prop_ptr, "dir",0),
|
2020-08-08 15:47:34 +02:00
|
|
|
XINSERT, 0,"","","","");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} /* end for(j=0;j<rects;j++) */
|
|
|
|
|
} /* end if( rects=...>0) */
|
|
|
|
|
} /* end if(type not a label nor pin)... */
|
|
|
|
|
} /* end for(i...) */
|
|
|
|
|
/*---------------------- */
|
|
|
|
|
rebuild_selected_array();
|
2020-10-06 16:19:52 +02:00
|
|
|
if (for_netlist>0) {
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_net_structs=1;
|
|
|
|
|
xctx->prep_hi_structs=1;
|
|
|
|
|
} else xctx->prep_hi_structs=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
my_free(835, &dir);
|
|
|
|
|
my_free(836, &type);
|
|
|
|
|
my_free(837, &sig_type);
|
|
|
|
|
my_free(838, &verilog_type);
|
|
|
|
|
my_free(839, &value);
|
|
|
|
|
my_free(840, &class);
|
|
|
|
|
my_free(841, &global_node);
|
2022-10-06 11:48:22 +02:00
|
|
|
dbg(1, "prepare_netlist_structs(): returning\n");
|
2021-12-05 01:34:19 +01:00
|
|
|
/* avoid below call: it in turn calls prepare_netlist_structs(), too many side effects */
|
|
|
|
|
/* propagate_hilights(1, 0, XINSERT_NOREPLACE);*/
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
|
2022-09-27 18:35:42 +02:00
|
|
|
int warning_overlapped_symbols(int sel)
|
2022-08-19 10:56:26 +02:00
|
|
|
{
|
|
|
|
|
int i;
|
2022-10-05 01:18:45 +02:00
|
|
|
Int_hashtable table = {NULL, 0};
|
2022-08-19 10:56:26 +02:00
|
|
|
Int_hashentry *found;
|
|
|
|
|
char str[2048];
|
2022-08-19 12:46:35 +02:00
|
|
|
char s[512];
|
2022-08-19 10:56:26 +02:00
|
|
|
|
2022-10-05 01:18:45 +02:00
|
|
|
int_hash_init(&table, HASHSIZE);
|
2022-08-19 10:56:26 +02:00
|
|
|
for(i = 0; i < xctx->instances; i++) {
|
|
|
|
|
dbg(1, "instance:%s: %s\n", xctx->inst[i].instname, xctx->inst[i].name);
|
2022-08-19 12:46:35 +02:00
|
|
|
my_snprintf(s, S(s), "%g %g %g %g",
|
|
|
|
|
xctx->inst[i].xx1, xctx->inst[i].yy1, xctx->inst[i].xx2, xctx->inst[i].yy2);
|
|
|
|
|
|
|
|
|
|
dbg(1, " bbox: %g %g %g %g\n", xctx->inst[i].xx1, xctx->inst[i].yy1, xctx->inst[i].xx2, xctx->inst[i].yy2);
|
|
|
|
|
dbg(1, " s=%s\n", s);
|
2022-10-05 01:18:45 +02:00
|
|
|
found = int_hash_lookup(&table, s, i, XINSERT_NOREPLACE);
|
2022-08-19 10:56:26 +02:00
|
|
|
if(found) {
|
2022-09-27 18:35:42 +02:00
|
|
|
if(sel == 0) {
|
|
|
|
|
xctx->inst[i].color = -PINLAYER;
|
|
|
|
|
xctx->hilight_nets=1;
|
|
|
|
|
} else {
|
|
|
|
|
xctx->inst[i].sel = SELECTED;
|
|
|
|
|
xctx->need_reb_sel_arr = 1;
|
|
|
|
|
}
|
2022-08-19 12:46:35 +02:00
|
|
|
my_snprintf(str, S(str), "Warning: overlapped instance found: %s(%s) -> %s\n",
|
|
|
|
|
xctx->inst[i].instname, xctx->inst[i].name, xctx->inst[found->value].instname);
|
2022-08-19 10:56:26 +02:00
|
|
|
statusmsg(str,2);
|
|
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-10-05 01:18:45 +02:00
|
|
|
int_hash_free(&table);
|
2022-09-27 18:35:42 +02:00
|
|
|
if(sel && xctx->need_reb_sel_arr) rebuild_selected_array();
|
2022-08-19 10:56:26 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-08 15:47:34 +02:00
|
|
|
int sym_vs_sch_pins()
|
|
|
|
|
{
|
|
|
|
|
char **lab_array =NULL;
|
|
|
|
|
int lab_array_size = 0;
|
2020-12-01 13:43:15 +01:00
|
|
|
int i, j, k, symbol, n_syms, rects, pin_cnt=0, pin_match, mult;
|
2020-08-08 15:47:34 +02:00
|
|
|
struct stat buf;
|
|
|
|
|
char name[PATH_MAX];
|
|
|
|
|
char *type = NULL;
|
|
|
|
|
char *tmp = NULL;
|
|
|
|
|
char *lab=NULL;
|
|
|
|
|
char *pin_name=NULL;
|
|
|
|
|
char *pin_dir=NULL;
|
|
|
|
|
double tmpd;
|
|
|
|
|
FILE *fd;
|
|
|
|
|
int tmpi;
|
2020-12-05 03:16:01 +01:00
|
|
|
short tmps;
|
2020-08-08 15:47:34 +02:00
|
|
|
int endfile;
|
|
|
|
|
char tag[1];
|
|
|
|
|
char filename[PATH_MAX];
|
2020-10-15 17:39:21 +02:00
|
|
|
n_syms = xctx->symbols;
|
2020-08-08 15:47:34 +02:00
|
|
|
for(i=0;i<n_syms;i++)
|
|
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
if( xctx->sym[i].type && !strcmp(xctx->sym[i].type,"subcircuit")) {
|
|
|
|
|
rects = xctx->sym[i].rects[PINLAYER];
|
2021-06-17 00:25:39 +02:00
|
|
|
|
2022-06-23 13:42:56 +02:00
|
|
|
get_sch_from_sym(filename, xctx->sym + i);
|
2020-08-08 15:47:34 +02:00
|
|
|
if(!stat(filename, &buf)) {
|
|
|
|
|
fd = fopen(filename, "r");
|
|
|
|
|
pin_cnt = 0;
|
|
|
|
|
endfile = 0;
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->file_version[0] = '\0';
|
2020-08-08 15:47:34 +02:00
|
|
|
while(!endfile) {
|
|
|
|
|
if(fscanf(fd," %c",tag)==EOF) break;
|
|
|
|
|
switch(tag[0]) {
|
|
|
|
|
case 'v':
|
2020-10-15 17:39:21 +02:00
|
|
|
load_ascii_string(&xctx->version_string, fd);
|
|
|
|
|
my_snprintf(xctx->file_version, S(xctx->file_version), "%s",
|
|
|
|
|
get_tok_value(xctx->version_string, "file_version", 0));
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'E':
|
|
|
|
|
case 'S':
|
|
|
|
|
case 'V':
|
|
|
|
|
case 'K':
|
|
|
|
|
case 'G':
|
|
|
|
|
load_ascii_string(&tmp, fd);
|
|
|
|
|
break;
|
2022-01-14 14:56:13 +01:00
|
|
|
case '#':
|
|
|
|
|
read_line(fd, 1);
|
|
|
|
|
break;
|
2022-01-16 12:42:55 +01:00
|
|
|
case 'F': /* extension for future symbol floater labels */
|
|
|
|
|
read_line(fd, 1);
|
|
|
|
|
break;
|
2020-08-08 15:47:34 +02:00
|
|
|
case 'L':
|
|
|
|
|
case 'B':
|
2021-01-10 16:11:34 +01:00
|
|
|
if(fscanf(fd, "%d",&tmpi)< 1) {
|
|
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for LINE/BOX object, ignoring\n");
|
|
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
case 'N':
|
|
|
|
|
if(fscanf(fd, "%lf %lf %lf %lf ",&tmpd, &tmpd, &tmpd, &tmpd) < 4) {
|
2021-01-10 16:11:34 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for LINE/BOX object, ignoring\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
load_ascii_string(&tmp, fd);
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
if(fscanf(fd, "%d %d",&tmpi, &tmpi)<2) {
|
2021-01-10 16:11:34 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for POLYGON object, ignoring.\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
for(j=0;j<tmpi;j++) {
|
|
|
|
|
if(fscanf(fd, "%lf %lf ",&tmpd, &tmpd)<2) {
|
2021-01-10 16:11:34 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for POLYGON points, ignoring.\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
load_ascii_string( &tmp, fd);
|
|
|
|
|
break;
|
|
|
|
|
case 'A':
|
2021-10-27 10:12:16 +02:00
|
|
|
if(fscanf(fd, "%d",&tmpi)< 1) {
|
|
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for ARC object, ignoring\n");
|
|
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
if(fscanf(fd, "%lf %lf %lf %lf %lf ",&tmpd, &tmpd, &tmpd, &tmpd, &tmpd) < 5) {
|
2021-01-10 16:11:34 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for ARC object, ignoring\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
load_ascii_string(&tmp, fd);
|
|
|
|
|
break;
|
|
|
|
|
case 'T':
|
|
|
|
|
load_ascii_string(&tmp,fd);
|
2020-12-05 03:16:01 +01:00
|
|
|
if(fscanf(fd, "%lf %lf %hd %hd %lf %lf ", &tmpd, &tmpd, &tmps, &tmps, &tmpd, &tmpd) < 6 ) {
|
2021-01-10 16:11:34 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins(): WARNING: missing fields for TEXT object, ignoring\n");
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
load_ascii_string(&tmp,fd);
|
|
|
|
|
break;
|
|
|
|
|
case 'C':
|
|
|
|
|
load_ascii_string(&tmp, fd);
|
|
|
|
|
my_strncpy(name, tmp, S(name));
|
|
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
if(!strcmp(xctx->file_version,"1.0") ) {
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(1, "sym_vs_sch_pins(): add_ext(name,\".sym\") = %s\n", add_ext(name, ".sym") );
|
|
|
|
|
my_strncpy(name, add_ext(name, ".sym"), S(name));
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 03:16:01 +01:00
|
|
|
if(fscanf(fd, "%lf %lf %hd %hd", &tmpd, &tmpd, &tmps, &tmps) < 4) {
|
2020-12-02 15:10:47 +01:00
|
|
|
fprintf(errfp,"sym_vs_sch_pins() WARNING: missing fields for INST object, filename=%s\n",
|
|
|
|
|
filename);
|
2020-08-08 15:47:34 +02:00
|
|
|
read_line(fd, 0);
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
load_ascii_string(&tmp,fd);
|
|
|
|
|
symbol = match_symbol(name);
|
2020-10-15 17:39:21 +02:00
|
|
|
my_strdup(276, &type, xctx->sym[symbol].type);
|
2020-10-12 13:13:31 +02:00
|
|
|
if(type && IS_PIN(type)) {
|
2020-12-01 13:43:15 +01:00
|
|
|
my_strdup(292, &lab, expandlabel(get_tok_value(tmp, "lab", 0), &mult));
|
2020-08-08 15:47:34 +02:00
|
|
|
if(pin_cnt >= lab_array_size) {
|
|
|
|
|
lab_array_size += CADCHUNKALLOC;
|
|
|
|
|
my_realloc(154, &lab_array, lab_array_size * sizeof(char *));
|
|
|
|
|
}
|
|
|
|
|
lab_array[pin_cnt] = NULL;
|
2020-10-12 13:13:31 +02:00
|
|
|
my_strdup(155, &(lab_array[pin_cnt]), lab);
|
2020-08-08 15:47:34 +02:00
|
|
|
pin_cnt++;
|
|
|
|
|
pin_match = 0;
|
|
|
|
|
for(j=0; j < rects; j++) {
|
2020-12-01 13:43:15 +01:00
|
|
|
my_strdup(293, &pin_name,
|
|
|
|
|
expandlabel(get_tok_value(xctx->sym[i].rect[PINLAYER][j].prop_ptr, "name", 0), &mult));
|
2020-10-15 17:39:21 +02:00
|
|
|
my_strdup(294, &pin_dir, get_tok_value(xctx->sym[i].rect[PINLAYER][j].prop_ptr, "dir", 0));
|
2020-08-08 15:47:34 +02:00
|
|
|
if( pin_name && !strcmp(pin_name, lab)) {
|
|
|
|
|
if(!(
|
|
|
|
|
( !strcmp(type, "ipin") && !strcmp(pin_dir, "in") ) ||
|
|
|
|
|
( !strcmp(type, "opin") && !strcmp(pin_dir, "out") ) ||
|
|
|
|
|
( !strcmp(type, "iopin") && !strcmp(pin_dir, "inout") )
|
|
|
|
|
)
|
|
|
|
|
) {
|
|
|
|
|
char str[2048];
|
2021-05-31 07:39:23 +02:00
|
|
|
my_snprintf(str, S(str), "Symbol %s: Unmatched subcircuit schematic pin direction: %s",
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->sym[i].name, lab);
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(str,2);
|
|
|
|
|
my_snprintf(str, S(str), " %s <--> %s", type, pin_dir);
|
|
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2020-10-15 17:39:21 +02:00
|
|
|
for(j = 0; j < xctx->instances; j++) {
|
2022-02-04 02:56:11 +01:00
|
|
|
if(!xctx->x_strcmp(xctx->inst[j].name, xctx->sym[i].name)) {
|
2021-01-07 16:35:57 +01:00
|
|
|
xctx->inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
pin_match++;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!pin_match) {
|
|
|
|
|
char str[2048];
|
|
|
|
|
/* fprintf(errfp, " unmatched sch / sym pin: %s\n", lab); */
|
2021-05-31 07:39:23 +02:00
|
|
|
my_snprintf(str, S(str), "Symbol %s: schematic pin: %s not in symbol", xctx->sym[i].name, lab);
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2020-10-15 17:39:21 +02:00
|
|
|
for(j = 0; j < xctx->instances; j++) {
|
2022-02-04 02:56:11 +01:00
|
|
|
if(!xctx->x_strcmp(xctx->inst[j].name, xctx->sym[i].name)) {
|
2021-01-07 16:35:57 +01:00
|
|
|
xctx->inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '[':
|
|
|
|
|
load_sym_def(name, fd);
|
|
|
|
|
break;
|
|
|
|
|
case ']':
|
|
|
|
|
read_line(fd, 0);
|
|
|
|
|
endfile=1;
|
|
|
|
|
break;
|
2020-10-12 13:13:31 +02:00
|
|
|
default:
|
2020-08-08 15:47:34 +02:00
|
|
|
if( tag[0] == '{' ) ungetc(tag[0], fd);
|
2020-09-26 01:15:33 +02:00
|
|
|
read_record(tag[0], fd, 0);
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
read_line(fd, 0); /* discard any remaining characters till (but not including) newline */
|
2020-10-15 17:39:21 +02:00
|
|
|
if(!xctx->file_version[0]) {
|
|
|
|
|
my_snprintf(xctx->file_version, S(xctx->file_version), "1.0");
|
|
|
|
|
dbg(1, "sym_vs_sch_pins(): no file_version, assuming file_version=%s\n", xctx->file_version);
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
} /* while(!endfile) */
|
|
|
|
|
fclose(fd);
|
|
|
|
|
if(pin_cnt != rects) {
|
|
|
|
|
char str[2048];
|
2021-05-31 07:39:23 +02:00
|
|
|
my_snprintf(str, S(str), "Symbol %s has %d pins, its schematic has %d pins",
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->sym[i].name, rects, pin_cnt);
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2020-10-15 17:39:21 +02:00
|
|
|
for(j = 0; j < xctx->instances; j++) {
|
2022-02-04 02:56:11 +01:00
|
|
|
if(!xctx->x_strcmp(xctx->inst[j].name, xctx->sym[i].name)) {
|
2021-01-07 16:35:57 +01:00
|
|
|
xctx->inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(j=0; j < rects; j++) {
|
2020-12-01 13:43:15 +01:00
|
|
|
my_strdup(295, &pin_name,
|
|
|
|
|
expandlabel(get_tok_value(xctx->sym[i].rect[PINLAYER][j].prop_ptr, "name", 0), &mult));
|
2020-08-08 15:47:34 +02:00
|
|
|
pin_match = 0;
|
|
|
|
|
for(k=0; k<pin_cnt; k++) {
|
|
|
|
|
if(pin_name && !strcmp(lab_array[k], pin_name)) {
|
2020-10-12 13:13:31 +02:00
|
|
|
pin_match++;
|
2020-08-08 15:47:34 +02:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(!pin_match) {
|
|
|
|
|
char str[2048];
|
|
|
|
|
/* fprintf(errfp, " unmatched sch / sym pin: %s\n", lab); */
|
2021-05-31 07:39:23 +02:00
|
|
|
my_snprintf(str, S(str), "Symbol %s: symbol pin: %s not in schematic",
|
2020-10-15 17:39:21 +02:00
|
|
|
xctx->sym[i].name, pin_name ? pin_name : "<NULL>");
|
2020-08-08 15:47:34 +02:00
|
|
|
statusmsg(str,2);
|
2022-01-06 22:38:00 +01:00
|
|
|
tcleval("show_infotext"); /* critical error: force ERC window showing */
|
2020-10-15 17:39:21 +02:00
|
|
|
for(k = 0; k < xctx->instances; k++) {
|
2022-02-04 02:56:11 +01:00
|
|
|
if(!xctx->x_strcmp(xctx->inst[k].name, xctx->sym[i].name)) {
|
2021-01-07 16:35:57 +01:00
|
|
|
xctx->inst[i].color = -PINLAYER;
|
2020-12-06 02:10:53 +01:00
|
|
|
xctx->hilight_nets=1;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if(lab_array_size) {
|
|
|
|
|
for(k=0;k<pin_cnt;k++) {
|
|
|
|
|
my_free(842, &(lab_array[k]));
|
|
|
|
|
}
|
|
|
|
|
my_free(843, &lab_array);
|
|
|
|
|
lab_array_size = 0;
|
|
|
|
|
pin_cnt=0;
|
|
|
|
|
}
|
|
|
|
|
} /* if( ... "subcircuit"... ) */
|
|
|
|
|
my_free(844, &type);
|
|
|
|
|
my_free(845, &tmp);
|
|
|
|
|
my_free(846, &lab);
|
|
|
|
|
my_free(847, &pin_name);
|
|
|
|
|
my_free(848, &pin_dir);
|
|
|
|
|
} /* for(i=0;i<n_syms;i++) */
|
|
|
|
|
|
2020-10-15 17:39:21 +02:00
|
|
|
while(xctx->symbols > n_syms) remove_symbol(xctx->symbols - 1);
|
2020-08-08 15:47:34 +02:00
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void delete_inst_node(int i)
|
|
|
|
|
{
|
|
|
|
|
int j, rects;
|
2021-11-23 01:14:49 +01:00
|
|
|
if( xctx->inst[i].ptr == -1 || !xctx->inst[i].node) return;
|
2020-10-15 17:39:21 +02:00
|
|
|
rects = (xctx->inst[i].ptr+ xctx->sym)->rects[PINLAYER] +
|
|
|
|
|
(xctx->inst[i].ptr+ xctx->sym)->rects[GENERICLAYER];
|
2020-08-08 15:47:34 +02:00
|
|
|
if( rects > 0 )
|
|
|
|
|
{
|
|
|
|
|
for(j=0;j< rects ;j++)
|
2020-10-15 17:39:21 +02:00
|
|
|
my_free(849, &xctx->inst[i].node[j]);
|
|
|
|
|
my_free(850, &xctx->inst[i].node );
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void delete_netlist_structs(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
/* erase node data structures */
|
|
|
|
|
dbg(1, "delete_netlist_structs(): begin erasing\n");
|
2020-10-15 17:39:21 +02:00
|
|
|
for(i=0;i<xctx->instances;i++)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
|
|
|
|
delete_inst_node(i);
|
|
|
|
|
}
|
2020-10-15 17:39:21 +02:00
|
|
|
for(i=0;i<xctx->wires;i++)
|
2020-08-08 15:47:34 +02:00
|
|
|
{
|
2020-10-15 17:39:21 +02:00
|
|
|
my_free(851, &xctx->wire[i].node);
|
2020-10-12 13:13:31 +02:00
|
|
|
}
|
2020-08-08 15:47:34 +02:00
|
|
|
/* erase inst and wire topological hash tables */
|
|
|
|
|
del_inst_pin_table();
|
2021-11-23 15:03:51 +01:00
|
|
|
node_hash_free();
|
2020-08-08 15:47:34 +02:00
|
|
|
dbg(1, "delete_netlist_structs(): end erasing\n");
|
2020-12-02 15:10:47 +01:00
|
|
|
xctx->prep_net_structs=0;
|
|
|
|
|
xctx->prep_hi_structs=0;
|
2020-08-08 15:47:34 +02:00
|
|
|
}
|