irsim-9.7.93/0000755000175000001440000000000012606133563011463 5ustar timusersirsim-9.7.93/VERSION0000644000175000001440000000000712606133561012526 0ustar timusers9.7.93 irsim-9.7.93/usersubckt/0000755000175000001440000000000011257631375013662 5ustar timusersirsim-9.7.93/usersubckt/dll.sim0000644000175000001440000000030110706367162015137 0ustar timusers| units: 100 tech: scmos x outClk inClk upDn flop x upDn inClk outClk outClk1 dll p outClk1 outClk_b Vdd 2 20 n outClk1 outClk_b Gnd 2 10 p outClk_b outClk Vdd 2 80 n outClk_b outClk Gnd 2 40 irsim-9.7.93/usersubckt/dll.c0000644000175000001440000000736710706367162014614 0ustar timusers/* a simple DLL simulation in irsim */ #include #include "subckt.h" uptr flop_init(); void flop_eval(); uptr dll_init(); void dll_eval(); #define DEBUG 0 #define dprintf if (DEBUG) lprintf static float flop_res[1] = {5000.0, 5000.0}; userSubCircuit subs[] = { { "flop", flop_eval, flop_init, 2, 1, flop_res}, { "dll", dll_eval, dll_init, 3, 0, NULL}, { NULL, NULL, NULL, 0, 0, NULL} }; /*--------------------------------------------------------------*/ /* Flip-flop internal state structure */ /*--------------------------------------------------------------*/ typedef struct _flopState { int prvClk; int Q; } flopState; /*--------------------------------------------------------------*/ /* Flip-flop initialization function */ /* Return pointer to internal structure for this instance */ /*--------------------------------------------------------------*/ uptr flop_init() { flopState *thisFlop = (flopState *)malloc(sizeof(flopState)); thisFlop->prvClk = HIGH; thisFlop->Q = X; return (uptr)thisFlop; } /*--------------------------------------------------------------*/ /* Flip-flop evaluation function */ /*--------------------------------------------------------------*/ void flop_eval(ins, outs, delay, data) char *ins, *outs; double *delay; uptr *data; { flopState *ff = (flopState *)data; if (ff->prvClk == LOW && ins[1] == HIGH) { dprintf("flop edge @ %.2fns\n", d2ns(cur_delta)); ff->Q = ins[0]; } delay[0] = 100.0; ff->prvClk = ins[1]; outs[0] = ff->Q; } /*--------------------------------------------------------------*/ /* DLL internal state structure */ /*--------------------------------------------------------------*/ typedef struct _dll_state { double chpmpV; /* the charge pump voltage */ int prvClk; } dll_state ; #define RAIL 3.3 /* rail of the charge pump 0 - 3.3 */ #define UDPULSE 2e-9 /* 2ns pulse */ #define CHPMP_I 100e-6 /* 100 uA chpmp current */ #define PMP_CAP 20e-12 /* 10 pf filter cap */ #define CHGPCKT (CHPMP_I * UDPULSE / PMP_CAP) /* charge packet */ /*--------------------------------------------------------------*/ /* DLL initialization function */ /* Return pointer to internal structure for this instance */ /*--------------------------------------------------------------*/ uptr dll_init() { dll_state *t = (dll_state *)malloc(sizeof(dll_state)); t->chpmpV = 0.0; t->prvClk = LOW; return (uptr)t; } #define DLY0 2800.0 /* 1.8ns start delay */ #define DLYSLOPE 1000.0 /* 1.0ns/V dline gain */ #define DLINE_TF(V) (DLY0 + DLYSLOPE * (V)) #define clkOut (out[0]) /*--------------------------------------------------------------*/ /* DLL evaluation function */ /* in[0] = up/!down */ /* in[1] = clock */ /* in[2] = clock output feedback */ /* out = no outputs defined. */ /*--------------------------------------------------------------*/ void dll_eval(in, out, delay, data) char *in, *out; double *delay; uptr *data; { dll_state *d = (dll_state *)data; char updn = in[0], clkIn = in[1], clkOutFb = in[2]; dprintf("dll called @ %.2fns voltage %lf\n", d2ns(cur_delta), d->chpmpV); dprintf("\t updn=%c clkin=%c clkOutFb=%c prevClk=%c\n", updn, clkIn, clkOutFb, d->prvClk); delay[0] = DLINE_TF(d->chpmpV); clkOut = clkIn; if (d->prvClk == LOW && clkOutFb == HIGH) { d->chpmpV += (updn == HIGH) ? CHGPCKT : -CHGPCKT ; dprintf("pumping %s @ %.2fns voltage %le\n", (updn == LOW) ? "up" : "dn", d2ns(cur_delta), d->chpmpV); } d->prvClk = clkOutFb; } /*--------------------------------------------------------------*/ /* End of Flip-flop and DLL example compiled-in library */ /*--------------------------------------------------------------*/ irsim-9.7.93/usersubckt/README0000644000175000001440000000207510706367162014544 0ustar timusersThis directory provides an example of how "black box" subcircuits work. The more involved example is in dll.c and is a dll simulation. To see what it does make irsim.user and then run it on dll.sim with dll.cmd. The edges of the two clocks should be aligned by the end of the simulation and the updn signal should be switching. The subcircuit is called by: x upDn inClk outClk outClk1 dll it means call the subcircuit dll (defined in dll.c) with inputs (upDn, inClk, outClk) and output (ouClk1). To create and compile a new subcircuit library, replace "user.c" in the Makefile with the source file containing the library initialization and evaluation routines. The files "dll.c" and "flop_mux.c" are provided as examples. Some caveats: 1. The output delay is always specified in picoseconds. 2. You might have to change the MAXARGS in sim.c to if you have way too many IO's. 3. The code in this directory is deprecated and has been replaced by the example code in directory "tclsubckt", which allows subcircuit libraries to be compiled and loaded independently of irsim. irsim-9.7.93/usersubckt/Makefile0000644000175000001440000000023510706367162015320 0ustar timusersMODULE = usersubckt IRSIMDIR = .. SRCS = subckt.c user.c include ${IRSIMDIR}/defs.mak CFLAGS += -I${IRSIMDIR}/base include ${IRSIMDIR}/rules.mak irsim-9.7.93/usersubckt/flop.cmd0000644000175000001440000000015210416553134015275 0ustar timusersstepsize 2 ana clk in out out2 clock clkb 1 1 1 0 0 0 1 1 1 0 0 0 clock in 0 0 1 1 1 0 0 0 0 0 0 0 c 10 irsim-9.7.93/usersubckt/flop.sim0000644000175000001440000000014710706367162015334 0ustar timusers| units: 100 tech: scmos x in clk out flop x out clk out2 flop p clkb clk Vdd 2 18 n clkb clk Gnd 2 9 irsim-9.7.93/usersubckt/dll.cmd0000644000175000001440000000007110416553134015110 0ustar timusersana inClk outClk* upDn clock inClk 0 1 stepsize 2 c 140 irsim-9.7.93/usersubckt/Depend0000644000175000001440000000014710416553134014776 0ustar timusersuser.o: user.c subckt.h subckt.o: subckt.c ../base/defs.h ../base/net.h ../base/globals.h \ subckt.h irsim-9.7.93/usersubckt/subckt.c0000644000175000001440000003316511133376236015324 0ustar timusers#include #include #include #ifdef TCL_IRSIM #include #endif #ifndef _DEFS_H #include "defs.h" #endif #ifndef _GLOBALS_H #include "globals.h" #endif #ifndef _NET_MACROS_H #include "net_macros.h" #endif #ifndef _SUBCKT_H #include "subckt.h" #endif #ifdef USER_SUBCKT typedef struct _Sub { userSubCircuit *subckt; /* subcircuit (possibly static) */ int inst; /* Number of instantiations */ #ifndef TCL_IRSIM struct _Sub *next; /* list of commands in bucket */ #endif } SubCircuit; extern userSubCircuit subs[]; extern tptr rd_tlist; #ifdef TCL_IRSIM extern Tcl_Interp *irsiminterp; /*----------------------------------------------*/ /* Tcl procedure characters representing states */ /*----------------------------------------------*/ static pot2ch[] = {'0', 'x', 'z', '1'}; /*------------------------------*/ /* Method 1: */ /* Make use of Tcl Hash tables */ /*------------------------------*/ Tcl_HashTable substbl; /* First add any C-compiled user subcircuits */ public void init_subs(userSubCircuit *subckts) { userSubCircuit *s; SubCircuit *sl; Tcl_HashEntry *he; int newptr; Tcl_InitHashTable(&substbl, TCL_STRING_KEYS); for (s = subckts; s->name != NULL; s++) { sl = (SubCircuit *)malloc(sizeof(SubCircuit)); sl->subckt = s; sl->inst = 0 ; he = Tcl_CreateHashEntry(&substbl, s->name, &newptr); Tcl_SetHashValue(he, (ClientData)sl); } } /* Instantiate a user subcircuit */ public userSubCircuit *subckt_instantiate(char *sname, int *inst, uptr *udatap) { int newptr, result; SubCircuit *sl; Tcl_HashEntry *he; Tcl_Obj *objv[1]; *udatap = NULL; /* placeholder, used only for procedures */ he = Tcl_CreateHashEntry(&substbl, sname, &newptr); sl = (SubCircuit *)Tcl_GetHashValue(he); if (sl != NULL) { sl->inst++; *inst = sl->inst; return sl->subckt; } /* We allow subcircuits to be defined as Tcl procedures. */ /* Two procedures need to be defined, given the name of the */ /* subcircuit plus "_eval" and "_init", respectively. The "_init" */ /* procedure must return a list containing: number of inputs, */ /* number of outputs, list of output pullup and pulldown */ /* resistances, and an object (Tcl_Obj *) containing any */ /* information required by the instance. */ objv[0] = Tcl_NewStringObj(sname, -1); Tcl_AppendToObj(objv[0], "_init", 5); result = Tcl_EvalObjv(irsiminterp, 1, objv, 0); if (result == TCL_OK) { int i, listlen, noutputs, ninputs; double dval; Tcl_Obj *elem, *rlist, *olist, *uobj; userSubCircuit *s; rlist = Tcl_GetObjResult(irsiminterp); result = Tcl_ListObjLength(irsiminterp, rlist, &listlen); if (result == TCL_OK && (listlen == 3 || listlen == 4)) { if (listlen == 4) result = Tcl_ListObjIndex(irsiminterp, rlist, 3, &uobj); else uobj = Tcl_NewListObj(0, NULL); *udatap = (uptr)uobj; Tcl_IncrRefCount(uobj); result = Tcl_ListObjIndex(irsiminterp, rlist, 0, &elem); result = Tcl_GetIntFromObj(irsiminterp, elem, &ninputs); if (result != TCL_OK) return NULL; result = Tcl_ListObjIndex(irsiminterp, rlist, 1, &elem); result = Tcl_GetIntFromObj(irsiminterp, elem, &noutputs); if (result != TCL_OK) return NULL; result = Tcl_ListObjIndex(irsiminterp, rlist, 2, &olist); result = Tcl_ListObjLength(irsiminterp, olist, &listlen); if (listlen != (noutputs * 2)) return NULL; /* Set up a new hash table record for this subcircuit */ sl = (SubCircuit *)malloc(sizeof(SubCircuit)); s = (userSubCircuit *)malloc(sizeof(userSubCircuit)); sl->inst = 1; sl->subckt = s; Tcl_SetHashValue(he, (ClientData)sl); s->name = strdup(sname); s->model = NULL; s->init = NULL; s->ninputs = ninputs; s->noutputs = noutputs; s->res = (float *)malloc(2 * noutputs * sizeof(float)); for (i = 0; i < (noutputs * 2); i++) { double dres; result = Tcl_ListObjIndex(irsiminterp, olist, i, &elem); result = Tcl_GetDoubleFromObj(irsiminterp, elem, &dres); if (dres <= 0.001) { dres = 500.0; lprintf(stderr, "\tError: bad resistance %g\n", dres); } s->res[i] = (result == TCL_OK) ? dres : 500.0; } Tcl_ResetResult(irsiminterp); *inst = sl->inst; return s; } } return NULL; } #else /*------------------------------*/ /* Method 2: */ /* Simple fixed-size hash table */ /*------------------------------*/ #define SUBSTBLSIZE 16 private SubCircuit *substbl[SUBSTBLSIZE]; private int HashSub(); public void init_subs(userSubCircuit *subckts) { register int n; register userSubCircuit *s; register SubCircuit *sl; for (n=0; n < SUBSTBLSIZE; n++) substbl[n] = NULL; for (s = subckts; s->name != NULL; s++) { sl = (SubCircuit *)malloc(sizeof(SubCircuit)); sl->subckt = s; sl->inst = 0; n = HashSub(s->name); sl->next = substbl[n]; substbl[n] = sl; } } private int HashSub(char *name) { register int hashcode = 0; do hashcode = (hashcode << 1) ^ (*name | 0x20); while (*(++name)); return (((hashcode >= 0) ? hashcode : ~hashcode) % SUBSTBLSIZE); } public userSubCircuit *subckt_instantiate(char *sname, int *inst, uptr *udatap) { register int n; register SubCircuit *s; *udatap = NULL; /* placeholder, used by Tcl version only */ n = HashSub(sname); for (s = substbl[n]; s != NULL; s = s->next) { if (str_eql(s->subckt->name, sname) == 0) { s->inst++; *inst = s->inst; return s->subckt; } } return NULL; } #endif /* !TCL_IRSIM */ /* *------------------------------------------------------------------ * Evalutate a subcircuit model *------------------------------------------------------------------ */ public void subckt_model_C(tptr t) { int i; SubcktT *subptr = (SubcktT *)(t->subptr); short nins = subptr->subckt->ninputs; short nouts = subptr->subckt->noutputs; nptr *nodes = subptr->nodes; uptr udata = subptr->udata; #ifdef TCL_IRSIM int result; #endif char *in, *out = NULL; double *delay; in = (char *) malloc((nins + 1) * sizeof(char)); out = (char *) malloc((nouts + 1) * sizeof(char)); delay = (double *) malloc(nouts * sizeof(double)); for (i = 0; i < nins; i++) in[i] = nodes[i]->npot; for (i = 0; i < nouts; i++) out[i] = nodes[i+nins]->npot; if (subptr->subckt->model != NULL) (*subptr->subckt->model)(in, out, delay, udata); #ifdef TCL_IRSIM else { Tcl_Obj *objv[4]; /* The Tcl version of IRSIM allows subcircuit to be defined as */ /* Tcl procedures. This procedure must return a list whose */ /* first element is a string of all the output values, followed */ /* by time delays to all of the outputs. */ for (i = 0; i < nins; i++) in[i] = pot2ch[in[i]]; in[nins] = '\0'; for (i = 0; i < nouts; i++) out[i] = pot2ch[out[i]]; out[nouts] = '\0'; objv[0] = Tcl_NewStringObj(subptr->subckt->name, -1); Tcl_AppendToObj(objv[0], "_eval", 5); objv[1] = Tcl_NewStringObj(in, nins); objv[2] = Tcl_NewStringObj(out, nouts); objv[3] = (Tcl_Obj *)udata; result = Tcl_EvalObjv(irsiminterp, 4, objv, 0); if (result == TCL_OK) { int listlen; double dval; char *newoutvals; Tcl_Obj *elem, *rlist; rlist = Tcl_GetObjResult(irsiminterp); result = Tcl_ListObjLength(irsiminterp, rlist, &listlen); if (result == TCL_OK && listlen == 1 + nouts) { result = Tcl_ListObjIndex(irsiminterp, rlist, 0, &elem); newoutvals = Tcl_GetString(elem); if (strlen(newoutvals) == nouts) { for (i = 0; i < nouts; i++) { result = Tcl_ListObjIndex(irsiminterp, rlist, i + 1, &elem); result = Tcl_GetDoubleFromObj(irsiminterp, elem, &delay[i]); switch (tolower(newoutvals[i])) { case '0': case 'l': out[i] = LOW; break; case '1': case 'h': out[i] = HIGH; break; case 'z': out[i] = HIGH_Z; break; default: out[i] = X; break; } } /* Clear the interpreter result */ Tcl_ResetResult(irsiminterp); } else { Tcl_SetResult(irsiminterp, "Subcircuit result does not match" " the number of defined outputs", 0); nouts = 0; } } else { if (result == TCL_OK) Tcl_SetResult(irsiminterp, "Subcircuit evaluator did not" " return the correct size list", 0); nouts = 0; } } else nouts = 0; } #endif for (i = 0; i < nouts; i++ ) { switch (out[i]) { case LOW: QueueFVal(nodes[i+nins], HIGH, (double) 1.0, delay[i]); QueueFVal(nodes[i+nins+nouts], HIGH, (double) 1.0, delay[i]); break; case X: QueueFVal(nodes[i+nins], X, (double) 1.0, delay[i]); QueueFVal(nodes[i+nins+nouts], X, (double) 1.0, delay[i]); break; case HIGH_Z: QueueFVal(nodes[i+nins], HIGH, (double) 1.0, delay[i]); QueueFVal(nodes[i+nins+nouts], LOW, (double) 1.0, delay[i]); break; case HIGH: QueueFVal(nodes[i+nins], LOW, (double) 1.0, delay[i]); QueueFVal(nodes[i+nins+nouts], LOW, (double) 1.0, delay[i]); break; } } free(in); free(out); free(delay); } /* *------------------------------------------------------------------ * Create a new subcircuit from the .sim file line * "x [] " * * The subcircuit definition is assumed to be already known; * otherwise, this routine returns an error result (-1). * Return 0 on success. *------------------------------------------------------------------ */ public int newsubckt(targc, targv) int targc; char *targv[]; { userSubCircuit *subcircuit; SubcktT *subptr, *subptr2; int i, n, ninputs, noutputs; float rtf; ufun init; register tptr t = 0; tptr t2; lptr l; char *sname, *out_name_Ub, *out_name_D; int subckt_out_counter = 0; nptr *nodes; lptr diodes = (lptr)NULL, d; uptr usrData = NULL; int inst, result = 0; subcircuit = subckt_instantiate(targv[targc - 1], &inst, &usrData); if (subcircuit == NULL) { lprintf(stderr, "\tError: subcircuit \"%s\" is not defined!\n", targv[targc - 1]); return -1; } ninputs = subcircuit->ninputs; noutputs = subcircuit->noutputs; sname = subcircuit->name; if (targc < ninputs + noutputs + 2) { lprintf(stderr, "\tError: wrong # args %d\n", targc); lprintf(stderr, "\tsubcircuit %s has %d input nodes, %d output nodes\n", subcircuit->name, ninputs, noutputs); return -1; } out_name_Ub = (char *)malloc(strlen(targv[targc-1]) + 20); out_name_D = (char *)malloc(strlen(targv[targc-1]) + 20); targc--; targv++; nodes = (nptr *)malloc((ninputs + 2 * noutputs) * sizeof(nptr)); lprintf(stdout, "defining new subcircuit \"%s\" instance %d #i:%d #o:%d\n", subcircuit->name, inst, ninputs, noutputs); /* If the functions are compiled from C code, the C code init */ /* function is responsible for interpreting any parameters given to */ /* the device instance in the .sim file. */ if (subcircuit->init) usrData = (uptr)(*subcircuit->init)(targc - ninputs - noutputs, targv + ninputs + noutputs); #ifdef TCL_IRSIM else if (targc >= ninputs + noutputs + 2) { /* Extra user data list has been specified in the .sim */ /* file. Append this to the current user data object. */ /* We assume that the evaluator procedure knows how to */ /* deal with the extra data. */ Tcl_Obj *sobj, *uobj = (Tcl_Obj *)usrData; if (uobj == NULL) { uobj = Tcl_NewListObj(0, NULL); Tcl_IncrRefCount(uobj); } for (i = ninputs + noutputs + 1; i < targc; i++) { sobj = Tcl_NewStringObj(targv[i], -1); Tcl_ListObjAppendElement(irsiminterp, uobj, sobj); } } #endif for (i = 0; i < ninputs; i++) { /* create new "transistor" */ NEW_TRANS(t); NEW_SUBCKT(subptr); t->subptr = (char *)subptr; t->ttype = SUBCKT; t->gate = RsimGetNode(targv[i]); subptr->nodes = nodes; t->source = VDD_node; t->drain = t->gate; /* link it to the list */ t->scache.t = rd_tlist; rd_tlist = t; t->r = requiv(RESIST, (int)2, (int)(1000000 * LAMBDACM)); subptr->subckt = subcircuit; /* All this can be referenced by a pointer to a subckt structure */ NEW_LINK(d); d->xtor = t; d->next = diodes; subptr->ndiode = d; diodes = d; nodes[i] = t->gate; subptr->udata = usrData; } for (l = subptr->ndiode; l != NULL; l = l->next) { t2 = l->xtor; subptr2 = (SubcktT *)(t2->subptr); subptr2->ndiode = diodes; } n = 0; for (; i < ninputs + noutputs; i++) { /* define two transistors for each output : */ sprintf(out_name_Ub, "%sUb_%d_%d", sname, inst, subckt_out_counter); sprintf(out_name_D , "%sD_%d_%d", sname, inst, subckt_out_counter++); if (find(out_name_Ub) || find(out_name_D)) { lprintf(stderr,"Error: nodes named %s or %s already exist\n", out_name_Ub, out_name_D); result = -1; goto donesubckt; } NEW_TRANS(t); /* Add pmos output driver */ t->ttype = PCHAN; t->gate = RsimGetNode(out_name_Ub); nodes[i] = t->gate; t->drain = VDD_node; t->source = RsimGetNode(targv[i]); t->scache.t = rd_tlist; /* link it to the list */ rd_tlist = t; rtf = subcircuit->res[n++]; t->r = requiv(RESIST, (int)2, (int)(rtf * LAMBDACM)); NEW_TRANS(t); /* Add nmos output driver */ t->ttype = NCHAN; t->gate = RsimGetNode(out_name_D); t->drain = RsimGetNode(targv[i]); nodes[i + noutputs] = t->gate; t->source = GND_node; t->scache.t = rd_tlist; /* link it to the list */ rd_tlist = t; rtf = subcircuit->res[n++]; t->r = requiv(RESIST, (int)2, (int)(rtf * LAMBDACM)); } /* for loop over outputs */ donesubckt: free(out_name_D); free(out_name_Ub); return result; } #endif /* USER_SUBCKT */ irsim-9.7.93/usersubckt/user.c0000644000175000001440000000152010706367221014774 0ustar timusers/*--------------------------------------------------------------*/ /* This file (user.c) is a placeholder that defines the array */ /* of information about user-defined subcircuits. To compile */ /* a different set of user subcircuits, replace "user.c" in the */ /* Makefile with the name of the source code file. Files */ /* "flop_mux.c" and "dll.c" are provided as examples. */ /*--------------------------------------------------------------*/ #include #ifndef _GLOBALS_H #include "globals.h" #endif #include "subckt.h" #define DEBUG 0 #define dprintf if (DEBUG) lprintf userSubCircuit subs[] = { { NULL, NULL, NULL, 0, 0, NULL} }; /*--------------------------------------------------------------*/ /* End of user.c empty placeholder library */ /*--------------------------------------------------------------*/ irsim-9.7.93/usersubckt/subckt.h0000644000175000001440000000343710706367162015333 0ustar timusers#ifndef _SUBCKT_H #define _SUBCKT_H #ifdef USER_SUBCKT #ifndef _LOCTYPES_H #include "loctypes.h" #endif /*----------------------------------------------------------------------*/ /* User-defined subcircuits have a different set of logic values, */ /* allowing the output to be defined in various ways, like high- */ /* impedence, pull-up, pull-down, open drain, etc. */ /*----------------------------------------------------------------------*/ #define C_LOW 'l' /* logic low */ #define C_X 'x' /* unknown or intermediate value */ #define C_Z 'z' /* high impedence state */ #define C_HI 'h' /* logic high */ /*----------------------------------------------------------------------*/ /* Structure used to declare information about user-defined subcircuit */ /* library components. */ /*----------------------------------------------------------------------*/ typedef struct { char *name; /* name of this sub-circuit */ vfun model; /* function that models sub-circuit */ ufun init; /* Function to call to init */ short ninputs; /* Number of input nodes */ short noutputs; /* Number of output nodes */ float *res; /* pointer to list of output driver */ /* "on" resistances */ } userSubCircuit; /*----------------------------------------------------------------------*/ /* Structure that substitutes for a transistor record in the netlist */ /* at each subcircuit input node */ /*----------------------------------------------------------------------*/ typedef struct _SubcktT { userSubCircuit *subckt; nptr *nodes; uptr udata; /* pointer to instance's private data */ lptr ndiode; } SubcktT; extern userSubCircuit subs[]; #endif #ifndef _UNITS_H #include "units.h" #endif #endif irsim-9.7.93/usersubckt/flop_mux.c0000644000175000001440000000233510706367162015660 0ustar timusers#include #include "subckt.h" uptr mux2_init(); void mux2_eval(); uptr flop_init(); void flop_eval(); static float mux2_res[2] = {500.0, 500.0}; static float flop_res[2] = {1000.0, 1000.0}; static userSubCircuit subs[] = { { "mux2", mux2_eval, mux2_init, 3, 1, mux2_res}, { "flop", flop_eval, flop_init, 3, 1, flop_res}, { NULL, NULL, NULL, 0, 0, NULL} }; typedef struct _flopState { int prvClk; int Q; } flopState; uptr flop_init() { flopState *thisFlop = (flopState *)malloc(sizeof(flopState)); thisFlop->prvClk = HIGH; thisFlop->Q = X; return (uptr)thisFlop; } void flop_eval(ins, outs, delay, data) char *ins, *outs; double *delay; uptr *data; { flopState *ff = (flopState *)data ; if (ff->prvClk == LOW && ins[1] == HIGH) { lprintf("flop edge @ %.2fns\n", d2ns(cur_delta)); ff->Q = ins[0]; } delay[0] = 100.0; ff->prvClk = ins[1]; outs[0] = ff->Q; } uptr mux2_init() { return (uptr)NULL; } void mux2_eval(ins, outs, delay, udata) char *ins; char *outs; double *delay; uptr udata; { delay[0] = 100.0; if (ins[2] == LOW) outs[0] = ins[1]; else if (ins[2] == HIGH) outs[0] = ins[0]; else outs[0] = X; } irsim-9.7.93/tcltk/0000755000175000001440000000000012605757014012606 5ustar timusersirsim-9.7.93/tcltk/tkAnalyzer.c0000644000175000001440000004130010417762771015101 0ustar timusers/* *----------------------------------------------------------------------- * tkAnalyzer.c -- * * Tk implementation of the logic analyzer widget for IRSIM * *----------------------------------------------------------------------- */ #ifdef TCL_IRSIM #include #include #ifdef LINUX #include /* for strncmp() */ #endif #include #include "ana.h" #include "ana_glob.h" #include "rsim.h" /* Backwards compatibility to tk8.3 and earlier */ #if TK_MAJOR_VERSION == 8 #if TK_MINOR_VERSION <= 3 #define Tk_SetClassProcs(a,b,c) TkSetClassProcs(a,b,c) #endif #endif #ifndef CONST84 #define CONST84 #endif /* Internal routine used---need to find an alternative! */ extern int TkpUseWindow(); /* * A data structure of the following type is kept for each * analyzer window that currently exists for this process: */ typedef struct { Tk_Window tkwin; /* Window that embodies the analyzer. NULL * means that the window has been destroyed * but the data structures haven't yet been * cleaned up. */ Display *display; /* Display containing widget. Used, among * other things, so that resources can be * freed even after tkwin has gone away. */ Tcl_Interp *interp; /* Interpreter associated with widget. Used * to delete widget command. */ Tcl_Command widgetCmd; /* Token for analyzer's widget command. */ char *className; /* Class name for widget (from configuration * option). Malloc-ed. */ int width; /* Width to request for window. <= 0 means * don't request any size. */ int height; /* Height to request for window. <= 0 means * don't request any size. */ XColor *background; /* background pixel used by XClearArea */ char *useThis; /* If the window is embedded, this points to * the name of the window in which it is * embedded (malloc'ed). For non-embedded * windows this is NULL. */ char *exitProc; /* Callback procedure upon window deletion. */ char *mydata; /* This space for hire. */ int flags; /* Various flags; see below for * definitions. */ } TkAnalyzer; /* * Flag bits for analyzers: * * GOT_FOCUS: non-zero means this widget currently has the input focus. */ #define GOT_FOCUS 1 static Tk_ConfigSpec configSpecs[] = { {TK_CONFIG_COLOR, "-background", "background", "Background", "Black", Tk_Offset(TkAnalyzer, background), 0}, {TK_CONFIG_SYNONYM, "-bg", "background", (char *)NULL, (char *)NULL, 0, 0}, {TK_CONFIG_PIXELS, "-height", "height", "Height", "0", Tk_Offset(TkAnalyzer, height), 0}, {TK_CONFIG_PIXELS, "-width", "width", "Width", "0", Tk_Offset(TkAnalyzer, width), 0}, {TK_CONFIG_STRING, "-use", "use", "Use", "", Tk_Offset(TkAnalyzer, useThis), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-exitproc", "exitproc", "ExitProc", "", Tk_Offset(TkAnalyzer, exitProc), TK_CONFIG_NULL_OK}, {TK_CONFIG_STRING, "-data", "data", "Data", "", Tk_Offset(TkAnalyzer, mydata), TK_CONFIG_NULL_OK}, {TK_CONFIG_END, (char *) NULL, (char *) NULL, (char *) NULL, (char *) NULL, 0, 0} }; /* * Forward declarations for procedures defined later in this file: */ static int ConfigureTkAnalyzer _ANSI_ARGS_((Tcl_Interp *interp, TkAnalyzer *analyzerPtr, int objc, Tcl_Obj *CONST objv[], int flags)); static void DestroyTkAnalyzer _ANSI_ARGS_((char *memPtr)); static void TkAnalyzerCmdDeletedProc _ANSI_ARGS_(( ClientData clientData)); static void TkAnalyzerEventProc _ANSI_ARGS_((ClientData clientData, XEvent *eventPtr)); static int AnalyzerWidgetObjCmd _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); /* *-------------------------------------------------------------- * * TkAnalyzerObjCmd -- * * This procedure is invoked to process the "tkanalyzer" * Tcl command. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. These procedures are just wrappers; * they call ButtonCreate to do all of the real work. * *-------------------------------------------------------------- */ int TkAnalyzerObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Main window associated with * interpreter. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { Tk_Window tkwin = (Tk_Window) clientData; TkAnalyzer *analyzerPtr; Tk_Window new; char *arg, *useOption; int i, c; size_t length; unsigned int mask; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "pathName ?options?"); return TCL_ERROR; } /* * Pre-process the argument list. Scan through it to find any * "-use" option, or the "-main" option. If the "-main" option * is selected, then the application will exit if this window * is deleted. */ useOption = NULL; for (i = 2; i < objc; i += 2) { arg = Tcl_GetStringFromObj(objv[i], (int *) &length); if (length < 2) { continue; } c = arg[1]; if ((c == 'u') && (strncmp(arg, "-use", length) == 0)) { useOption = Tcl_GetString(objv[i+1]); } } /* * Create the window, and deal with the special option -use. */ if (tkwin != NULL) { new = Tk_CreateWindowFromPath(interp, tkwin, Tcl_GetString(objv[1]), NULL); } if (new == NULL) { goto error; } Tk_SetClass(new, "TkAnalyzer"); if (useOption == NULL) { useOption = (char *)Tk_GetOption(new, "use", "Use"); } if (useOption != NULL) { if (TkpUseWindow(interp, new, useOption) != TCL_OK) { goto error; } } /* * Create the widget record, process configuration options, and * create event handlers. Then fill in a few additional fields * in the widget record from the special options. */ analyzerPtr = (TkAnalyzer *) ckalloc(sizeof(TkAnalyzer)); analyzerPtr->tkwin = new; analyzerPtr->display = Tk_Display(new); analyzerPtr->interp = interp; analyzerPtr->widgetCmd = Tcl_CreateObjCommand(interp, Tk_PathName(new), AnalyzerWidgetObjCmd, (ClientData) analyzerPtr, TkAnalyzerCmdDeletedProc); analyzerPtr->className = NULL; analyzerPtr->width = 0; analyzerPtr->height = 0; analyzerPtr->background = NULL; analyzerPtr->useThis = NULL; analyzerPtr->exitProc = NULL; analyzerPtr->flags = 0; analyzerPtr->mydata = NULL; /* * Store backreference to analyzer widget in window structure. */ Tk_SetClassProcs(new, NULL, (ClientData) analyzerPtr); /* We only handle focus and structure events, and even that might change. */ mask = StructureNotifyMask|FocusChangeMask|NoEventMask|ExposureMask; Tk_CreateEventHandler(new, mask, TkAnalyzerEventProc, (ClientData) analyzerPtr); if (ConfigureTkAnalyzer(interp, analyzerPtr, objc-2, objv+2, 0) != TCL_OK) { goto error; } Tcl_SetResult(interp, Tk_PathName(new), TCL_STATIC); return TCL_OK; error: if (new != NULL) { Tk_DestroyWindow(new); } return TCL_ERROR; } /* *-------------------------------------------------------------- * * AnalyzerWidgetObjCmd -- * * This procedure is invoked to process the Tcl command * that corresponds to a analyzer widget path name. See * the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *-------------------------------------------------------------- */ static int AnalyzerWidgetObjCmd(clientData, interp, objc, objv) ClientData clientData; /* Information about analyzer widget. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */ { static char *tkanalyzerOptions[] = { "cget", "configure", "height", "width", "init", "help", (char *) NULL }; enum options { ANALYZER_CGET, ANALYZER_CONFIGURE, ANALYZER_HEIGHT, ANALYZER_WIDTH, ANALYZER_INIT, ANALYZER_HELP }; register TkAnalyzer *analyzerPtr = (TkAnalyzer *) clientData; int result = TCL_OK, idx; int c, i; size_t length; Tcl_Obj *robj; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], (CONST84 char **)tkanalyzerOptions, "option", 0, &idx) != TCL_OK) { return TCL_ERROR; } Tcl_Preserve((ClientData) analyzerPtr); switch ((enum options)idx) { case ANALYZER_HELP: Tcl_SetResult(interp, "Options are \"configure\", \"cget\", " "\"height\", \"width\", \"init\", or \"help\".\n", NULL); break; case ANALYZER_CGET: if (objc != 3) { Tcl_WrongNumArgs(interp, 2, objv, "option"); result = TCL_ERROR; goto done; } result = Tk_ConfigureValue(interp, analyzerPtr->tkwin, configSpecs, (char *) analyzerPtr, Tcl_GetString(objv[2]), 0); break; case ANALYZER_CONFIGURE: if (objc == 2) { result = Tk_ConfigureInfo(interp, analyzerPtr->tkwin, configSpecs, (char *) analyzerPtr, (char *) NULL, 0); } else if (objc == 3) { result = Tk_ConfigureInfo(interp, analyzerPtr->tkwin, configSpecs, (char *) analyzerPtr, Tcl_GetString(objv[2]), 0); } else { for (i = 2; i < objc; i++) { char *arg = Tcl_GetStringFromObj(objv[i], (int *) &length); if (length < 2) { continue; } c = arg[1]; if ((c == 'u') && (strncmp(arg, "-use", length) == 0)) { Tcl_AppendResult(interp, "can't modify ", arg, " option after widget is created", (char *) NULL); result = TCL_ERROR; goto done; } } result = ConfigureTkAnalyzer(interp, analyzerPtr, objc-2, objv+2, TK_CONFIG_ARGV_ONLY); } break; /* Report actual window width and height, for manipulating */ /* the slider, and converting pixels to simulation time. */ case ANALYZER_WIDTH: robj = Tcl_NewIntObj(Tk_Width(analyzerPtr->tkwin)); Tcl_SetObjResult(interp, robj); break; case ANALYZER_HEIGHT: robj = Tcl_NewIntObj(Tk_Height(analyzerPtr->tkwin)); Tcl_SetObjResult(interp, robj); break; case ANALYZER_INIT: /* Force mapping of the window */ Tk_MakeWindowExist(analyzerPtr->tkwin); start_analyzer(analyzerPtr->tkwin); result = TCL_OK; break; } done: Tcl_Release((ClientData) analyzerPtr); return result; } /* *---------------------------------------------------------------------- * * DestroyTkAnalyzer -- * * This procedure is invoked by Tcl_EventuallyFree or Tcl_Release * to clean up the internal structure of a analyzer at a safe time * (when no-one is using it anymore). * * Results: * None. * * Side effects: * Everything associated with the analyzer is freed up. * *---------------------------------------------------------------------- */ static void DestroyTkAnalyzer(memPtr) char *memPtr; /* Info about analyzer widget. */ { register TkAnalyzer *analyzerPtr = (TkAnalyzer *) memPtr; Tk_FreeOptions(configSpecs, (char *) analyzerPtr, analyzerPtr->display, TK_CONFIG_USER_BIT); if (analyzerPtr->exitProc != NULL) { /* Call the exit procedure */ Tcl_EvalEx(analyzerPtr->interp, analyzerPtr->exitProc, -1, 0); } ckfree((char *) analyzerPtr); } /* *---------------------------------------------------------------------- * * ConfigureTkAnalyzer -- * * This procedure is called to process an objv/objc list, plus * the Tk option database, in order to configure (or * reconfigure) a analyzer widget. * * Results: * The return value is a standard Tcl result. If TCL_ERROR is * returned, then the interp's result contains an error message. * * Side effects: * Configuration information, such as text string, colors, font, * etc. get set for analyzerPtr; old resources get freed, if there * were any. * *---------------------------------------------------------------------- */ static int ConfigureTkAnalyzer(interp, analyzerPtr, objc, objv, flags) Tcl_Interp *interp; /* Used for error reporting. */ register TkAnalyzer *analyzerPtr; /* Information about widget; may or may * not already have values for some fields. */ int objc; /* Number of valid entries in objv. */ Tcl_Obj *CONST objv[]; /* Arguments. */ int flags; /* Flags to pass to Tk_ConfigureWidget. */ { if (Tk_ConfigureWidget(interp, analyzerPtr->tkwin, configSpecs, objc, (CONST84 char **) objv, (char *) analyzerPtr, flags | TK_CONFIG_OBJS) != TCL_OK) { return TCL_ERROR; } if ((analyzerPtr->width > 0) || (analyzerPtr->height > 0)) { Tk_GeometryRequest(analyzerPtr->tkwin, analyzerPtr->width, analyzerPtr->height); } if (analyzerPtr->background != NULL) { Tk_SetWindowBackground(analyzerPtr->tkwin, analyzerPtr->background->pixel); } return TCL_OK; } /* *-------------------------------------------------------------- * * TkAnalyzerEventProc -- * * This procedure is invoked by the Tk dispatcher on * structure changes to a analyzer. For analyzers with 3D * borders, this procedure is also invoked for exposures. * * Results: * None. * * Side effects: * When the window gets deleted, internal structures get * cleaned up. When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void TkAnalyzerEventProc(clientData, eventPtr) ClientData clientData; /* Information about window. */ register XEvent *eventPtr; /* Information about event. */ { register TkAnalyzer *analyzerPtr = (TkAnalyzer *) clientData; switch (eventPtr->type) { case DestroyNotify: if (analyzerPtr->tkwin != NULL) { /* * If this window is a container, then this event could be * coming from the embedded application, in which case * Tk_DestroyWindow hasn't been called yet. When Tk_DestroyWindow * is called later, then another destroy event will be generated. * We need to be sure we ignore the second event, since the analyzer * could be gone by then. To do so, delete the event handler * explicitly (normally it's done implicitly by Tk_DestroyWindow). */ Tk_DeleteEventHandler(analyzerPtr->tkwin, StructureNotifyMask | FocusChangeMask, TkAnalyzerEventProc, (ClientData) analyzerPtr); analyzerPtr->tkwin = NULL; Tcl_DeleteCommandFromToken(analyzerPtr->interp, analyzerPtr->widgetCmd); } Tcl_EventuallyFree((ClientData) analyzerPtr, DestroyTkAnalyzer); analyzerON = FALSE; break; case FocusIn: if (eventPtr->xfocus.detail != NotifyInferior) { analyzerPtr->flags |= GOT_FOCUS; } break; case FocusOut: if (eventPtr->xfocus.detail != NotifyInferior) { analyzerPtr->flags &= ~GOT_FOCUS; } break; case Expose: { XExposeEvent *exposeEvent = (XExposeEvent *)eventPtr; BBox box; box.left = exposeEvent->x; box.right = exposeEvent->x + exposeEvent->width - 1; box.bot = exposeEvent->y + exposeEvent->height - 1; box.top = exposeEvent->y; /* Note that we call RedrawTraces(), not RedrawWindow(), * because RedrawTraces() is the only thing handled by * the TkAnalyzer window, and it takes up the whole * window, so it always must intersect traceBox. */ RedrawTraces(&box); } break; case ConfigureNotify: { BBox box; XWINDOWSIZE = Tk_Width(analyzerPtr->tkwin); YWINDOWSIZE = Tk_Height(analyzerPtr->tkwin); start_analyzer(analyzerPtr->tkwin); WindowChanges(); box.left = box.top = 0; box.right = XWINDOWSIZE; box.bot = YWINDOWSIZE; RedrawTraces(&box); } break; } return; } /* *---------------------------------------------------------------------- * * TkAnalyzerCmdDeletedProc -- * * This procedure is invoked when a widget command is deleted. If * the widget isn't already in the process of being destroyed, * this command destroys it. * * Results: * None. * * Side effects: * The widget is destroyed. * *---------------------------------------------------------------------- */ static void TkAnalyzerCmdDeletedProc(clientData) ClientData clientData; /* Pointer to widget record for widget. */ { TkAnalyzer *analyzerPtr = (TkAnalyzer *) clientData; Tk_Window tkwin = analyzerPtr->tkwin; /* * This procedure could be invoked either because the window was * destroyed and the command was then deleted (in which case tkwin * is NULL) or because the command was deleted, and then this procedure * destroys the widget. */ if (tkwin != NULL) { analyzerPtr->tkwin = NULL; Tk_DestroyWindow(tkwin); } } /* Create the command callback for the Tk analyzer window */ void InitTkAnalyzer(interp) Tcl_Interp *interp; { Tk_Window tktop; tktop = Tk_MainWindow(interp); Tcl_CreateObjCommand(interp, "tkanalyzer", (Tcl_ObjCmdProc *)TkAnalyzerObjCmd, (ClientData)tktop, (Tcl_CmdDeleteProc *)NULL); } #endif /* TCL_IRSIM */ irsim-9.7.93/tcltk/console.tcl0000644000175000001440000000023710416553134014751 0ustar timusers# Tcl commands to run in the console before IRSIM is initialized # puts stdout "Running IRSIM Console Functions" bind .text {irsim::interrupt} irsim-9.7.93/tcltk/irsim.sh.in0000755000175000001440000000255310416553134014675 0ustar timusers#!/bin/sh # # For installation, put this file (irsim.sh) in a standard executable path. # Put startup script "irsim.tcl" and shared library "tclirsim.so" # in ${CAD_ROOT}/irsim/tcl/, with a symbolic link from file # ".wishrc" to "irsim.tcl". # # This script starts irsim under the Tcl interpreter, # reading commands from a special .wishrc script which # launches irsim and retains the Tcl interactive interpreter. # Parse for the argument "-c[onsole]". If it exists, run irsim # with the TkCon console. Strip this argument from the argument list. TKCON=true IRSIM_WISH=WISH_EXE export IRSIM_WISH # Hacks for Cygwin if [ ${TERM:=""} = "cygwin" ]; then export PATH="$PATH:TCLLIB_DIR" export DISPLAY=${DISPLAY:=":0"} fi for i in $@ ; do case $i in -noc*) TKCON=;; esac done if [ $TKCON ]; then exec TCL_DIR/tkcon.tcl \ -eval "source TCL_DIR/console.tcl" \ -slave "package require Tk; set argc $#; set argv [list $*]; \ source TCL_DIR/irsim.tcl" # exec TCL_DIR/tkcon.tcl -exec "" -eval \ # "set argc $#; set argv [list $*]; source TCL_DIR/irsim.tcl" else # # Run the stand-in for wish (irsimexec), which acts exactly like "wish" # except that it replaces ~/.wishrc with irsim.tcl. This executable is # *only* needed when running without the console; the console itself is # capable of sourcing the startup script. # exec TCL_DIR/irsimexec -- $@ fi irsim-9.7.93/tcltk/vcd.tcl0000664000175000001440000000536212517765570014106 0ustar timusers#--------------------------------------------------------- # vcd.tcl #--------------------------------------------------------- # Support for reading "VCD" format dumpfiles in IRSIM. # Adds command "readvcd ", which reads in # the file and displays the traces in the analyzer. #--------------------------------------------------------- proc readvcd {dumpfile} { set prefix "" if { [catch {open $dumpfile r} df] } { puts stderr "Could not open VCD dumpfile $dumpfile\n" return } while {[gets $df line] >= 0} { if {[regexp {^\$([^ ]+)} $line lmatch dumpvar]} { switch $dumpvar { date { gets $df line puts stdout $line } version { gets $df line puts stdout $line } timescale { gets $df line regexp {([0-9]+)[ \t]*([^ ]+)} $line lmatch scale metric switch $metric { fs {set scale [expr 0.001 * $scale]} ns {set scale [expr 1000 * $scale]} } } var { regexp {^\$var[ \t]+[^ ]+[ \t]+([0-9]+)[ \t]+([^ ]+)[ \t]+([^ ]+)} \ $line lmatch bitlen repchar signame if {$bitlen == 1} { addnode ${prefix}${signame} } else { for {set i 0} {$i < $bitlen} {incr i} { addnode ${prefix}${signame}\[$i\] } incr bitlen -1 vector ${prefix}${signame} ${prefix}${signame}\[0:${bitlen}\] } set nodenames($repchar) ${prefix}${signame} ana ${prefix}${signame} } scope { regexp {^\$scope[ \t]+([^ ]+)[ \t]+([^ ]+)} \ $line lmatch scopetype instname set prefix "${prefix}${instname}/" } upscope { set prefix "" } } } else { # Known patterns are: 0, 1, x (bit set), b (vector set), # (schedule) set curtime 0 while {[gets $df line] >= 0} { set cmd [string index $line 0] switch $cmd { b { regexp {^b([0-9]+)[ \t]+([^ ]+)} $line lmatch bval sname setvector $nodenames($sname) %b${bval} } # { set tval [string range $line 1 end] set tval [expr $tval * $scale] set nexttime $tval set tval [expr $tval - $curtime] if {$tval > 0} s $tval set curtime $nexttime } 0 { set sname [string range $line 1 end] l $nodenames($sname) } 1 { set sname [string range $line 1 end] h $nodenames($sname) } x { set sname [string range $line 1 end] u $nodenames($sname) } } } } } close $df } #--------------------------------------------------------- # For backward compatibility. Procedure was originally named "readcver", # but the format is VCD. #--------------------------------------------------------- proc readcver {dumpfile} { readvcd $dumpfile } irsim-9.7.93/tcltk/irsimexec.c0000644000175000001440000000615510416553134014744 0ustar timusers/*----------------------------------------------------------------------*/ /* irsimexec.c */ /* */ /* Written by R. Timothy Edwards for MultiGiG, Inc., November 2004 */ /* This file mainly lifted from the main application routine for */ /* "wish" from the Tk distribution. */ /* */ /* This is a compact re-write of the "wish" executable that calls */ /* Tk_MainEx with application-specific processing. Specifically, */ /* "wish" doesn't allow the startup script (~/.wishrc) to be renamed. */ /* However, for irsim running as an extension of Tcl, we want to source */ /* the irsim.tcl file instead of ~/.wishrc. So, all this file really */ /* does is to set the Tcl variable "tcl_rcFileName" to irsim.tcl, so */ /* that it will be processed as the startup script, followed by a drop */ /* back to the Tcl interpreter command-line main loop. */ /* */ /* This is a standalone executable. However, it is only called when */ /* "-noconsole" is specified on the UNIX command-line. When the */ /* console is used, the console is capable of sourcing the irsim.tcl */ /* script itself, and so it uses "wish" as the executable. However, */ /* the console redirects standard input, so it prevents irsim from */ /* being used in a batch processing mode. Thus, to batch-process with */ /* irsim, use "irsim -noc < script.tcl" or, interactively, */ /* "irsim -noc << EOF" followed by commands entered from stdin */ /* and ending with "EOF". */ /* */ /* The "irsimexec" method replaces the former use of "wish" with the */ /* "irsim" script setting HOME to point to the directory containing */ /* ".wishrc", a symbolic link to "irsim.tcl". That failed to work on */ /* remote systems because the $HOME environment variable is also used */ /* to find the user's .Xauthority file to authenticate the X11 */ /* connection. */ /*----------------------------------------------------------------------*/ #include #include #include /*----------------------------------------------------------------------*/ /* Application initiation. This is exactly like the AppInit routine */ /* for "wish", minus the cruft, but with "tcl_rcFileName" set to */ /* "irsim.tcl" instead of "~/.wishrc". */ /*----------------------------------------------------------------------*/ int irsim_AppInit(interp) Tcl_Interp *interp; { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } if (Tk_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); /* This is where we replace the home ".wishrc" file with */ /* irsim's startup script. */ Tcl_SetVar(interp, "tcl_rcFileName", TCL_DIR "/irsim.tcl", TCL_GLOBAL_ONLY); return TCL_OK; } /*----------------------------------------------------------------------*/ /* The main procedure; replacement for "wish". */ /*----------------------------------------------------------------------*/ int main(argc, argv) int argc; char **argv; { Tk_Main(argc, argv, irsim_AppInit); return 0; } /*----------------------------------------------------------------------*/ irsim-9.7.93/tcltk/tkTag.c0000644000175000001440000001541610516003122014012 0ustar timusers/*----------------------------------------------------------------------*/ /* Tag callback mechanism */ /*----------------------------------------------------------------------*/ #include #include #include /* for strlen() */ #include "net.h" /* defines TRUE and FALSE */ Tcl_HashTable IrsimTagTable; /*----------------------------------------------------------------------*/ /* Quick reimplementation of strdup() using Tcl's alloc calls */ /*----------------------------------------------------------------------*/ char *Tcl_StrDup(const char *s) { char *snew; int slen; slen = 1 + strlen(s); snew = Tcl_Alloc(slen); if (snew != NULL) memcpy(snew, s, slen); return snew; } /*----------------------------------------------------------------------*/ /* Implement tag callbacks on functions */ /* Find any tags associated with a command and execute them. */ /*----------------------------------------------------------------------*/ int IrsimTagCallback(Tcl_Interp *interp, int argc, char *argv[]) { int argidx, result = TCL_OK; char *postcmd, *substcmd, *newcmd, *sptr, *sres; char *croot = argv[0]; Tcl_HashEntry *entry; Tcl_SavedResult state; int reset = FALSE; int i, llen, cmdnum; /* Skip over namespace qualifier, if any */ if (!strncmp(croot, "::", 2)) croot += 2; if (!strncmp(croot, "irsim::", 10)) croot += 10; entry = Tcl_FindHashEntry(&IrsimTagTable, croot); postcmd = (entry) ? (char *)Tcl_GetHashValue(entry) : NULL; if (postcmd) { substcmd = (char *)Tcl_Alloc(strlen(postcmd) + 1); strcpy(substcmd, postcmd); sptr = substcmd; /*--------------------------------------------------------------*/ /* Parse "postcmd" for Tk-substitution escapes */ /* Allowed escapes are: */ /* %W substitute the tk path of the calling window */ /* %r substitute the previous Tcl result string */ /* %R substitute the previous Tcl result string and */ /* reset the Tcl result. */ /* %[0-5] substitute the argument to the original command */ /* %N substitute all arguments as a list */ /* %% substitute a single percent character */ /* %* (all others) no action: print as-is. */ /* */ /* Characters "[" and "]" in IRSIM commands are escaped to */ /* prevent Tcl from attempting to treat them as an immediate */ /* evaluation. */ /*--------------------------------------------------------------*/ while ((sptr = strchr(sptr, '%')) != NULL) { switch (*(sptr + 1)) { case 'W': { char *tkpath = NULL; Tk_Window tkwind = Tk_MainWindow(interp); if (tkwind != NULL) tkpath = Tk_PathName(tkwind); if (tkpath == NULL) newcmd = (char *)Tcl_Alloc(strlen(substcmd)); else newcmd = (char *)Tcl_Alloc(strlen(substcmd) + strlen(tkpath)); strcpy(newcmd, substcmd); if (tkpath == NULL) strcpy(newcmd + (int)(sptr - substcmd), sptr + 2); else { strcpy(newcmd + (int)(sptr - substcmd), tkpath); strcat(newcmd, sptr + 2); } Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; } break; case 'R': reset = TRUE; case 'r': sres = (char *)Tcl_GetStringResult(interp); newcmd = (char *)Tcl_Alloc(strlen(substcmd) + strlen(sres) + 1); strcpy(newcmd, substcmd); sprintf(newcmd + (int)(sptr - substcmd), "\"%s\"", sres); strcat(newcmd, sptr + 2); Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; break; case '0': case '1': case '2': case '3': case '4': case '5': argidx = (int)(*(sptr + 1) - '0'); if ((argidx >= 0) && (argidx < argc)) { int needList = 0; if (strchr(argv[argidx], '[') != NULL || strchr(argv[argidx], ']') != NULL) needList = 1; newcmd = (char *)Tcl_Alloc(strlen(substcmd) + strlen(argv[argidx]) + 2 * needList); strcpy(newcmd, substcmd); if (needList) strcpy(newcmd + (int)(sptr - substcmd), "{"); strcpy(newcmd + (int)(sptr - substcmd) + needList, argv[argidx]); if (needList) strcat(newcmd, "}"); strcat(newcmd, sptr + 2); Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; } else if (argidx >= argc) { newcmd = (char *)Tcl_Alloc(strlen(substcmd) + 1); strcpy(newcmd, substcmd); strcpy(newcmd + (int)(sptr - substcmd), sptr + 2); Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; } else sptr++; break; case 'N': llen = 1; for (i = 1; i < argc; i++) llen += (1 + strlen(argv[i])); newcmd = (char *)Tcl_Alloc(strlen(substcmd) + llen); strcpy(newcmd, substcmd); strcpy(newcmd + (int)(sptr - substcmd), "{"); for (i = 1; i < argc; i++) { strcat(newcmd, argv[i]); if (i < (argc - 1)) strcat(newcmd, " "); } strcat(newcmd, "}"); strcat(newcmd, sptr + 2); Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; break; case '%': newcmd = (char *)Tcl_Alloc(strlen(substcmd) + 1); strcpy(newcmd, substcmd); strcpy(newcmd + (int)(sptr - substcmd), sptr + 1); Tcl_Free(substcmd); substcmd = newcmd; sptr = substcmd; break; default: break; } } /* lprintf(stderr, "Substituted tag callback is \"%s\"\n", substcmd); */ Tcl_SaveResult(interp, &state); result = Tcl_Eval(interp, substcmd); if ((result == TCL_OK) && (reset == FALSE)) Tcl_RestoreResult(interp, &state); else Tcl_DiscardResult(&state); Tcl_Free(substcmd); } return result; } /*--------------------------------------------------------------*/ /* Add a command tag callback */ /*--------------------------------------------------------------*/ int _irsim_tag(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_HashEntry *entry; char *hstring; int new; if (objc != 2 && objc != 3) return TCL_ERROR; entry = Tcl_CreateHashEntry(&IrsimTagTable, Tcl_GetString(objv[1]), &new); if (entry == NULL) return TCL_ERROR; hstring = (char *)Tcl_GetHashValue(entry); if (objc == 2) { Tcl_SetResult(interp, hstring, NULL); return TCL_OK; } if (strlen(Tcl_GetString(objv[2])) == 0) { Tcl_DeleteHashEntry(entry); } else { hstring = Tcl_StrDup(Tcl_GetString(objv[2])); Tcl_SetHashValue(entry, hstring); } return TCL_OK; } /*--------------------------------------------------------------*/ /* Initialize the tag callback stuff. */ /*--------------------------------------------------------------*/ void TagInit(interp) Tcl_Interp *interp; { Tcl_InitHashTable(&IrsimTagTable, TCL_STRING_KEYS); Tcl_CreateObjCommand(interp, "irsim::tag", (Tcl_ObjCmdProc *)_irsim_tag, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); } irsim-9.7.93/tcltk/lookup.c0000644000175000001440000000544310416553134014264 0ustar timusers/* lookup.c -- * * This file contains a single routine used to look up a string in * a table, allowing unique abbreviations. * * Lifted in large part from the source for magic. */ #include #include #include "globals.h" /*--------------------------------------------------------- * Lookup -- * Searches a table of strings to find one that matches a given * string. It's useful mostly for command lookup. * * Only the portion of a string in the table up to the first * blank character is considered significant for matching. * * Return value: * If str is the same as or an unambiguous abbreviation for one * of the entries in table, then the index of the matching entry * is returned. If str is not the same as any entry in the table, * but an abbreviation for more than one entry, then -1 is returned * (ambiguous result). If str doesn't match any entry, then * -2 is returned. Case differences are ignored. *--------------------------------------------------------- */ int lookup(char *str, char *(table[]), int quiet) { int match = -2; /* result, initialized to -2 = no match */ int pos; int ststart = 0; char mesg[50]; static char *namespace = "::irsim::"; /* Skip over prefix of qualified namespaces "::irsim::" and "irsim::" */ for (pos = 0; pos < 9; pos++) if ((str[pos] != namespace[pos]) || (str[pos] == '\0')) break; if (pos == 9) ststart = 9; else { for (pos = 0; pos < 7; pos++) if ((str[pos] != namespace[pos + 2]) || (str[pos] == '\0')) break; if (pos == 7) ststart = 7; } /* search for match */ for (pos=0; table[pos] != NULL; pos++) { char *tabc = table[pos]; char *strc = &(str[ststart]); while(*strc!='\0' && *tabc!=' ' && ((*tabc==*strc) || (isupper(*tabc) && islower(*strc) && (tolower(*tabc)== *strc))|| (islower(*tabc) && isupper(*strc) && (toupper(*tabc)== *strc)))) { strc++; tabc++; } if (*strc == '\0') { /* entry matches */ if (*tabc == ' ' || *tabc == '\0') { /* exact match - record it and terminate search */ match = pos; break; } else if (match == -2) { /* inexact match and no previous match - record this one * and continue search */ match = pos; } else { /* previous match, so string is ambiguous unless exact * match exists. Mark ambiguous for now, and continue * search. */ match = -1; } } } if (!quiet) { if (match == -1) { sprintf(mesg, "Ambiguous option \"%s\"\n", str); lprintf(stderr, mesg); } else if (match == -2) { lprintf(stderr, "Unknown option. Valid options are: "); for (pos=0; table[pos] != NULL; pos++) { lprintf(stderr, table[pos]); lprintf(stderr, " "); } lprintf(stderr, "\n"); } } return(match); } irsim-9.7.93/tcltk/Makefile0000664000175000001440000000263612075645177014266 0ustar timusersMODULE = tcltk IRSIMDIR = .. SRCS = tclirsim.c tclanalyzer.c lookup.c TK_SRCS = tkAnalyzer.c tkTag.c include ${IRSIMDIR}/defs.mak EXTRA_LIBS = ${MAIN_EXTRA_LIBS} DFLAGS += -DIRSIM_DATE="\"`date`\"" LIBS += ${GR_LIBS} -lm CLEANS += irsim.sh irsim.tcl irsimexec SRCS += ${GR_SRCS} CFLAGS += -I${IRSIMDIR}/base -I${IRSIMDIR}/analyzer TCL_FILES = \ $(DESTDIR)${TCLDIR}/tkcon.tcl \ $(DESTDIR)${TCLDIR}/console.tcl \ $(DESTDIR)${TCLDIR}/vcd.tcl \ $(DESTDIR)${TCLDIR}/irsim.tcl tcl-main: irsimexec irsim.tcl irsim.sh install-tcl: irsimexec $(DESTDIR)${BINDIR}/irsim.sh ${TCL_FILES} ${RM} $(DESTDIR)${TCLDIR}/irsimexec ${CP} irsimexec $(DESTDIR)${TCLDIR}/irsimexec irsimexec: irsimexec.c tclirsim.o ${CC} ${CFLAGS} ${CPPFLAGS} ${DFLAGS} irsimexec.c -o irsimexec \ ${LIBS} ${LIB_SPECS} irsim.tcl: irsim.tcl.in sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \ -e /SHDLIB_EXT/s%SHDLIB_EXT%${SHDLIB_EXT}%g \ irsim.tcl.in > irsim.tcl irsim.sh: irsim.sh.in sed -e /TCL_DIR/s%TCL_DIR%${TCLDIR}%g \ -e /TCLLIB_DIR/s%TCLLIB_DIR%${TCL_LIB_DIR}%g \ -e /WISH_EXE/s%WISH_EXE%${WISH_EXE}%g \ irsim.sh.in > irsim.sh $(DESTDIR)${TCLDIR}/%: % ${RM} $(DESTDIR)${TCLDIR}/$* ${CP} $* $(DESTDIR)${TCLDIR}/$* $(DESTDIR)${BINDIR}/irsim.sh: irsim.sh ${RM} $(DESTDIR)${BINDIR}/irsim.sh $(DESTDIR)${BINDIR}/irsim ${CP} irsim.sh $(DESTDIR)${BINDIR}/irsim (cd $(DESTDIR)${BINDIR}; chmod 0755 irsim) include ${IRSIMDIR}/rules.mak irsim-9.7.93/tcltk/Depend0000644000175000001440000000066310416553134013730 0ustar timuserstclirsim.o: tclirsim.c ../base/defs.h ../base/net.h ../base/globals.h \ ../base/rsim.h tclanalyzer.o: tclanalyzer.c ../base/globals.h ../base/net.h \ ../analyzer/ana.h ../base/defs.h ../analyzer/ana_glob.h \ ../analyzer/graphics.h lookup.o: lookup.c ../base/globals.h ../base/net.h tkAnalyzer.o: tkAnalyzer.c ../analyzer/ana.h ../base/net.h ../base/defs.h \ ../analyzer/ana_glob.h ../base/rsim.h tkTag.o: tkTag.c ../base/net.h irsim-9.7.93/tcltk/tclirsim.c0000664000175000001440000004651412605757014014614 0ustar timusers/*----------------------------------------------------------------------*/ /* tclirsim.c --- Creates the interpreter-wrapped version of irsim */ /* */ /* Written by Tim Edwards November 2002 */ /* */ /*----------------------------------------------------------------------*/ #define _GNU_SOURCE #include #include #include #include /* Ctrl-C interrupt handling */ #include #include #include "defs.h" #include "net.h" #include "globals.h" #include "rsim.h" /* * Handling of VA_COPY. These variables are set by the configuration * script. Some systems define va_copy, some define __va_copy, and * some don't define it at all. It is assumed that systems which do * not define it at all allow arguments to be copied with "=". */ #ifndef HAVE_VA_COPY #ifdef HAVE___VA_COPY #define va_copy(a, b) __va_copy(a, b) #else #define va_copy(a, b) a = b #endif #endif Tcl_Interp *irsiminterp; Tcl_Interp *consoleinterp; private int UseTkConsole = TRUE; extern char *filename; /* current input file (see rsim.h) */ extern int lineno; /* current line number */ extern char *first_file; /* basename of network file read-in */ extern int targc; extern char **targv; extern Command cmds[]; extern char wildCard[MAXARGS]; extern void Tcl_stdflush(); extern void InitTkAnalyzer(); extern void TagInit(); extern int IrsimTagCallback(); extern void enable_interrupt(); extern void disable_interrupt(); extern Tcl_Obj *list_all_vectors(); private int InterruptPending = FALSE; private void (*oldinthandler)() = SIG_DFL; int tclirsim_base(); int tclirsim_marker(); int tclirsim_print(); int tclirsim_simtime(); int tclirsim_trace(); int tclirsim_zoom(); Command anacmds[] = { {"base", tclirsim_base, 1, 4, "base get|set [trace] [bin|oct|hex]", 0}, {"marker", tclirsim_marker, 1, 4, "marker [1|2] set|move|delta...", 0}, {"print", tclirsim_print, 1, 3, "print [|