2 This file is part of the software library CADLIB written by Conrad Ziesler
3 Copyright 2003, Conrad Ziesler, all rights reserved.
5 *************************
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 /* netlist_lib.c, routines for building a library of netlists
27 /* the goal here is to be able to read/write a file composed of segments
28 each segment has a header describing
31 2. equation parameters to iterate through
33 4. output ports, output tokens
34 5. input ports, input tokens
35 6. spice format netlist block to be parsed by netlist_spice
37 we then maintain this library of each version of each gate
39 in addition we would like to procedurally add gates to our library.
40 (ie. automatically generate library from templates)
48 #include "netlist_lib.h"
49 #include "netlist_dev.h"
53 #ifndef STRIP_DEBUGGING
54 #define D(level,a) do { if(__debug_nlib__>(level)) a; } while(0)
61 /* add a new param, to a db */
62 int nlib_add_pm(nlib_t
*nlib
, int dbindex
, char *str
, float min
, float max
, int qty
)
70 db
=list_data(&(nlib
->db
),dbindex
);
71 if(db
==NULL
)assert(0);
73 template.index
=eqnl_find(&(db
->nl
->eqnl
),str
);
74 else template.index
=-1;
77 { fprintf(stderr
,"couldn't find parameter %s used in netlist, assuming ignoring\n",str
); return -1; }
79 index
=list_add(&(db
->params
),&template);
83 /* add a new io definition to a db */
84 int nlib_add_io(nlib_t
*nlib
, int dbindex
, nlibiol_t
*io
, int tokens
, int nodes
, int dig
, char **names
)
90 db
=list_data(&(nlib
->db
),dbindex
);
93 memset(&template,0,sizeof(template));
94 index
=list_add(&(io
->iol
),&template);
95 p
=list_data(&(io
->iol
),index
);
97 assert((nodes
<NLIBIO_MAXNODES
) && "Compile time node limit exceeded, change and recompile");
99 io
->qtokens
= (io
->qtokens
>0)?io
->qtokens
*tokens
: tokens
;
105 ni
=names_check(db
->nl
->names
,names
[i
]);
108 fprintf(stderr
,"NLIB: could not find i/o node %s in circuit\n",names
[i
]);
117 static void nlib_init_io(nlibiol_t
*io
)
120 list_init(&(io
->iol
),sizeof(nlibio_t
),LIST_UNITMODE
);
124 int nlib_db_netlist(nlib_t
*nlib
, int index
, netlist_t
*nl
)
127 db
=list_data(&(nlib
->db
),index
);
136 int nlib_new_db(nlib_t
*nlib
, char *str
)
139 nlibdb_t
template,*db
;
141 memset(&template,0,sizeof(template));
142 index
=list_add(&(nlib
->db
),&template);
143 names_add(nlib
->dbref
,index
,str
);
144 db
=list_data(&(nlib
->db
),index
);
145 list_init(&(db
->params
),sizeof(nlibpm_t
),LIST_DEFMODE
);
146 nlib_init_io(&(db
->in
));
147 nlib_init_io(&(db
->out
));
148 list_init(&(db
->refnodes
),sizeof(nlibrefnode_t
),LIST_UNITMODE
);
153 nlibfref_t
nlib_func_lookup(nlib_t
*nlib
, char *str
)
156 f
.index
=names_check(nlib
->funcnames
,str
);
160 /* fixme: should look up name of function in nlib->functions and
163 int nlib_db_func(nlib_t
*nlib
, int index
, char *str
)
166 db
=list_data(&(nlib
->db
),index
);
168 db
->map
=nlib_func_lookup(nlib
,str
);
172 /* makes empty function of specified variables */
173 nlibfunc_t
*nlib_new_func(nlib_t
*nlib
, char *str
, int qin
, int qout
,int p_delay
, int p_offset
, int p_cycle
)
177 fp
=malloc((l
=sizeof(nlibfunc_t
)+(sizeof(int)*qin
)));
183 fp
->p_offset
=p_offset
;
185 l
=list_add(&(nlib
->funcs
),&fp
);
186 names_add(nlib
->funcnames
,l
,str
);
189 /* specify one mapping */
190 void nlib_func_addmap(nlib_t
*nlib
, nlibfunc_t
*fp
, int in
, int out
)
193 assert(out
<fp
->qout
);
201 /* inits a nlib, call before any action on nlib */
202 int nlib_init(nlib_t
*nlib
)
204 list_init(&(nlib
->db
),sizeof(nlibdb_t
),LIST_DEFMODE
);
205 nlib
->dbref
=names_new();
206 list_init(&(nlib
->iodefs
),sizeof(nlibiodef_t
), LIST_DEFMODE
);
207 eqnl_init(&(nlib
->eqnl
));
208 list_init(&(nlib
->funcs
), sizeof(nlibfunc_t
*), LIST_DEFMODE
); /* list of pointers */
209 list_init(&(nlib
->flatdb
), sizeof(nlibflatdb_t
), LIST_DEFMODE
);
210 nlib
->funcnames
=names_new();
212 nlib
->vref
=names_new();
214 nlib
->eqn_mem
=eqn_mem_new();
218 void nlib_release_flatdb(nlib_t
*nlib
)
222 list_iterate(&(nlib
->flatdb
),i
,fdbp
)
224 list_empty(&(fdbp
->uservals
));
225 if(fdbp
->pvals
!=NULL
)free(fdbp
->pvals
);
228 list_empty(&(nlib
->flatdb
));
229 bitlist_free(nlib
->flags
);
233 void nlib_release_io(nlib_t
*nlib
, nlibiol_t
*io
)
235 list_empty(&(io
->iol
));
238 void nlib_release_db(nlib_t
*nlib
)
243 list_iterate(&(nlib
->db
),i
,dbp
)
245 if(dbp
->pvals
!=NULL
)free(dbp
->pvals
);
247 list_empty(&(dbp
->refnodes
));
248 list_empty(&(dbp
->params
));
249 nlib_release_io(nlib
,&(dbp
->in
));
250 nlib_release_io(nlib
,&(dbp
->out
));
251 netlist_free(dbp
->nl
);
254 list_empty(&(nlib
->db
));
255 names_free(nlib
->dbref
);
259 void nlib_release_funcs(nlib_t
*nlib
)
263 names_free(nlib
->funcnames
);
264 nlib
->funcnames
=NULL
;
265 list_iterate(&(nlib
->funcs
),i
,p
)
270 list_empty(&(nlib
->funcs
));
273 void nlib_release_refs(nlib_t
*nlib
)
275 names_free(nlib
->vref
);
280 void nlib_release_iodefs(nlib_t
*nlib
)
284 list_iterate(&(nlib
->iodefs
),i
,p
)
286 if(p
->encoding
!=NULL
)free(p
->encoding
);
289 list_empty(&(nlib
->iodefs
));
292 /* frees all data in nlib */
293 void nlib_release(nlib_t
*nlib
)
295 nlib_release_flatdb(nlib
);
296 nlib_release_db(nlib
);
297 nlib_release_refs(nlib
);
298 nlib_release_funcs(nlib
);
299 eqnl_free(&(nlib
->eqnl
));
300 nlib_release_iodefs(nlib
);
301 eqn_mem_free(nlib
->eqn_mem
);
307 /* post processing of db structure */
308 int nlib_db_fixup(nlib_t
*nlib
, nlibdb_t
*db
)
313 int l
=list_qty(&(db
->params
));
314 db
->pvals
=malloc((sizeof(float)*l
));
315 memset(db
->pvals
,0,sizeof(float)*l
);
316 list_shrink(&(db
->params
));
317 list_shrink(&(db
->refnodes
));
319 list_iterate(&(db
->params
),i
,p
)
321 if(0)fprintf(stderr
,"nlib_db_fixup: trying to define eqn: %i->%s (%p)\n",p
->index
,eqnl_lookup(&(db
->nl
->eqnl
),p
->index
),db
->pvals
+i
);
322 eqnl_define(&(db
->nl
->eqnl
),p
->index
,db
->pvals
+i
);
324 q
=eqnl_qty(&(db
->nl
->eqnl
));
326 /* setup equations in our reference nodes */
327 list_iterate(&(db
->refnodes
),i
,rnp
)
330 eqnl_depend(&(nlib
->eqnl
), rnp
->skew
[j
]);
337 /* step through library,
338 (in terms of param qty's, in order)
339 substitute in, and call client process function
340 for each instance of each cell
342 void nlib_process(nlib_process_t
*user
, int screened
)
345 nlib_t
*nlib
=user
->nlib
;
348 int li
[64]; /* max 64 parameters */
353 memset(li
,0,sizeof(li
));
354 memset(lq
,0,sizeof(lq
));
356 list_iterate(&(nlib
->db
),i
,dbp
)
359 list_iterate(&(dbp
->params
),j
,dbpm
)
363 dbp
->pvals
[j
]= dbpm
->min
;
368 fprintf(stderr
,"\n\nstarting db index %i\n",i
);
373 fprintf(stderr
,"iteration:");
375 fprintf(stderr
," (%i,%i)",li
[j
]+1,lq
[j
]);
376 fprintf(stderr
,"\n");
379 if(nlib_isdisabled(nlib
,lib_index
)!=1)
381 /* eval each parameters */
384 dbpm
=list_data(&(dbp
->params
),j
);
386 dbp
->pvals
[j
]=dbpm
->min
+
387 li
[j
]*(dbpm
->max
-dbpm
->min
)/dbpm
->qty
;
389 if(0)fprintf(stderr
,"setting %i (%p) val[%i]=%g\n",j
,dbp
->pvals
+j
,dbpm
->index
,dbp
->pvals
[j
]);
393 user
->lib_index
=lib_index
;
403 for(j
--;j
>=0;j
--) /* roll over rest of indices */
414 static void nlib_fixup_process(nlib_process_t
*user
)
420 void nlib_fixup(nlib_t
*nlib
)
425 eqnl_autodepend(&(nlib
->eqnl
));
426 eqnl_evaldep(&(nlib
->eqnl
));
427 if(nlib
->flags
!=NULL
) /* in case we were called multiple times */
428 bitlist_free(nlib
->flags
);
434 pr
.process
=nlib_fixup_process
;
436 nlib
->flags
=bitlist_new(count
+1);
440 /* this does the dirty work of updating configurable db netlists from flat db */
441 void nlib_doflat(nlib_t
*nlib
, int index
)
446 fdb
=list_data(&(nlib
->flatdb
),index
);
448 db
=list_data(&(nlib
->db
),fdb
->db_index
);
451 memcpy(db
->pvals
,fdb
->pvals
,sizeof(float)*fdb
->qvals
);
453 assert(fdb
->qvals
==0);
456 /* call this from user process for each gate we want to keep */
457 void *nlib_flat(nlib_process_t
*user
, int s_uservals
, int q_uservals
)
467 index
=list_nextz(&(nlib
->flatdb
));
468 fdb
=list_data(&(nlib
->flatdb
),index
);
469 fdb
->lib_index
=user
->lib_index
;
470 fdb
->db_index
=user
->db_index
;
471 db
=list_data(&(nlib
->db
),fdb
->db_index
);
473 fdb
->qvals
=list_qty(&(db
->params
));
475 list_init(&(fdb
->uservals
),s_uservals
,LIST_UNITMODE
);
476 list_hint(&(fdb
->uservals
),q_uservals
);
480 fdb
->pvals
=malloc(sizeof(float)*fdb
->qvals
);
481 assert(fdb
->pvals
!=NULL
);
482 memcpy(fdb
->pvals
,db
->pvals
,sizeof(float)*fdb
->qvals
);
484 else fdb
->pvals
=NULL
;
486 return list_block_next(&(fdb
->uservals
),q_uservals
);
490 void nlib_disable(nlib_t
*nlib
, int index
)
492 if(nlib
->flags
!=NULL
)
493 bitlist_set(nlib
->flags
,index
);
496 int nlib_isdisabled(nlib_t
*nlib
, int index
)
498 if(nlib
->flags
!=NULL
)
499 return bitlist_test(nlib
->flags
,index
);
504 static void nlib_o_spice_subckt_(nlib_t
*nlib
, int db_index
, int lib_index
, void * of_fp
)
514 dbp
=list_data(&(nlib
->db
),db_index
);
516 fprintf(of
,"\n.subckt sc%i", lib_index
);
518 /* reference nodes */
519 list_iterate(&(dbp
->refnodes
),i
,rnp
)
520 fprintf(of
," rn%i",rnp
->vrefi
);
523 list_iterate(&(dbp
->in
.iol
),i
,iop
)
524 for(j
=0;j
<iop
->qnodes
;j
++)
525 fprintf(of
," %i",iop
->nodes
[j
]+n_start
);
528 list_iterate(&(dbp
->out
.iol
),i
,iop
)
529 for(j
=0;j
<iop
->qnodes
;j
++)
530 fprintf(of
," on%i_%i",i
,j
);
534 /* call netlist_o_spice to output subckt netlist */
535 netlist_o_spice(of
, dbp
->nl
, n_start
);
537 /* add additional circuitry for output buffers */
538 list_iterate(&(dbp
->out
.iol
),i
,iop
)
539 for(j
=0;j
<iop
->qnodes
;j
++)
540 fprintf(of
,"Ez%i on%i_%i 0 VCVS PWL(1) %i 0 -10v,-10v 10v,10v\n",z_index
++,i
,j
, iop
->nodes
[j
]+n_start
);
542 /* add aditional circuitry for delay and rc of references */
544 list_iterate(&(dbp
->refnodes
),i
,rnp
)
546 float f
[4]={0.0, 0.0, 0.0, 0.0 };
551 ud
[j
]=(eqn_is_undefined(rnp
->skew
[j
])!=0);
552 f
[j
]=eqnl_eval(&(nlib
->eqnl
),rnp
->skew
[j
]);
555 if( ud
[RTdelay
] && ud
[RTrseries
] )
556 fprintf(of
,"rz%i rn%i %i 1e-3\n", z_index
++,rnp
->vrefi
,rnp
->devnodei
+n_start
);
558 else if (!ud
[RTdelay
] && ud
[RTrseries
])
559 fprintf(of
,"Ez%i %i 0 VCVS DELAY rn%i 0 TD=%g SCALE=1\n",
560 z_index
++, rnp
->devnodei
+n_start
, rnp
->vrefi
, f
[RTdelay
]
563 else if ( ud
[RTdelay
] && !ud
[RTrseries
])
564 fprintf(of
,"rz%i rn%i %i %g\n",z_index
++, rnp
->vrefi
, rnp
->devnodei
+n_start
, f
[RTrseries
]);
568 fprintf(of
,"dz%i rn%i rn%ia %g\nrz%i rn%ia %i %g\n",
569 z_index
, rnp
->vrefi
, rnp
->vrefi
, f
[RTdelay
],
570 z_index
+1, rnp
->vrefi
, rnp
->devnodei
+n_start
, f
[RTrseries
]
575 fprintf(of
,"cz%i %i 0 %g\n",z_index
++,rnp
->devnodei
+n_start
, f
[RTcshunt
] );
577 fprintf(of
,".ends sc%i\n",lib_index
);
582 void nlib_o_spice_refs(nlib_t
*nlib
, void * of_fp
)
587 for(i
=0;(p
=names_lookup(nlib
->vref
,i
))!=NULL
;i
++)
589 fprintf(of
,"*nref %s\n",p
);
594 static void nlib_o_spice_subckt_process(nlib_process_t
*user
)
595 { nlib_o_spice_subckt_(user
->nlib
,user
->db_index
,user
->lib_index
, user
->user
); }
597 void nlib_o_spice_subckts(nlib_t
*nlib
, void * of_fp
)
600 /* if we built a flat db, use it */
601 if(list_qty(&(nlib
->flatdb
))>0)
607 list_iterate(&(nlib
->flatdb
),i
,fdb
)
609 /* print header with some usefull info */
610 fprintf(of
,"****** index=%i db_index=%i lib_index=%i ***",
611 i
,fdb
->db_index
,fdb
->lib_index
613 list_iterate(&(fdb
->uservals
),j
,dp
)
614 fprintf(of
,"%s%g",((j
%5)==0)?"\n*** ":" ",*dp
);
617 nlib_doflat(nlib
,i
); /* update the netlist */
618 nlib_o_spice_subckt_(nlib
,fdb
->db_index
,fdb
->lib_index
, of
);
626 proc
.process
=nlib_o_spice_subckt_process
;
627 nlib_process(&proc
,1);
635 /************ TOFIX: NEED to add multiple input nodes
636 probably the easiest is to pass a list ptr of i_nodes
638 tree.c needs some helper function in netlist_lib.c which gives the number of inputs
639 a given gate needs, so it can figure out it's proper wiring topology.
640 perhaps we should allocate the list of input nodes within the flatdb structure
641 and then tree would only have to pass *which* node to change in the list?
642 or at the very least, tree.c won't have to allocate a bunch of random lists and keep them
650 /* output spice style subckt call, mapping i_node and o_node */
651 void nlib_o_spice_call(nlib_t
*nlib
, int index
, int i_node
, int o_node
, int *skt
, void * of_fp
)
662 fdb
=list_data(&(nlib
->flatdb
),index
);
664 db
=list_data(&(nlib
->db
),fdb
->db_index
);
667 fprintf(of
,"X%i ",(*skt
)++);
669 /* reference nodes */
670 list_iterate(&(db
->refnodes
),i
,rnp
)
671 fprintf(of
," %s",names_lookup(nlib
->vref
,rnp
->vrefi
));
673 if(i_node
==-1)sprintf(tmp
,"root");
674 else sprintf(tmp
,"n%i",i_node
);
676 /* input nodes, for multi-input gate, tie inputs together */
677 list_iterate(&(db
->in
.iol
),i
,iop
)
678 for(j
=0;j
<iop
->qnodes
;j
++)
679 fprintf(of
," %s_%i",tmp
,j
);
681 /* output nodes, for multi-output gate, tie outputs together */
682 list_iterate(&(db
->out
.iol
),i
,iop
)
683 for(j
=0;j
<iop
->qnodes
;j
++)
684 fprintf(of
," n%i_%i",o_node
,j
);
686 fprintf(of
," sc%i",fdb
->lib_index
);
688 fprintf(of
,"*nlib %i %i %i %i\n",i_node
,o_node
,fdb
->db_index
,index
);
691 void nlib_iface_release(nlib_iface_t
*iface
)
693 list_empty(&(iface
->icalls
));
694 list_empty(&(iface
->frefs
));
697 void nlib_iface_init(nlib_iface_t
*iface
, nlib_t
*nlib
)
699 memset(iface
->ref_map
,0,sizeof(iface
->ref_map
));
700 list_init(&(iface
->icalls
),sizeof(nlib_icall_t
),LIST_DEFMODE
);
701 list_init(&(iface
->frefs
),sizeof(nlib_ifref_t
),LIST_DEFMODE
);
706 nlib_ifref_t
*nlib_iface_getref(nlib_iface_t
*iface
, int id
)
709 assert(id
<NLIBref_max
);
711 rp
=list_data(&(iface
->frefs
),iface
->ref_map
[id
]);
716 static int nlib_digitize(float *vals
[], int digitize
, int tokens
[], nlib_iface_t
*iface
)
725 case 0: /* default */
728 case 1: /* delta v */
729 assert(vals
[0]!=NULL
);
730 assert(vals
[1]!=NULL
);
731 dv
=(*vals
[0])-(*vals
[1]);
732 if(dv
>(1e-3))token
=1;
733 if(dv
<(-1e-3)) token
=0;
736 assert(vals
[0]!=NULL
);
738 vss
=nlib_iface_getref(iface
,NLIBref_vss
)->val
[0];
739 vdd
=nlib_iface_getref(iface
,NLIBref_vdd
)->val
[0];
740 if((2*dv
)>(vdd
-vss
)) token
=1;
748 /* update tokens[phases] current phase is always tokens[0].. */
751 for(i
=(NLIB_MAXPHASES
-1);i
>=1;i
--)
752 tokens
[i
]=tokens
[i
-1];
758 int nlib_func_compute(nlibfunc_t
*map
, int input
)
761 if(input
<0)return -1;
762 assert(input
<map
->qin
);
763 return map
->map
[input
];
767 int nlib_icall_digitize(nlib_iface_t
*iface
, int calli
, int phase
)
771 nlibfunc_t
*fp
,**fpp
;
773 cd
=list_data(&(iface
->icalls
),calli
);
775 dp
=list_data(&(iface
->nlib
->db
),cd
->dbi
);
777 fpp
=list_data(&(iface
->nlib
->funcs
),dp
->map
.index
);
782 nlib_digitize(cd
->in
, cd
->idigitize
, cd
->itokens
, iface
);
783 nlib_digitize(cd
->out
, cd
->odigitize
, cd
->otokens
, iface
);
785 if(phase
> (fp
->p_delay
+fp
->p_offset
)) /* wait at least this long before checking valididy */
786 if( (phase
%fp
->p_cycle
)== (fp
->p_delay
%fp
->p_cycle
) ) /* are we on the correct phase */
788 cd
->ctoken
=nlib_func_compute(fp
,cd
->itokens
[(fp
->p_offset
%fp
->p_delay
)]);
789 if(cd
->ctoken
!=cd
->otokens
[0]) cd
->err
++;
795 void nlib_iface_phase(nlib_iface_t
*iface
)
801 list_iterate(&(iface
->icalls
),i
,cp
)
802 nlib_icall_digitize(iface
,i
,iface
->phase
);
805 int nlib_iface_do_call(nlib_iface_t
*iface
, int in
, int on
, int dbi
, int fdbi
)
807 nlib_t
*nlib
=iface
->nlib
;
815 db
=list_data(&(nlib
->db
),dbi
);
816 if(db
==NULL
)return 0;
818 z
=list_qty(&(iface
->icalls
));
819 cd
=list_next(&(iface
->icalls
));
824 for(j
=0;j
<NLIBIO_MAXNODES
;j
++)
829 for(j
=0;j
<NLIB_MAXPHASES
;j
++)
830 cd
->itokens
[j
]=cd
->otokens
[j
]=-1;
836 /*** lookup input nodes from tracefile interface *****/
839 sprintf(nn
,"n%i_",in
);
840 else sprintf(nn
,"root_");
844 iop
=list_data(&(db
->in
.iol
),0); /* only handle inverters right now */
846 for(j
=0;j
<iop
->qnodes
;j
++)
849 cd
->in
[j
]=iface
->lookup_node_f(iface
->user
, nn
);
851 fprintf(stderr
,"ERROR: did not find trace node %s\n",nn
);
853 cd
->idigitize
=iop
->digitize
;
855 /*** lookup output nodes from tracefile interface ****/
857 sprintf(nn
,"n%i_",on
);
860 iop
=list_data(&(db
->out
.iol
),0); /* only handle inverters right now */
862 for(j
=0;j
<iop
->qnodes
;j
++)
865 cd
->out
[j
]=iface
->lookup_node_f(iface
->user
, nn
);
867 fprintf(stderr
,"ERROR: did not find trace node %s\n",nn
);
869 cd
->odigitize
=iop
->digitize
;
874 int nlib_i_spice_calls(nlib_iface_t
*iface
, void * cktf_fp
)
884 memset(line
,0,sizeof(line
));
889 line
[sizeof(line
)-1]=0;
890 line
[sizeof(line
)-2]=0;
891 fgets(line
,sizeof(line
-2),cktf
);
893 while(i
>=0) { if(isspace(line
[i
])) line
[i
]=0; else break; i
--; }
895 if( ( line
[0]=='*') && (line
[1]=='n') && (line
[2]=='l') && (line
[3]=='i') && (line
[4]=='b') )
901 sscanf(line
+5," %i %i %i %i",&in
,&on
,&dbi
,&fdbi
);
902 if(fdbi
==-1)continue;
903 q
+=nlib_iface_do_call(iface
,in
,on
,dbi
,fdbi
);
907 if( (line
[0]=='*') && (line
[1]=='n') && (line
[2]=='r') && (line
[3]=='e') && (line
[4]=='f'))
909 if(line
[5]!=' ')continue;
910 memset(&ifref
,0,sizeof(ifref
));
912 for(i
=6;line
[i
]!=0;i
++)
914 if(isspace(line
[i
]))break;
915 ifref
.name
[i
-6]=line
[i
];
918 for(i
=0;i
<NLIB_MAXPHASES
;i
++) ifref
.vals
[i
]=0.0;
919 ifref
.val
=iface
->lookup_node_f(iface
->user
,ifref
.name
);
920 dbi
=list_add(&(iface
->frefs
),&ifref
);
921 /* this is all just a big consistancy check */
922 fdbi
=names_check(iface
->nlib
->vref
,ifref
.name
);
925 fprintf(stderr
,"FATAL ERROR: this database file does not seem to match given tracefile\n");
936 /* saving and restoring the flat db
938 these are non human readable formatted files because i am lazy
939 note: architecture float format and endianess dependence in user parameters
942 static char nlib_flatdb_ver
[]="NLIB_FLATDB_a";
944 int nlib_flatdb_write(nlib_t
*nlib
, void * file
)
949 fprintf(file
,"%s %i\n",nlib_flatdb_ver
,list_qty(&(nlib
->flatdb
)));
950 list_iterate(&(nlib
->flatdb
),i
,p
)
952 q
=list_sizeof(&(p
->uservals
))*list_qty(&(p
->uservals
));
953 c
=list_data(&(p
->uservals
),0);
954 fprintf(file
,"lib %i db %i qvals %i user %i %i\n",p
->lib_index
,p
->db_index
,p
->qvals
,
955 list_sizeof(&(p
->uservals
)),list_qty(&(p
->uservals
))
957 for(j
=0;j
<p
->qvals
;j
++)
958 fprintf(file
,"%e%c",p
->pvals
[j
],(j
==(p
->qvals
-1))?'\n':' ');
961 fprintf(file
,"%i%c",(int)c
[j
],(j
==(q
-1))?'\n':' ');
962 if(0)fprintf(stderr
,"%i ",c
[j
]);
965 fprintf(file
,"NLIB_FLATDB_END\n");
970 int nlib_flatdb_read(nlib_t
*nlib
, void * file_fp
)
975 int i
,j
,q
,qty
,p_qvals
,ua
,ub
,index
;
979 line
[sizeof(line
)-1]=0;
980 fgets(line
,sizeof(line
)-2,file
);
981 if(memcmp(line
,nlib_flatdb_ver
,strlen(nlib_flatdb_ver
))!=0)return -1;
982 qty
=atoi(line
+sizeof(nlib_flatdb_ver
));
984 list_hint(&(nlib
->flatdb
),qty
);
990 fgets(line
,sizeof(line
)-2,file
);
991 memset(&up
,0,sizeof(up
));
998 if(sscanf(line
,"lib %i db %i qvals %i user %i %i",&up
.lib_index
,&up
.db_index
,&p_qvals
,&ua
,&ub
)!=5)
999 { assert(0); continue; }
1000 index
=list_qty(&(nlib
->flatdb
));
1001 c
=nlib_flat(&up
,ua
,ub
);
1002 p
=list_data(&(nlib
->flatdb
),index
);
1004 assert(p_qvals
==p
->qvals
);
1006 fgets(line
,sizeof(line
)-2,file
);
1007 for(lp
=line
,j
=0;j
<p
->qvals
;j
++)
1010 while(isspace(lp
[0]))lp
++;
1011 if(sscanf(lp
,"%f",&f
)!=1)assert(0);
1012 while(!isspace(lp
[0]))lp
++;
1018 fgets(line
,sizeof(line
)-2,file
);
1020 for(lp
=line
,j
=0;j
<q
;j
++)
1023 while(isspace(lp
[0]))lp
++;
1024 if(sscanf(lp
,"%i",&x
)!=1)assert(0);
1025 while(!isspace(lp
[0]))lp
++;
1027 if(0)fprintf(stderr
,"%i ",c
[j
]);
1034 /* parse a library file format
1037 .reference=ref_name name=spice_name delay=time rseries=res cshunt=cap
1039 .input=encoding spice_name[0] .... spice_name_[qnodes-1]
1041 .output spice_nam.....
1043 .param=spice_name .min=xxx .max=xxx .qtysteps=xxx
1048 .encoding=encodingname .wires=number .tokens=number .digitize=methodname
1050 .digital=functionname
1051 0=0 1=0 0011=.. ... input_token = output_token
1057 # spice netlist format
1059 .end_section # end of spice netlist
1064 static tokenmap_t nlib_tokens
[]=NLIB_TOKENS
;
1066 /* assume nlib aready initted, this adds to it */
1067 int nlib_parse(nlib_t
*nlib
, scanner_t
*scan
)
1071 deck_t
*db_deck
=NULL
, *digital_deck
=NULL
;
1072 nlibiodef_t encoding_default
;
1073 nlibfunc_t
*digital_func
=NULL
;
1074 deck_t
*dplast
=NULL
;
1077 assert(nlib
->eqn_mem
!=NULL
);
1078 eqn_mem_push(nlib
->eqn_mem
);
1080 defs
=*scanner_def_spice();
1081 strcpy(defs
.line_stop
,".end_nlib");
1082 encoding_default
.encoding
="dual_rail";
1083 encoding_default
.wires
=2;
1084 encoding_default
.tokens
=2;
1085 encoding_default
.digitize
=0;
1086 scanner_sect_new(scan
,&defs
,nlib_tokens
);
1087 while(scanner_parse_line(scan
))
1092 if(scan
->sectp
!=NULL
)
1093 if(scan
->sectp
->dp
!=NULL
)
1094 if((cp
=scan
->sectp
->dp
->card
)!=NULL
)
1096 if(flag
&&(scan
->sectp
->dp
!=dplast
))
1098 dplast
=scan
->sectp
->dp
;
1099 scan
->errdeck
=dplast
;
1100 scan
->errcard
=dplast
->card
;
1101 if(0)scanner_debug_all(scan
,stderr
);
1110 int qtyin
=-1, qtyout
=-1, p_delay
=-1, p_offset
=-1, p_cycle
=-1;
1111 for(p
=cp
->next
;p
!=NULL
;p
=p
->next
)
1127 case Knlib_p_offset
:
1135 scan
->errdeck
=dplast
;
1136 parse_warn(scan
,"unknown word in function definition %s\n",p
->val
);
1141 if((qtyin
!=-1) && (qtyout
!=-1) && (p_delay
!=-1) && (p_offset
!=-1) && (p_cycle
!=-1))
1143 digital_deck
=scan
->sectp
->dp
;
1144 digital_func
=nlib_new_func(nlib
,cp
->val
, qtyin
, qtyout
, p_delay
,p_offset
,p_cycle
);
1148 parse_error(scan
,"mangled function definition");
1151 case Knlib_end_digital
:
1152 if((digital_deck
!=NULL
) && (digital_func
!=NULL
))
1155 for(dp
=digital_deck
->next
;dp
!=NULL
;dp
=dp
->next
)
1158 if(dp
==scan
->sectp
->dp
)break;
1159 for(p
=dp
->card
;p
!=NULL
;p
=p
->next
)
1161 unsigned int a
=0,b
=0;
1167 a
=parse_binary(&sp
);
1171 b
=parse_binary(&sp
);
1172 nlib_func_addmap(nlib
, digital_func
, a
, b
);
1174 else parse_warn(scan
,"ignoring mangled mapping %s=%s\n",cp
->str
,cp
->val
);
1176 else parse_warn(scan
,"ignoring mangled mapping %s=%s\n",cp
->str
,cp
->val
);
1181 parse_error(scan
,"mangled function definition");
1186 case Knlib_encoding
: /* io def */
1189 int tokens
=0, wires
=0, h_tokens
=0, h_wires
=0;
1190 char *digitize
=NULL
;
1192 for(p
=cp
->next
;p
!=NULL
;p
=p
->next
)
1194 D(20,fprintf(stderr
,"encoding: %s=[%s]\n",p
->str
,p
->val
));
1204 tokens
=atoi(p
->val
);
1207 case Knlib_digitize
:
1213 if( h_tokens
&& h_wires
&& (digitize
!=NULL
) )
1217 index
=list_add(&(nlib
->iodefs
),&encoding_default
);
1218 iop
=list_data(&(nlib
->iodefs
),index
);
1219 iop
->encoding
=strdup(cp
->val
);
1221 if(strcmp(digitize
,"deltav")==0)
1223 else if(strcmp(digitize
,"cmos")==0)
1230 D(20,fprintf(stderr
,"adding encoding %s, %i %i\n",cp
->val
,tokens
,wires
));
1235 parse_error(scan
,"mangled encoding line ");
1242 for(p
=cp
->next
;p
!=NULL
;p
=p
->next
)
1246 eqnl_add(&(nlib
->eqnl
),eqn_parse(p
->val
),p
->str
);
1255 db_index
=nlib_new_db(nlib
,cp
->val
);
1256 db_deck
=scan
->sectp
->dp
; /* store location in deck where netlist occured */
1259 parse_error(scan
,".netlist=name expected");
1265 nl
=netlist_devnew(netlist_parse_input(scan
,"spice",NULL
));
1268 if(1)netlist_release(nl
); /* release spice parse structures */
1269 /* why does it crash with this ???? */
1272 parse_error(scan
,".spice section must be preceded by .netlist section");
1275 case Knlib_end_netlist
:
1277 parse_error(scan
,".end netlist without .netlist");
1283 nlib_db_netlist(nlib
,db_index
,nl
);
1284 dbp
=list_data(&(nlib
->db
),db_index
);
1286 for(dp
=db_deck
;dp
!=NULL
;dp
=dp
->next
) /* walk through from db_deck to here */
1288 if(dp
->card
==NULL
)continue;
1299 float min
=0,max
=0,qty
=0,v
;
1300 int h_min
=0, h_max
=0, h_qty
=0;
1302 for(p
=cp
->next
;p
!=NULL
;p
=p
->next
)
1306 v
=parse_float(p
->val
);
1321 if(h_min
&&h_max
&&h_qty
)
1323 nlib_add_pm(nlib
,db_index
, cp
->val
, min
, max
, floorf(qty
));
1328 scan
->errcard
=dp
->card
;
1329 parse_error(scan
,"mangled param statement\n");
1337 char *names
[64]; /* max limit */
1340 int tokens
=0, wires
=0, digital
=0, h_stuff
=0;
1342 for(i
=0,p
=cp
->next
;(p
!=NULL
)&&(i
<64);p
=p
->next
,i
++)
1346 list_iterate(&(nlib
->iodefs
),i
,iop
)
1348 if(strcmp(cp
->val
,iop
->encoding
)==0)
1352 digital
=iop
->digitize
;
1354 if(0)fprintf(stderr
,"got stuff %s %i %i \n",cp
->val
,wires
,qnames
);
1358 if(h_stuff
&& (wires
==qnames
)&& (dbp
!=NULL
) )
1361 if(cp
->token
==Knlib_input
)
1362 nlib_add_io(nlib
,db_index
,&(dbp
->in
),tokens
,wires
,digital
,names
);
1363 if(cp
->token
==Knlib_output
)
1364 nlib_add_io(nlib
,db_index
,&(dbp
->out
),tokens
,wires
,digital
,names
);
1369 scan
->errcard
=dp
->card
;
1370 parse_error(scan
,"mangled input/output statement \n");
1372 case Knlib_function
:
1375 nlib_db_func(nlib
,db_index
,cp
->val
);
1378 parse_error(scan
,"mangled function line \n");
1381 case Knlib_reference
:
1385 char *str_name
=NULL
;
1386 eqn_t cshunt
,rseries
,delay
;
1387 int h_cshunt
=0, h_rseries
=0, h_delay
=0;
1388 int nl_index
=-1, top_index
=-1;
1390 for(p
=cp
->next
;p
!=NULL
;p
=p
->next
)
1399 cshunt
=eqn_parse(p
->val
);
1403 rseries
=eqn_parse(p
->val
);
1407 delay
=eqn_parse(p
->val
);
1413 parse_warn(scan
,"reference: unknown word %s\n",cp
->str
);
1417 nl_index
=netlist_findnode(dbp
->nl
,str_name
);
1424 top_index
=names_check(nlib
->vref
,cp
->val
);
1427 top_index
=nlib
->qvref
;
1428 names_add(nlib
->vref
,top_index
,cp
->val
);
1432 for(l
=0;l
<MAXSKEW_PARAMS
;l
++)
1433 rn
.skew
[l
]=eqn_empty();
1436 rn
.devnodei
=nl_index
;
1438 rn
.skew
[RTdelay
]=delay
;
1440 rn
.skew
[RTrseries
]=rseries
;
1442 rn
.skew
[RTcshunt
]=cshunt
;
1444 list_add(&(dbp
->refnodes
),&rn
);
1447 else { parse_warn(scan
,"reference netlist node %s not found, ignoring\n",str_name
); break; }
1449 parse_error(scan
,"mangled reference line cp=%s val=%s\n",cp
->str
,cp
->val
);
1455 case Knlib_end_netlist
:
1460 parse_warn(scan
,"ignoring unknown card %s\n",cp
->str
);
1465 nlib_db_fixup(nlib
,dbp
);
1476 /* check memory after parse */ free(malloc(32));
1478 if(eqn_mem_pop()!=nlib
->eqn_mem
)assert(0);
1479 return list_qty(&(nlib
->db
));