shers@mit-caf.MIT.EDU (Alex Sherstinsky) (11/24/88)
The source code for a new switch level simulator for MOS digital ICs is included below in a "shar" format. The new switch level simulator has certain advantages and disadvantages compared to the existing switch level simulators. The program is distributed free of charge to any person or organization willing to observe the copyright formalities and to send comments, criticism, and suggestions to the author. Very Best Wishes, Alex Sherstinsky (shers@caf.mit.edu) ---- Cut Here and unpack ---- #!/bin/sh # shar: Shell Archiver (v1.22) # # Run the following text with /bin/sh to create: # slic.doc # .exrc # Makefile # args.h # dump.h # files.h # func.h # hash.h # main.h # queue.h # runsim.h # state.h # tech.h # args.c # dump.c # files.c # func.c # hash.c # main.c # queue.c # runsim.c # state.c # if test -f slic.doc; then echo "File slic.doc exists"; else echo "x - extracting slic.doc (Text)" sed 's/^X//' << 'SHAR_EOF' > slic.doc && X SLIC: Switch Level Integrated Circuits Simulator X X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu X X X Background X X X One of the crucial steps in the design of a digital IC is X Xthe verification of the layout of individual cells and, ulti- X Xmately, the entire chip. This problem can be approached using X Xtwo different strategies: net-list comparison and logic simula- X Xtion. If the chip is laid out using an automatic layout genera- X Xtor, then it is advantageous to extract the resulting layout into X Xa net-list and compare it with the net-list extracted from a X Xbehavioral model of the system. On the other hand, a simulation X Xof the system on the transistor level is a more appropriate X Xchoice for designs laid out manually. The purpose of the simula- X Xtion would be to check the operation of the chip and to detect X Xerrors in circuit design and layout. SPICE is a circuit simula- X Xtor that uses the most accurate models for transistors, capaci- X Xtors, etc. However, running SPICE on large circuits is infeasi- X Xble using a standard computer resource. Hence, a need arises for X Xa simulator whose models for circuit elements are simple enough X Xto make simulations run faster and yet adequate to capture the X Xessentials of the circuit's performance. X X X In digital circuits, signals are expected to take on only a X Xfew discrete levels (e.g., low, high, and don't-care). In this X Xcase, a simulation model that treats MOS transistors as switches X Xcan be explored to yield an acceptable degree of accuracy. X X X The main objective of the switch level simulator presented X Xin this document is to be able to handle, under a certain set of X Xassumptions, as wide a variety of MOS circuit topologies as pos- X Xsible (transmission gates, flip flops, etc.) without the need for X Xthe user to intervene on the circuit level. Typical examples of X Xuser intervention are: giving directionality to signal flow in X Xmosfets, assigning higher capacitive weight to some nodes rela- X Xtive to others, and so on. X X Introduction To SLIC X X X A logic circuit consists of a set of nodes connected by MOS X Xtransistors. When modeling mosfet circuits, the simulator com- X Xputes the logical behavior in a highly idealized way according to X Xa switch level algorithm presented below. This approach has the X Xpotential to capture many of the subtleties of MOS circuit opera- X Xtion, such as ratioed circuits, charge sharing, bidirectional X Xtransmission gates (pass transistors), MOS diodes, and precharged X Xlogic. However, the simulator makes no attempt to model the X Xactual circuit timing; the simulator cannot be used to measure X Xthe speed of a circuit, and it may yield incorrect results when X Xthe circuit behavior is sensitive to delays. Even though a wide X Xvariety of circuits can be modeled at the switch level, there X Xremains one important circuit phenomenon that SLIC does not X Xcapture (because of the lack of timing in its switch level X Xmodel): transient charge sharing. Circuits which rely on this X Xphenomenon to override a feedback value cannot be modeled. The X Xuser must either redesign these circuits, or change the timing of X Xcontrol signals. X X X In order to benefit the most from SLIC, the following design X Xmethodology for digital NMOS or CMOS projects should be used: X X1. Perform all timing and transient charge sharing X X simulations with simulators that do handle timing, such as X X SPICE and CRYSTAL. X X2. Once timing has been figured out and accepted, X X run SLIC on the cell to check the logic. X X3. After that, connect all the cells into blocks X X of higher and higher abstraction and run SLIC to check the X X functionality and, thereby, layout. X X X SLIC is thus ideal for projects with clearly defined clocked X Xdata paths. X X X Provided circuits are designed and laid out to make them X Xinsensitive to SLIC's limitations, here is a list of the capabil- X Xities of SLIC: X X1. All purely combinational circuits. This includes X X domino logic. SLIC has no problems with transmission gates, X X and can simulate as well as detect W/L circuit design errors X X in the famous six transistor CMOS "exclusive OR" (6tXOR) X X gate. X X2. SLIC can simulate a limited variety of SRAM X X and DRAM designs. X X3. SLIC cannot handle unstable circuits X X such as ring oscillators. X X X SLIC requires no user intervention on the circuit level X X(i.e., specifying directionality for mosfets, resizing node capa- X Xcitances, etc.). However, a limited degree of user intervention X Xis allowed on the command level. The user can initialize arbi- X Xtrary nodes at the beginning of the simulation run in order to X Xstart the circuit in a desired state. X X I/O File Formats Used By SLIC X X X SLIC reads the ".sim" file (UC Berkeley format). Here are X Xthe tokens in the ".sim" file, which SLIC uses to read mosfets: X Xmos_type gate_name source_name drain_name length width, X Xwhere the ordering of source and drain node names is interchange- X Xable; and capacitors: X XC node_name substrate_node_name. X XFor example, here is a ".sim" file for a CMOS inverter: X X| units: 100 tech: scmos Xp in Vdd out 2 20 Xn in GND out 2 10 XC in GND 120 XC Vdd GND 110 XC GND GND 300 XC out GND 200 X X X The commands that drive SLIC (and thus should be contained X Xin the ".drive" file) are the specification of inputs, clocks, X Xoutputs, and initialization (preset) of nodes. SLIC supports X Xcomments as long as the first character on the line is "|". SLIC X Xinterprets all of its commands and bit values in a case insensi- X Xtive fashion. Power and ground are treated as ordinary inputs. X XThe clocks sequence through all of their values for each value of X Xother inputs. The last bit of an input (or a clock) is used again X Xin the next cycle of the simulation if the index of that bit is X Xless than the index of the bit of some other input (or a clock). X XThis feature is common to many switch level simulators. X X X The simulation program is designed primarily for simulating X Xclocked systems, where a clocking scheme consists of a set of X Xstate sequences to be applied cyclically to a set of input nodes. X XThe program assumes that the circuit clocks operate slowly enough X Xfor the entire circuit to stabilize between each change of clock X Xand input data values. For synchronous circuits, the flow of X Xtime can be viewed at four levels of granularity: X Xcycle: A complete sequencing of the clocks. Xphase: A period in which all clock and input X values remain constant. Xstep: The basic simulation time unit. X Within a phase, unit steps are simulated until the net- X work reaches a stable state, or the step limit is X exceeded. X X X Unclocked circuits can also be simulated by interacting with X Xthe user at the phase level. For a combinational circuit, each X Xphase represents the propagation of a set of values from the X Xinputs to the outputs. For an asynchronous circuit, each phase X Xrepresents a reaction by the circuit to a change in the control X Xlines implementing the communication protocol (generally some X Xform of hand-shaking). X X| This is an example of a ".drive" file. X| X| Supplies X| XI Vdd 1 XI GND 0 X| X| Initialize the state of a T flip flop. X| XP TFFQ 1 X| X| Specification of a two phase non overlapping X| clock sequence. X| X| Observe that this pattern requires four X| simulation phases. In phases 1 and X| 3, one clock is active, while in in phases 2 X| and 4, both clocks are inactive. X| These inactive phases are required to model the X| nonoverlapping period of the clocks. X| XC phi1 1000 XC phi2 0010 X| X| All other inputs. X| XI A 001101XX0010 XI B 0101XX10 X| X| Note that the last "0" in the value sequence X| for B will be used for all X| remaining vectors of the simulation. X| X| The specification of output (observation) nodes. X| XO DataOut XO Control X X X In this example, the same values for Vdd and GND are used X Xthroughout the entire duration of the longest input bit string X X(input A). The specified outputs will be reported in the ".res" X Xfile (the file of results) at the end of the simulation. X X X The symbols in the ".res" file are: X X X1 -- logic high with drive X0 -- logic low with drive XH -- logic high without drive XL -- logic low without drive XX -- logic don't-care with or without drive X X X Here is an example of a ".res" file: X X>XX0101011H0L:DataOut X>X01101001010:Control X X X The simulator assumes that when the circuit does not reach a X Xstable state within a fixed number of unit steps (determined by X Xthe step limit), an unbounded oscillation has occurred. It will X Xthen stop the simulation phase and print an error message. X X Switch Level Model X X X In SLIC, a logic circuit is thought of having two types of X Xelements: X XMosfet: An MOS transistor acting as either a switch X that can connect its source and drain terminals, or as a X diode, depending on the state of its gate, source, and X drain terminals. XNode: An electrical node acting as either a signal X source (input) to the circuit, or a capacitor that can X store charge dynamically. X XNodes can be divided into two categories: X XInput: Provide strong signals from sources external X to the network (e.g., power, ground, clock, and data X inputs). XStorage: Have states determined by the operation of X the network and can retain these states in the absence of X applied signals. X X X A mosfet is a three terminal device with node connections X Xgate, source, and drain. There is no distinction between source X Xand drain connections -- the mosfet is a symmetric, bidirectional X Xdevice. The simulator models three types of mosfets: n-type, p- X Xtype, and depletion. A mosfet acts as a switch or a diode X Xbetween source and drain, controlled by the state of its gate, X Xsource, and drain electrodes as follows: X X XNMOS: X Xgate source drain intended data flow mode X------------------------------------------------------------- X0 X X either direction switch-off X1 0 X source to drain switch-on X1 1 0 source to drain diode-on X1 1 1 source to drain diode-off X1 X 0 drain to source switch-on X1 0 1 drain to source diode-on X1 1 1 drain to source diode-off X XPMOS: X Xgate source drain intended data flow mode X------------------------------------------------------------- X1 X X either direction switch-off X0 1 X source to drain switch-on X0 0 0 source to drain diode-off X0 0 1 source to drain diode-on X0 X 1 drain to source switch-on X0 0 0 drain to source diode-off X0 1 0 drain to source diode-on X XDNMOS: X Xgate source drain intended data flow mode X------------------------------------------------------------- X0 1 1 either direction switch-off X0 1 0 source to drain diode-on XX 0 X source to drain switch-on X1 1 X source to drain switch-on X0 0 1 drain to source diode-on XX X 0 drain to source switch-on X1 X 1 drain to source switch-on X X X Each mosfet has a strength associated with it, which equals X Xto its W/L ratio for NMOS transistors and W/L ratio divided by X Xthe ratio of the mobilities of electrons and holes for PMOS X Xtransistors. Strength of a mosfet indicates (in a simplified way) X Xits conductance when turned on relative to other mosfets which X Xmay form part of a ratioed path. X X X The Abstract Data Type (ADT) for each mosfet can access all X Xof the nodes associated with the mosfet terminals. The ADT for X Xeach node can access all of the mosfets connected to that node. X XWith these ADTs, it is possible to start at any node or mosfet X Xand visit all nodes and mosfets in the network. This property is X Xused for traversing charge shared sub-networks. X X X Each node in SLIC has a notion of "drive" associated with X Xit. The logic state of a node is represented by one of three X Xlogic values: X X X0 low X1 high XX invalid (between 0 and 1), or uninitialized X XA node having one of the above logic values can have any value of X Xdrive, the lowest being no drive (high impedance state). The X Xexternal input nodes have infinite drive; the nodes that are X Xdisconnected from the rest of the network have no drive. When X Xthere is at least one path of conducting mosfets to a storage X Xnode from some input node(s), the node is driven to a logic state X Xdependent only on the strongest path(s), where the drive of any X Xnode terminating a path is less than the minimum transistor X Xstrength in the path. The drive of a node in a path is computed X Xaccording to the same formula as the net conductance of a series X Xconnection of conductances. Thus a stronger signal will always X Xoverride a weaker one, regardless of the logic value. This means X Xthat SLIC does not model signal dependent drive accurately. X XNevertheless, a design style that eliminates the concern for sig- X Xnal dependent drive is simpler, not much less area efficient, and X Xis common. X X X Each storage node has a capacitance (to substrate) computed X Xfor it based on the information in the ".sim" file. Input nodes X Xhave infinite capacitance by convention. X X Principle Of Operation Of SLIC X X X SLIC reads the ".sim" file and constructs a hash table of X Xnodes. Folded mosfets connected to the same set of terminals X X(comb structures) are merged into a single mosfet of combined X Xstrength. Prior to the first vector of the simulation, the X Xpreset nodes receive the specified initialization values, but no X Xdrive. X X X A simulation of a network with SLIC involves two processes: X Xpropagation of drive and charge sharing. During one step, a X Xqueue consisting of nodes that need to be evaluated is main- X Xtained. The queue is comprised of perturbed nodes and of nodes X Xthat are electrically connected to perturbed nodes via conducting X Xmosfets. Propagation of drive and charge sharing are applied to X Xeach node in the queue, obeying the following precedence (in the X Xorder of decreasing capability): input nodes (infinite current, X Xinfinite capacitance), nodes with drive (finite current, infinite X Xcapacitance), nodes with no drive (zero current, finite capaci- X Xtance). X X X Drive is propagated from external inputs to as many nodes in X Xthe network as possible, one node at a time. Modulated by mos- X Xfets, drive flows throughout the network, thereby updating nodal X Xlogic values. All mosfets attached to each node are evaluated X Xusing the switch level model. The evaluation of a mosfet amounts X Xto computing the drive the given mosfet is capable of imparting X Xto the node, based on the logic values and drives present at the X Xmosfet's terminals. For each logic value (low, high, don't- X Xcare), the maximum drive available from the node's mosfets is X Xcomputed. The highest of these drives and the corresponding X Xlogic value are assigned to be the node's next drive and logic X Xvalue, after which the node's ADT is updated. This implies that X Xthe node's parameters can influence the rest of the network as X Xsoon as the node has been updated. In other words, mosfets have X Xzero delay. The use of the zero-delay mosfet model speeds up the X Xpropagation of drive and eliminates difficulties in getting cir- X Xcuits with positive feedback to settle during simulation. X X X Charge sharing is attempted among the nodes that are not X Xdriven, starting with the node for which the propagation of drive X Xhas just been performed. When a set of connected storage nodes is X Xisolated from any input nodes, they are charged to a logic state X Xdependent only on the state(s) of the node(s) with the largest X Xcapacitance. Thus the value on a more capacitive node will X Xalways override the value on a less capacitive one. Charge shar- X Xing sub-networks are formed from electrically connected (i.e., X Xseparated by conducting mosfets) groups of non driven nodes. The X Xcapacitances of every node in a charge sharing sub-network can be X Xfound charged to one of the three possible logic values: low, X Xhigh, or don't-care. Thus for each group, three equivalent capa- X Xcitances are formed according to the logic level. The final X Xcharge shared logic value for all nodes in the group is decided X Xbased on the relative sizes of the three equivalent capacitances. X X X Propagation of drive and charge sharing process pair is X Xrepeated until the entire network settles, or the step limit is X Xexceeded. X X X X X References X X X X[1] R. E. Bryant, "A Switch-Level Model and Simulator for X X MOS Digital Systems," IEEE Transactions on Computers C- X X 33(2):160-177, February, 1984. SHAR_EOF chmod 0644 slic.doc || echo "restore of slic.doc fails" fi if test -f .exrc; then echo "File .exrc exists"; else echo "x - extracting .exrc (Text)" sed 's/^X//' << 'SHAR_EOF' > .exrc && Xset ai sm sw=4 SHAR_EOF chmod 0644 .exrc || echo "restore of .exrc fails" fi if test -f Makefile; then echo "File Makefile exists"; else echo "x - extracting Makefile (Text)" sed 's/^X//' << 'SHAR_EOF' > Makefile && X# Makefile for the Switch Level Integrated Circuits simulator (SLIC) X#****************************************************************************** X#Author: X# Alex Sherstinsky, X# Microsystems Technology Laboratories, X# Building 39, Room 611, X# Massachusetts Institute Of Technology, X# 77 Massachusetts Avenue, X# Cambridge, MA 02139 X# Telephone: (617)253-0710 X# Electronic Mail Address: shers@caf.mit.edu X#Copyright 1988 Massachusetts Institute Of Technology X#All rights reserved. X#This program may not be distributed to other organizations without the X#permission of the author. In no case may it be distributed outside the X#United States and Canada. This program is supplied "as is", without any X#kind of warranty, and M.I.T. does not promise to support it in any way. X#This program is not to be incorporated into a commercial product, or access X#to it sold, without prior written agreement from the author. X#****************************************************************************** X#SLIC X#****************************************************************************** X# Leaves executable file in slic X X#Compiler flags for debugging. X#cflags = -g X#Compiler flags for optimizing. Xcflags = -O Xhead = main.h dump.h runsim.h state.h hash.h queue.h files.h args.h tech.h \ X func.h Xobjs = main.o dump.o runsim.o state.o hash.o queue.o files.o args.o func.o Xsrcs = main.c dump.c runsim.c state.c hash.c queue.c files.c args.c func.c X Xslic: $(objs) X cc $(cflags) $(objs) -o slic X Xmain.o: main.c func.h tech.h args.h files.h queue.h hash.h state.h runsim.h \ X main.h X cc -c $(cflags) main.c X Xdump.o: dump.c func.h queue.h dump.h X cc -c $(cflags) dump.c X Xrunsim.o: runsim.c func.h tech.h state.h queue.h runsim.h X cc -c $(cflags) runsim.c X Xstate.o: state.c func.h tech.h queue.h hash.h runsim.h state.h X cc -c $(cflags) state.c X Xhash.o: hash.c func.h tech.h runsim.h state.h queue.h hash.h X cc -c $(cflags) hash.c X Xqueue.o: queue.c func.h queue.h X cc -c $(cflags) queue.c X Xfiles.o: files.c func.h files.h X cc -c $(cflags) files.c X Xargs.o: args.c func.h args.h X cc -c $(cflags) args.c X Xfunc.o: func.c func.h X cc -c $(cflags) func.c X Xclean: X /bin/rm $(objs) X Xlint: X lint -u -z $(srcs) X Xtar: X cd ..; tar -crf slic.tar Slic; cd Slic; /bin/mv ../slic.tar . SHAR_EOF chmod 0644 Makefile || echo "restore of Makefile fails" fi if test -f args.h; then echo "File args.h exists"; else echo "x - extracting args.h (Text)" sed 's/^X//' << 'SHAR_EOF' > args.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module obtains and processes the command line arguments. X*/ X X/* XThe functions that obtain and process the command line arguments. X*/ X Xvoid ProcessArgs(); SHAR_EOF chmod 0644 args.h || echo "restore of args.h fails" fi if test -f dump.h; then echo "File dump.h exists"; else echo "x - extracting dump.h (Text)" sed 's/^X//' << 'SHAR_EOF' > dump.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module prints the values of output vectors into the ".res" (results) file. X*/ X X/* XFunctions used. X*/ X Xvoid DumpRes(); SHAR_EOF chmod 0644 dump.h || echo "restore of dump.h fails" fi if test -f files.h; then echo "File files.h exists"; else echo "x - extracting files.h (Text)" sed 's/^X//' << 'SHAR_EOF' > files.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XModule for opening and closing relevant files. X*/ X X/* XFunctions used for dealing with files. X*/ X Xvoid OpenFiles(); Xvoid CloseFiles(); SHAR_EOF chmod 0644 files.h || echo "restore of files.h fails" fi if test -f func.h; then echo "File func.h exists"; else echo "x - extracting func.h (Text)" sed 's/^X//' << 'SHAR_EOF' > func.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XUseful library declarations. X*/ X XFILE * fopen(); Xint fclose(); Xvoid perror(); Xvoid exit(); Xchar * malloc(); Xchar * calloc(); Xvoid free(); Xchar * fgets(); Xint sscanf(); Xint strlen(); Xint strcmp(); Xint strncmp(); Xchar * strcpy(); Xchar * strncpy(); Xchar * strcat(); Xchar * strncat(); Xint fprintf(); Xchar * sprintf(); Xdouble atof(); X X/* XUseful constants. X*/ X X#define RANDOM_MULTIPLIER 25173/*multiplier used in random number generator*/ X#define RANDOM_INCREMENT 13849/*increment used in random number generator*/ X#define RANDOM_MODULUS 65536/*modulus used in random number generator*/ X X/* XUseful functions. X*/ X Xint MinInt(); Xfloat MinFloat(); Xint MaxInt(); Xfloat MaxFloat(); Xvoid SwapInt(); Xvoid SwapFloat(); Xint AbsInt(); Xfloat AbsFloat(); Xint SquareInt(); Xfloat SquareFloat(); Xint Odd(); Xint Xor(); Xchar * IntToChar(); Xchar * CharToString(); Xchar * ReverseString(); Xchar * GoRev(); Xchar * MidString(); Xchar * AllocateString(); Xfloat Random(); SHAR_EOF chmod 0644 func.h || echo "restore of func.h fails" fi if test -f hash.h; then echo "File hash.h exists"; else echo "x - extracting hash.h (Text)" sed 's/^X//' << 'SHAR_EOF' > hash.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module manages the hash table ADT. X*/ X X/* XUseful constants. X*/ X X#define HASH_SIZE 11731/*number of node queue entries in the hash table*/ X X/* XThe ADT for the hash table of nodes. X*/ X Xtypedef struct nhashtab { X char *name; X int node_count; X NQUEUE *nqueue_array[HASH_SIZE]; X} NHASHTAB; X X/* XFunctions used to construct the hash table of nodes. X*/ X XNHASHTAB * NHashInit(); XNODE * NHashPut(); XNODE * NHashGet(); Xint HashFunction(); SHAR_EOF chmod 0644 hash.h || echo "restore of hash.h fails" fi if test -f main.h; then echo "File main.h exists"; else echo "x - extracting main.h (Text)" sed 's/^X//' << 'SHAR_EOF' > main.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThe main function that performs the Switch Level Integrated Circuits Xsimulation (SLIC). X*/ X Xvoid main(); SHAR_EOF chmod 0644 main.h || echo "restore of main.h fails" fi if test -f queue.h; then echo "File queue.h exists"; else echo "x - extracting queue.h (Text)" sed 's/^X//' << 'SHAR_EOF' > queue.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module manages all queue ADTs. X*/ X X/* XThe nil number to be coerced into the nil pointer on demand by XMOSFET, NODE, and SIGNAL ADTs. X*/ X X#define NIL -1 X X/* XThe ADT for storing the relevant information about mosfets. X*/ X Xtypedef struct mosfet { X char mosfet_type; X struct node *term[3];/*gate, source, and drain nodes of a mosfet*/ X short value[3];/*logic values for gate, source, and drain*/ X float drive[2];/*drive for source and drain*/ X float strength; X struct mosfet *link; X} MOSFET; X X/* XThe queue ADT for mosfets. X*/ X Xtypedef struct mqueue { X char *name; X MOSFET *head; X MOSFET *tail; X} MQUEUE; X X/* XThe ADT for storing the relevant information about nodes. X*/ X Xtypedef struct node { X char *name; X short present_value; X short next_value; X float present_drive; X float next_drive; X float capacitance;/*node capacitance in fF*/ X short perturbed;/*flag indicating whether node drive or value changed*/ X short acquired;/*flag used to mark nodes traversed during charge sharing*/ X short set;/*flag used to mark nodes set during charge sharing*/ X MQUEUE *mosfet_queue; X struct node *link; X} NODE; X X/* XThe queue ADT for nodes. X*/ X Xtypedef struct nqueue { X char *name; X NODE *head; X NODE *tail; X} NQUEUE; X X/* XThe ADT for storing the relevant information about signals. X*/ X Xtypedef struct signal { X char signal_type; X char *name; X char *value_sequence; X NODE *node; X struct signal *link; X} SIGNAL; X X/* XThe queue ADT for signals. X*/ X Xtypedef struct squeue { X char *name; X SIGNAL *head; X SIGNAL *tail; X} SQUEUE; X X/* XFunctions used to construct queues of mosfets, nodes, and signals. X*/ X XMQUEUE * MQInit(); Xvoid MQPut(); XMOSFET * MQGet(); XMOSFET * MakeMosfet(); XNQUEUE * NQInit(); Xvoid NQPut(); XNODE * NQGet(); XNODE * MakeNode(); XSQUEUE * SQInit(); Xvoid SQPut(); XSIGNAL * SQGet(); XSIGNAL * MakeSignal(); SHAR_EOF chmod 0644 queue.h || echo "restore of queue.h fails" fi if test -f runsim.h; then echo "File runsim.h exists"; else echo "x - extracting runsim.h (Text)" sed 's/^X//' << 'SHAR_EOF' > runsim.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module performs the mechanics of the switch level simulation. X*/ X X/* XUseful constants. X*/ X X#define MAX_STEP 128/*max number of steps allowed to settle network*/ X#define SUPER_DRIVE 1.0e6/*given to input nodes*/ X#define SUPER_CAPACITANCE 1.0e6/*given to input nodes*/ X#define NO_DRIVE 0.0/*given to nodes with no driving capability*/ X#define LOGIC_DONTCARE (-1)/*value of logic dontcare (with or without drive)*/ X#define LOGIC_LOW 0/*value of logic 0 (with drive)*/ X#define LOGIC_HIGH 1/*value of logic 1 (with drive)*/ X X/* XFunctions used for the mechanics of SLIC. X*/ X Xvoid RunSim(); Xvoid ApplyInputVector(); Xvoid DrivePropagation(); Xvoid ChargeSharing(); Xvoid MosfetAction(); Xint MosfetOn(); Xvoid MosfetActive(); Xvoid MosfetDisable(); Xvoid EvaluateNode(); Xvoid GetNodeDrive(); Xvoid SortDrive(); Xvoid UpdateNode(); Xvoid ResolveConflict(); Xvoid RemoveStatic(); Xvoid AccumulateCSValue(); Xvoid SortCapacitance(); Xshort DetermineCSValue(); Xvoid SetCSValue(); Xvoid NodeStats(); Xvoid GenerateEvents(); Xvoid AssignInputs(); Xvoid AssignClocks(); Xvoid AssignPreset(); Xvoid AssignOutputs(); SHAR_EOF chmod 0644 runsim.h || echo "restore of runsim.h fails" fi if test -f state.h; then echo "File state.h exists"; else echo "x - extracting state.h (Text)" sed 's/^X//' << 'SHAR_EOF' > state.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis module allocates space for and fills in the state ADTs for SLIC. X*/ X X/* XUseful constants. X*/ X X#define NMOS 'n'/*symbol for nmos in ".sim" file*/ X#define PMOS 'p'/*symbol for pmos in ".sim" file*/ X#define ENMOS 'e'/*symbol for enhancement nmos in ".sim" file*/ X#define DNMOS 'd'/*symbol for depletion nmos in ".sim" file*/ X#define CAPACITOR 'C'/*symbol for non mosfet capacitance in ".sim" file*/ X#define READ 0/*flag to read node hash table*/ X#define WRITE 1/*flag to create node hash table*/ X#define MAXBITS 64/*max number of bits in an input sequence*/ X#define COMMAND_LENGTH 64/*max number of extra chars in a drive command*/ X#define MAX_TOKENS 8/*max number of tokens in a line of ".sim" file*/ X#define MAX_TOKEN_LENGTH 64/*max number of chars in a terminal name*/ X#define SIM_LINE_LENGTH (MAX_TOKENS * MAX_TOKEN_LENGTH) X X/* XFunctions used for allocating and building the state space for SLIC. X*/ X Xvoid BuildState(); Xvoid BuildDrive(); Xvoid BuildNetwork(); Xvoid ReadSimNetlist(); Xvoid ParseSimLine(); Xvoid ReadMosfet(); Xvoid ReadCapacitor(); Xvoid CombineMosfet(); Xvoid ConnectInputsNodes(); Xvoid ConnectClocksNodes(); Xvoid ConnectPresetNodes(); Xvoid ConnectOutputsNodes(); Xvoid CreateNodeQueue(); SHAR_EOF chmod 0644 state.h || echo "restore of state.h fails" fi if test -f tech.h; then echo "File tech.h exists"; else echo "x - extracting tech.h (Text)" sed 's/^X//' << 'SHAR_EOF' > tech.h && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X/* XThis header file contains the essential information about the particular XMOS technology used. X*/ X X/* XUseful constants. X*/ X X#define STRENGTH_RATIO 2.0/*ratio of mobilities of electrons and holes*/ X#define COX 1.5/*mos gate oxide capacitance (fF/sq-micron)*/ X/*Mos diffusion capacitance is not yet included. Alex Sherstinsky, 10-27-88*/ X#define MIN_DRIVE 1.0/*min non zero drive allowed for a node*/ X#define CAP_FACTOR 10.0/*storage capability ratio for valid logic transfer*/ SHAR_EOF chmod 0644 tech.h || echo "restore of tech.h fails" fi if test -f args.c; then echo "File args.c exists"; else echo "x - extracting args.c (Text)" sed 's/^X//' << 'SHAR_EOF' > args.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "args.h" X X/* XThis function obtains and processes the command line arguments. X*/ X Xvoid XProcessArgs(argc, argv, sim_file_name, drive_file_name, res_file_name) Xint argc; Xchar **argv; Xchar *sim_file_name; Xchar *drive_file_name; Xchar *res_file_name; X X{ X if(argc < 2) { X (void) fprintf(stdout, "Syntax: slic sim_file_name\n"); X (void) exit(0); X } X (void) sscanf(argv[1], "%s", sim_file_name); X (void) strcpy(drive_file_name, sim_file_name); X (void) strcpy(res_file_name, sim_file_name); X (void) strcat(sim_file_name, ".sim"); X (void) strcat(drive_file_name, ".drive"); X (void) strcat(res_file_name, ".res"); X} SHAR_EOF chmod 0644 args.c || echo "restore of args.c fails" fi if test -f dump.c; then echo "File dump.c exists"; else echo "x - extracting dump.c (Text)" sed 's/^X//' << 'SHAR_EOF' > dump.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "queue.h" X#include "dump.h" X X/* XThis routine prints the values of output vectors into the ".res" (results) Xfile. X*/ X Xvoid XDumpRes(res_file, output_queue) XFILE *res_file; XSQUEUE *output_queue; X X{ X SIGNAL *output; X X for(output = output_queue->head; output != ((SIGNAL *) NIL); X output = output->link) { X (void) fprintf(res_file, ">%s:%s\n", X output->value_sequence, output->name); X } X} SHAR_EOF chmod 0644 dump.c || echo "restore of dump.c fails" fi if test -f files.c; then echo "File files.c exists"; else echo "x - extracting files.c (Text)" sed 's/^X//' << 'SHAR_EOF' > files.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "files.h" X X/* XOpens the relevant files. X*/ X Xvoid XOpenFiles(sim_file_name, drive_file_name, res_file_name, Xsim_file, drive_file, res_file) Xchar *sim_file_name; Xchar *drive_file_name; Xchar *res_file_name; XFILE **sim_file; XFILE **drive_file; XFILE **res_file; X X{ X if((*sim_file = (FILE *) fopen(sim_file_name, "r")) == NULL) { X (void) perror(sim_file_name); X (void) exit(1); X } X if((*drive_file = (FILE *) fopen(drive_file_name, "r")) == NULL) { X (void) perror(drive_file_name); X (void) exit(1); X } X if((*res_file = (FILE *) fopen(res_file_name, "w")) == NULL) { X (void) perror(res_file_name); X (void) exit(1); X } X} X X/* XCloses the opened files. X*/ X Xvoid XCloseFiles(sim_file, drive_file, res_file) XFILE **sim_file; XFILE **drive_file; XFILE **res_file; X X{ X (void) fclose(*sim_file); X (void) fclose(*drive_file); X (void) fclose(*res_file); X} SHAR_EOF chmod 0644 files.c || echo "restore of files.c fails" fi if test -f func.c; then echo "File func.c exists"; else echo "x - extracting func.c (Text)" sed 's/^X//' << 'SHAR_EOF' > func.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X X/* XReturns the minimum of two integers. X*/ X Xint XMinInt(int1, int2) Xint int1, int2; X X{ X return (int1 < int2) ? int1 : int2; X} X X/* XReturns the minimum of two floats. X*/ X Xfloat XMinFloat(float1, float2) Xfloat float1, float2; X X{ X return (float1 < float2) ? float1 : float2; X} X X/* XReturns the maximum of two integers. X*/ X Xint XMaxInt(int1, int2) Xint int1, int2; X X{ X return (int1 > int2) ? int1 : int2; X} X X/* XReturns the maximum of two floats. X*/ X Xfloat XMaxFloat(float1, float2) Xfloat float1, float2; X X{ X return (float1 > float2) ? float1 : float2; X} X X/* XSwaps two integers. X*/ X Xvoid XSwapInt(int1, int2) Xint *int1, *int2; X X{ X int tmp; X X tmp = *int1; X *int1 = *int2; X *int2 = tmp; X} X X/* XSwaps two floats. X*/ X Xvoid XSwapFloat(float1, float2) Xfloat *float1, *float2; X X{ X float tmp; X X tmp = *float1; X *float1 = *float2; X *float2 = tmp; X} X X/* XReturns absolute value of an integer. X*/ X Xint XAbsInt(int1) Xint int1; X X{ X return (int1 < 0) ? (- int1) : int1; X} X X/* XReturns absolute value of an float. X*/ X Xfloat XAbsFloat(float1) Xfloat float1; X X{ X return((float1 < 0) ? (- float1) : float1); X} X X/* XReturns the square of the input integer. X*/ X Xint XSquareInt(int1) Xint int1; X X{ X return(int1 * int1); X} X X/* XReturns the square of the input float. X*/ X Xfloat XSquareFloat(float1) Xfloat float1; X X{ X return(float1 * float1); X} X X/* XReturns 1 if the argument is an Odd integer; 0 otherwise. X*/ X Xint XOdd(int1) Xint int1; X X{ X return(int1 % 2); X} X X/* XReturns 1 if the only one of the arguments is 1. X*/ X Xint XXor(int1, int2) Xint int1; Xint int2; X X{ X return((int1 && !int2) || (!int1 && int2)); X} X X/* XReturns the character representation of an integer. X*/ X Xchar * XIntToChar(num) Xint num; X X{ X char string[10]; X int is_negative = 0; X char complete_string[10]; X X if(num < 0) { X is_negative = 1; X } X num = (int) AbsInt(num); X (void) strcpy(string, ""); X (void) strcpy(complete_string, "-"); X while(num / 10) { X (void) strcat(string, CharToString('0' + (num % 10))); X num /= 10; X } X (void) strcat(string, CharToString('0' + (num % 10))); X (void) strcpy(string, ReverseString(string)); X if(is_negative) { X (void) strcat(complete_string, string); X return(complete_string); X } else { X return(string); X } X} X X/* XMakes a string out of one character. X*/ X Xchar * XCharToString(ch) Xchar ch; X X{ X char string[2]; X X string[0] = ch; X string[1] = '\0'; X return(string); X} X X/* XReturns the string whose characters appear in reverse order. X*/ X Xchar * XReverseString(string) Xchar *string; X X{ X char tmp[10]; X X (void) strcpy(tmp, ""); X (void) strcpy(tmp, (char *) GoRev(string, tmp)); X return(tmp); X} X X/* XReturns the string whose characters are those of the first argument in reverse. X*/ X Xchar * XGoRev(string, tmp) Xchar *string; Xchar *tmp; X X{ X if(*(string+1) == '\0') { X return((char *) strcat(tmp, string)); X } else { X return((char *) strcat((char *) GoRev((string+1), tmp), X (char *) CharToString(*string))); X } X} X X/* XReturns the middle of three strings that comprise the overall string. X*/ X Xchar * XMidString(line) Xchar *line; X X{ X char *middle = (char *) malloc((unsigned) 121 * sizeof(char)); X char first[20]; X char third[20]; X X (void) sscanf(line, "%s %s %s", first, middle, third); X return(middle); X} X X/* XAllocates a string for a given number of characters and returns a pointer Xto it. X*/ X Xchar * XAllocateString(num_chars) Xint num_chars; X X{ X char *string = (char *) malloc((unsigned) (num_chars + 1) * sizeof(char)); X return(string); X} X X/* XThis function is a pseudo random number generator. X*/ X Xfloat XRandom(seed) Xint *seed; X X{ X *seed = ((RANDOM_MULTIPLIER * *seed) + RANDOM_INCREMENT) % RANDOM_MODULUS; X return((1.0 * *seed) / RANDOM_MODULUS); X} SHAR_EOF chmod 0644 func.c || echo "restore of func.c fails" fi if test -f hash.c; then echo "File hash.c exists"; else echo "x - extracting hash.c (Text)" sed 's/^X//' << 'SHAR_EOF' > hash.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "tech.h" X#include "runsim.h" X#include "state.h" X#include "queue.h" X#include "hash.h" X X/* XInitializes the hash table of nodes. X*/ X XNHASHTAB * XNHashInit(name) Xchar *name; X X{ X NHASHTAB *nhashtab; X int index; X char *string = (char *) malloc((unsigned) 10 * sizeof(char)); X X nhashtab = (NHASHTAB *) malloc(sizeof(NHASHTAB)); X nhashtab->name = (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(nhashtab->name, name); X nhashtab->node_count = 0; X for(index = 0; index < HASH_SIZE; index++) { X (void) sprintf(string, "%d", index); X (nhashtab->nqueue_array)[index] = (NQUEUE *) NQInit(string); X } X return(nhashtab); X} X X/* XHashes and puts a new node into the node hash table. X*/ X XNODE * XNHashPut(nhashtab, node_name, mosfet, mosfet_type, strength) XNHASHTAB *nhashtab; Xchar *node_name; XMOSFET **mosfet; Xchar mosfet_type; Xfloat strength; X X{ X int hash_number; X MQUEUE *mosfet_queue; X NODE *node; X X if(mosfet_type == PMOS) { X strength /= STRENGTH_RATIO; X } else if(!((mosfet_type == NMOS) || X (mosfet_type == ENMOS) || (mosfet_type == DNMOS))) { X (void) fprintf(stdout, "Error: Unknown mosfet type. Exit 1.\n"); X (void) exit(1); X } X if((node = (NODE *) NHashGet(nhashtab, WRITE, node_name, mosfet, X mosfet_type, strength)) == ((NODE *) NIL)) { X hash_number = (int) HashFunction(node_name); X (void) NQPut((nhashtab->nqueue_array)[hash_number], X node = (NODE *) MakeNode(node_name, X LOGIC_DONTCARE, LOGIC_DONTCARE, NO_DRIVE, NO_DRIVE, 1.0, 0, 0, 0, X mosfet_queue = (MQUEUE *) MQInit("mosfet_queue"))); X (void) MQPut(mosfet_queue, (*mosfet) = (MOSFET *) X MakeMosfet(mosfet_type, ((NODE *) NIL), ((NODE *) NIL), ((NODE *) NIL), X LOGIC_DONTCARE, LOGIC_DONTCARE, LOGIC_DONTCARE, X NO_DRIVE, NO_DRIVE, strength)); X (nhashtab->node_count)++; X } X return(node); X} X X/* XHashes and gets a node number (corresponding to the given node name) Xfrom the node hash table. X*/ X XNODE * XNHashGet(nhashtab, write, node_name, mosfet, mosfet_type, strength) XNHASHTAB *nhashtab; Xint write; Xchar *node_name; XMOSFET **mosfet; Xchar mosfet_type; Xfloat strength; X X{ X int hash_number; X NODE *node; X X if(((nhashtab->nqueue_array)[hash_number = X (int) HashFunction(node_name)])->head == ((NODE *) NIL)) { X return((NODE *) NIL); X } else { X for(node = ((nhashtab->nqueue_array)[hash_number])->head; X node != ((NODE *) NIL); node = node->link) { X if(!((int) strcmp(node_name, node->name))) { X if(write) { X (void) MQPut(node->mosfet_queue, *mosfet = X (MOSFET *) MakeMosfet(mosfet_type, X ((NODE *) NIL), ((NODE *) NIL), ((NODE *) NIL), X LOGIC_DONTCARE, LOGIC_DONTCARE, LOGIC_DONTCARE, X NO_DRIVE, NO_DRIVE, strength)); X } X return(node); X } X } X return((NODE *) NIL); X } X} X X/* XThis routine is a hash function for a node name hash into the node hash table. XThe ideal hash function returns a unique number for each distinct argument. XSince the number returned by the hash function must be less than the size of Xthe hash table, finding such a map is not simple. The hash function below uses Xthe node name argument in a way that reduces the probability of two different Xnames mapping into the same hash number. X*/ X Xint XHashFunction(name) Xchar *name; X X{ X int index; X int sum; X X for(index = 0, sum = 0; index < (int) strlen(name); index++) { X sum = sum * 13 + name[index] - '0'; X sum %= HASH_SIZE; X } X return((sum < 0) ? (sum + HASH_SIZE) : sum); X} SHAR_EOF chmod 0644 hash.c || echo "restore of hash.c fails" fi if test -f main.c; then echo "File main.c exists"; else echo "x - extracting main.c (Text)" sed 's/^X//' << 'SHAR_EOF' > main.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "tech.h" X#include "args.h" X#include "files.h" X#include "queue.h" X#include "hash.h" X#include "state.h" X#include "runsim.h" X#include "dump.h" X#include "main.h" X Xvoid Xmain(argc, argv) Xint argc; Xchar **argv; X X{ X FILE *sim_file; X FILE *drive_file; X FILE *res_file; X char *sim_file_name = (char *) malloc((unsigned) 100 * sizeof(char)); X char *drive_file_name = (char *) malloc((unsigned) 100 * sizeof(char)); X char *res_file_name = (char *) malloc((unsigned) 100 * sizeof(char)); X int mosfet_count = 0; X int node_count = 0; X SQUEUE *input_queue; X int input_count = 0; X int input_duration = 0; X SQUEUE *clock_queue; X int clock_count = 0; X int clock_duration = 0; X SQUEUE *preset_queue; X SQUEUE *output_queue; X int output_count = 0; X X (void) ProcessArgs(argc, argv, X sim_file_name, drive_file_name, res_file_name); X (void) OpenFiles(sim_file_name, drive_file_name, res_file_name, X &sim_file, &drive_file, &res_file); X (void) BuildState(sim_file, drive_file, X &input_queue, &clock_queue, &preset_queue, &output_queue, X &mosfet_count, &node_count, &input_count, &clock_count, X &output_count, &input_duration, &clock_duration); X if((mosfet_count == 0) || (node_count == 0)) { X (void) fprintf(stdout, "No network specified. Exit 0.\n"); X (void) exit(0); X } else if(input_count == 0) { X (void) fprintf(stdout, "Error: No inputs specified. Exit 1.\n"); X (void) exit(1); X } else if(input_duration == 0) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No input values specified. Exit 1.\n"); X (void) exit(1); X } else if(input_duration > MAXBITS) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Input bit string too long. Exit 1.\n"); X (void) exit(1); X } else if((clock_count != 0) && (clock_duration == 0)) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No clock values specified. Exit 1.\n"); X (void) exit(1); X } else if(clock_duration > MAXBITS) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Clock bit string too long. Exit 1.\n"); X (void) exit(1); X } else if(output_count == 0) { X (void) fprintf(stdout, "No outputs indicated to display. Exit 0.\n"); X (void) exit(0); X } else { X (void) RunSim(input_queue, clock_queue, preset_queue, X output_queue, input_duration, clock_duration, node_count); X (void) DumpRes(res_file, output_queue); X } X (void) CloseFiles(&sim_file, &drive_file, &res_file); X} SHAR_EOF chmod 0644 main.c || echo "restore of main.c fails" fi if test -f queue.c; then echo "File queue.c exists"; else echo "x - extracting queue.c (Text)" sed 's/^X//' << 'SHAR_EOF' > queue.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "queue.h" X X/* XInitializes the queue of mosfets. X*/ X XMQUEUE * XMQInit(name) Xchar *name; X X{ X MQUEUE *mqueue; X X mqueue = (MQUEUE *) malloc(sizeof(MQUEUE)); X mqueue->name = (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(mqueue->name, name); X mqueue->head = mqueue->tail = ((MOSFET *) NIL); X return(mqueue); X} X X/* XAppends a mosfet to the tail of a mosfet queue. X*/ X Xvoid XMQPut(mqueue, chunk) XMQUEUE *mqueue; XMOSFET *chunk; X X{ X if((mqueue->head == ((MOSFET *) NIL)) && X (mqueue->tail == ((MOSFET *) NIL))) { X mqueue->head = mqueue->tail = chunk; X } else { X mqueue->tail->link = chunk; X mqueue->tail = chunk; X } X chunk->link = ((MOSFET *) NIL); X} X X/* XReturns the mosfet at the head of the mosfet queue and updates Xthe mosfet queue. X*/ X XMOSFET * XMQGet(mqueue) XMQUEUE *mqueue; X X{ X MOSFET *chunk; X X if((mqueue->head == ((MOSFET *) NIL)) && X (mqueue->tail == ((MOSFET *) NIL))) { X return((MOSFET *) NIL); X } else if(mqueue->head == mqueue->tail) { X chunk = mqueue->head; X mqueue->head = mqueue->tail = ((MOSFET *) NIL); X return(chunk); X } else { X chunk = mqueue->head; X mqueue->head = mqueue->head->link; X return(chunk); X } X} X X/* XFills in the MOSFET ADT. X*/ X XMOSFET * XMakeMosfet(mosfet_type, gate_node, source_node, drain_node, Xgate_value, source_value, drain_value, Xsource_drive, drain_drive, strength) Xchar mosfet_type; XNODE *gate_node; XNODE *source_node; XNODE *drain_node; Xshort gate_value; Xshort source_value; Xshort drain_value; Xfloat source_drive; Xfloat drain_drive; Xfloat strength; X X{ X MOSFET *chunk; X X chunk = (MOSFET *) malloc(sizeof(MOSFET)); X chunk->mosfet_type = mosfet_type; X chunk->term[0] = gate_node; X chunk->term[1] = source_node; X chunk->term[2] = drain_node; X chunk->value[0] = gate_value; X chunk->value[1] = source_value; X chunk->value[2] = drain_value; X chunk->drive[0] = source_drive; X chunk->drive[1] = drain_drive; X chunk->strength = strength; X return(chunk); X} X X/* XInitializes the queue of nodes. X*/ X XNQUEUE * XNQInit(name) Xchar *name; X X{ X NQUEUE *nqueue; X X nqueue = (NQUEUE *) malloc(sizeof(NQUEUE)); X nqueue->name = (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(nqueue->name, name); X nqueue->head = nqueue->tail = ((NODE *) NIL); X return(nqueue); X} X X/* XAppends a node to the tail of a node queue. X*/ X Xvoid XNQPut(nqueue, chunk) XNQUEUE *nqueue; XNODE *chunk; X X{ X if((nqueue->head == ((NODE *) NIL)) && X (nqueue->tail == ((NODE *) NIL))) { X nqueue->head = nqueue->tail = chunk; X } else { X nqueue->tail->link = chunk; X nqueue->tail = chunk; X } X chunk->link = ((NODE *) NIL); X} X X/* XReturns the node at the head of the node queue and updates the node queue. X*/ X XNODE * XNQGet(nqueue) XNQUEUE *nqueue; X X{ X NODE *chunk; X X if((nqueue->head == ((NODE *) NIL)) && X (nqueue->tail == ((NODE *) NIL))) { X return((NODE *) NIL); X } else if(nqueue->head == nqueue->tail) { X chunk = nqueue->head; X nqueue->head = nqueue->tail = ((NODE *) NIL); X return(chunk); X } else { X chunk = nqueue->head; X nqueue->head = nqueue->head->link; X return(chunk); X } X} X X/* XFills in the NODE ADT. X*/ X XNODE * XMakeNode(name, present_value, next_value, present_drive, next_drive, Xcapacitance, perturbed, acquired, set, mosfet_queue) Xchar *name; Xshort present_value; Xshort next_value; Xfloat present_drive; Xfloat next_drive; Xfloat capacitance; Xshort perturbed; Xshort acquired; Xshort set; XMQUEUE *mosfet_queue; X X{ X NODE *chunk; X X chunk = (NODE *) malloc(sizeof(NODE)); X chunk->name = (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(chunk->name, name); X chunk->present_value = present_value; X chunk->next_value = next_value; X chunk->present_drive = present_drive; X chunk->next_drive = next_drive; X chunk->capacitance = capacitance; X chunk->perturbed = perturbed; X chunk->acquired = acquired; X chunk->set = set; X chunk->mosfet_queue = mosfet_queue; X return(chunk); X} X X/* XInitializes the queue of signals. X*/ X XSQUEUE * XSQInit(name) Xchar *name; X X{ X SQUEUE *squeue; X X squeue = (SQUEUE *) malloc(sizeof(SQUEUE)); X squeue->name = (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(squeue->name, name); X squeue->head = squeue->tail = ((SIGNAL *) NIL); X return(squeue); X} X X/* XAppends a signal to the tail of a signal queue. X*/ X Xvoid XSQPut(squeue, chunk) XSQUEUE *squeue; XSIGNAL *chunk; X X{ X if((squeue->head == ((SIGNAL *) NIL)) && X (squeue->tail == ((SIGNAL *) NIL))) { X squeue->head = squeue->tail = chunk; X } else { X squeue->tail->link = chunk; X squeue->tail = chunk; X } X chunk->link = ((SIGNAL *) NIL); X} X X/* XReturns the signal at the head of the signal queue and updates the signal queue. X*/ X XSIGNAL * XSQGet(squeue) XSQUEUE *squeue; X X{ X SIGNAL *chunk; X X if((squeue->head == ((SIGNAL *) NIL)) && X (squeue->tail == ((SIGNAL *) NIL))) { X return((SIGNAL *) NIL); X } else if(squeue->head == squeue->tail) { X chunk = squeue->head; X squeue->head = squeue->tail = ((SIGNAL *) NIL); X return(chunk); X } else { X chunk = squeue->head; X squeue->head = squeue->head->link; X return(chunk); X } X} X X/* XFills in the SIGNAL ADT. X*/ X XSIGNAL * XMakeSignal(signal_type, name, value_sequence, node, length) Xchar signal_type; Xchar *name; Xchar *value_sequence; XNODE *node; Xshort length; X X{ X SIGNAL *chunk; X X chunk = (SIGNAL *) malloc(sizeof(SIGNAL)); X chunk->signal_type = signal_type; X chunk->name = X (char *) malloc((unsigned) ((int) strlen(name) + 1) * X sizeof(char)); X (void) strcpy(chunk->name, name); X if((signal_type == 'O') || (signal_type == 'o')) { X chunk->value_sequence = X (char *) calloc((unsigned) (length + 1), sizeof(char)); X } else { X chunk->value_sequence = X (char *) malloc((unsigned) ((int) strlen(value_sequence) + 1) * X sizeof(char)); X (void) strcpy(chunk->value_sequence, value_sequence); X } X chunk->node = node; X return(chunk); X} SHAR_EOF chmod 0644 queue.c || echo "restore of queue.c fails" fi if test -f runsim.c; then echo "File runsim.c exists"; else echo "x - extracting runsim.c (Text)" sed 's/^X//' << 'SHAR_EOF' > runsim.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X X#include "func.h" X#include "tech.h" X#include "state.h" X#include "queue.h" X#include "runsim.h" X X/* XThis function performs the mechanics of the switch level simulation. X*/ X Xvoid XRunSim(input_queue, clock_queue, preset_queue, output_queue, Xinput_duration, clock_duration, node_count) XSQUEUE *input_queue; XSQUEUE *clock_queue; XSQUEUE *preset_queue; XSQUEUE *output_queue; Xint input_duration; Xint clock_duration; Xint node_count; X X{ X int input_index; X int clock_index; X int settling_error = 0; X NQUEUE *node_queue; X X node_queue = (NQUEUE *) NQInit("node_queue"); X (void) AssignPreset(preset_queue, node_queue); X for(input_index = 0; (!settling_error && (input_index < input_duration)); X input_index++) { X (void) AssignInputs(input_queue, input_index, node_queue); X if(clock_duration > 0) { X for(clock_index = 0; (!settling_error && X (clock_index < clock_duration)); clock_index++) { X (void) AssignClocks(clock_queue, clock_index, node_queue); X (void) ApplyInputVector(node_queue, node_count * MAX_STEP, X &settling_error); X if(settling_error) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "The circuit does not settle.\n"); X (void) fprintf(stdout, "Premature termination during "); X (void) fprintf(stdout, "clock phase %d of input %d.\n", X clock_index, input_index); X } X } X } else { X (void) ApplyInputVector(node_queue, node_count * MAX_STEP, X &settling_error); X if(settling_error) { X (void) fprintf(stdout, "Error:\n"); X (void) fprintf(stdout, "The circuit does not settle. "); X (void) fprintf(stdout, "Premature termination during "); X (void) fprintf(stdout, "input %d.\n", X input_index); X } X } X (void) AssignOutputs(output_queue, input_index); X } X} X X/* XThis function applies to the entire network one vector, consisting of single Xbit values of all inputs and clocks. XThe simulation of an overall network is modeled by two processes: Xpropagation of drive and charge sharing. XDrive is propagated from the external inputs to as many nodes in Xthe network as possible. XCharge sharing is attempted among the nodes that are not driven. XPropagation of drive and charge sharing process pair is repeated until the Xentire network settles. XThe acronym CS used in function names stands for Charge Sharing. X*/ X Xvoid XApplyInputVector(node_queue, max_iter, settling_error) XNQUEUE *node_queue; Xint max_iter; Xint *settling_error; X X{ X NODE *node; X int num_step; X X for(node = (NODE *) NQGet(node_queue), num_step = 0; X ((num_step < max_iter) && (node != ((NODE *) NIL))); X node = (NODE *) NQGet(node_queue), num_step++) { X node->perturbed = 0; X (void) DrivePropagation(node, node_queue); X (void) ChargeSharing(node, node_queue); X } X if(num_step == max_iter) { X *settling_error = 1; X } X} X X/* XThis function helps distribute drive to as many nodes in the network as Xpossible. Super drive, originating from external inputs, is modulated by Xmosfets in the network. Drive propagates throughout the network, thereby Xupdating nodal logic values. X*/ X Xvoid XDrivePropagation(node, node_queue) XNODE *node; XNQUEUE *node_queue; X X{ X (void) MosfetAction(node); X (void) EvaluateNode(node); X (void) NodeStats(node, node_queue); X} X X/* XThis function performs charge sharing among electrically connected non driven Xnodes in the network. The charge sharing model lumps all capacitances (from Xnode to substrate) into three capacitors connected in parallel, one for each Xlogic value: low, high, and dontcare. The final node value is then determined Xbased on the relative sizes of the three capacitors. X*/ X Xvoid XChargeSharing(node, node_queue) XNODE *node; XNQUEUE *node_queue; X X{ X float logic_low_capacitance = 0.0; X float logic_high_capacitance = 0.0; X float logic_dontcare_capacitance = 0.0; X X if((node->present_drive == NO_DRIVE) && !node->acquired) { X (void) AccumulateCSValue(node, &logic_low_capacitance, X &logic_high_capacitance, &logic_dontcare_capacitance); X (void) SetCSValue(node, node_queue, X (short) DetermineCSValue(logic_low_capacitance, X logic_high_capacitance, logic_dontcare_capacitance)); X } X} X X/* XThis function traverses all the mosfets of the given node and performs the Xaction of an nmos or a pmos (depending on the type of the mosfet in question) Xfor a single mosfet. X*/ X Xvoid XMosfetAction(node) XNODE *node; X X{ X MOSFET *mosfet; X X for(mosfet = node->mosfet_queue->head; mosfet != ((MOSFET *) NIL); X mosfet = mosfet->link) { X if((node == mosfet->term[1]) || (node == mosfet->term[2])) { X if((int) MosfetOn(node, mosfet)) { X (void) MosfetActive(node, mosfet); X } else { X (void) MosfetDisable(mosfet); X } X } X } X} X X/* XThis function checks whether or not the given mosfet is turned on, which is Xincluded in switch-on and diode-on modes of operation. The modes of Xoperation in which the given mosfet is turned off are switch-off and diode-off. X*/ X Xint XMosfetOn(node, mosfet) XNODE *node; XMOSFET *mosfet; X X{ X NODE *gate; X NODE *source; X NODE *drain; X char mosfet_type; X X gate = mosfet->term[0]; X source = mosfet->term[1]; X drain = mosfet->term[2]; X mosfet_type = mosfet->mosfet_type; X if(((node == source) && X (((mosfet_type == NMOS) || (mosfet_type == ENMOS)) && X ((gate->present_value == LOGIC_HIGH) && X ((drain->present_value == LOGIC_LOW) || X (drain->present_value != source->present_value)))) || X ((mosfet_type == DNMOS) && X !((gate->present_value == LOGIC_LOW) && X (drain->present_value == LOGIC_HIGH) && X (source->present_value == LOGIC_HIGH))) || X ((mosfet_type == PMOS) && X ((gate->present_value == LOGIC_LOW) && X ((drain->present_value == LOGIC_HIGH) || X (drain->present_value != source->present_value))))) || X ((node == drain) && X (((mosfet_type == NMOS) || (mosfet_type == ENMOS)) && X ((gate->present_value == LOGIC_HIGH) && X ((source->present_value == LOGIC_LOW) || X (source->present_value != drain->present_value)))) || X ((mosfet_type == DNMOS) && X !((gate->present_value == LOGIC_LOW) && X (source->present_value == LOGIC_HIGH) && X (drain->present_value == LOGIC_HIGH))) || X ((mosfet_type == PMOS) && X ((gate->present_value == LOGIC_LOW) && X ((source->present_value == LOGIC_HIGH) || X (source->present_value != drain->present_value)))))) { X return(1); X } else { X return(0); X } X} X X/* XThis function simulates the action of a mosfet in the ohmic region of Xoperation (switch-on mode), or in the high electric field portion of the Xsaturation region of operation (diode-on mode). X*/ X Xvoid XMosfetActive(node, mosfet) XNODE *node; XMOSFET *mosfet; X X{ X NODE *source; X NODE *drain; X X source = mosfet->term[1]; X drain = mosfet->term[2]; X mosfet->value[1] = drain->present_value; X mosfet->value[2] = source->present_value; X if(node == source) { X if(drain->present_drive > NO_DRIVE) { X mosfet->drive[0] = X ((drain->present_drive == SUPER_DRIVE) ? mosfet->strength : X (1.0 / ((1.0 / mosfet->strength) + X (1.0 / drain->present_drive)))); X } else { X mosfet->drive[0] = NO_DRIVE; X } X } else if(node == drain) { X if(source->present_drive > NO_DRIVE) { X mosfet->drive[1] = X ((source->present_drive == SUPER_DRIVE) ? mosfet->strength : X (1.0 / ((1.0 / mosfet->strength) + X (1.0 / source->present_drive)))); X } else { X mosfet->drive[1] = NO_DRIVE; X } X } X} X X/* XThis function simulates the action of a mosfet in the cut-off region of Xoperation (switch-off mode), or at the edge of saturation and cut-off Xregions of operation (diode-off mode). X*/ X Xvoid XMosfetDisable(mosfet) XMOSFET *mosfet; X X{ X mosfet->drive[0] = mosfet->drive[1] = NO_DRIVE; X} X X/* XThis function determines the new drive and logic value for the given node Xbased on the terminal drives and logic values of all mosfets connected to Xthe node. X*/ X Xvoid XEvaluateNode(node) XNODE *node; X X{ X float logic_high_drive = NO_DRIVE; X float logic_low_drive = NO_DRIVE; X float logic_dontcare_drive = NO_DRIVE; X X (void) GetNodeDrive(node, X &logic_low_drive, &logic_high_drive, &logic_dontcare_drive); X (void) UpdateNode(node, X logic_low_drive, logic_high_drive, logic_dontcare_drive); X} X X/* XThis function uses the terminal drives of all mosfets connected to the given Xnode to determine the drive for each logic value: low, high, and dontcare. X*/ X Xvoid XGetNodeDrive(node, Xlogic_low_drive, logic_high_drive, logic_dontcare_drive) XNODE *node; Xfloat *logic_low_drive; Xfloat *logic_high_drive; Xfloat *logic_dontcare_drive; X X{ X MOSFET *mosfet; X X for(mosfet = node->mosfet_queue->head; mosfet != ((MOSFET *) NIL); X mosfet = mosfet->link) { X (void) SortDrive(node, mosfet, X logic_low_drive, logic_high_drive, logic_dontcare_drive); X } X} X X/* XThis function examines the logic value of the appropriate mosfet terminal Xand updates the corresponding drive. X*/ X Xvoid XSortDrive(node, mosfet, Xlogic_low_drive, logic_high_drive, logic_dontcare_drive) XNODE *node; XMOSFET *mosfet; Xfloat *logic_low_drive; Xfloat *logic_high_drive; Xfloat *logic_dontcare_drive; X X{ X if(node == mosfet->term[1]) { X if(mosfet->value[1] == LOGIC_LOW) { X *logic_low_drive = (float) MaxFloat(*logic_low_drive, X mosfet->drive[0]); X } else if(mosfet->value[1] == LOGIC_HIGH) { X *logic_high_drive = (float) MaxFloat(*logic_high_drive, X mosfet->drive[0]); X } else if(mosfet->value[1] == LOGIC_DONTCARE) { X *logic_dontcare_drive = (float) MaxFloat(*logic_dontcare_drive, X mosfet->drive[0]); X } X } else if(node == mosfet->term[2]) { X if(mosfet->value[2] == LOGIC_LOW) { X *logic_low_drive = (float) MaxFloat(*logic_low_drive, X mosfet->drive[1]); X } else if(mosfet->value[2] == LOGIC_HIGH) { X *logic_high_drive = (float) MaxFloat(*logic_high_drive, X mosfet->drive[1]); X } else if(mosfet->value[2] == LOGIC_DONTCARE) { X *logic_dontcare_drive = (float) MaxFloat(*logic_dontcare_drive, X mosfet->drive[1]); X } X } X} X X/* XThis function considers the drive of each logic value for the given node Xand produces the new drive and logic value. X*/ X Xvoid XUpdateNode(node, Xlogic_low_drive, logic_high_drive, logic_dontcare_drive) XNODE *node; Xfloat logic_low_drive; Xfloat logic_high_drive; Xfloat logic_dontcare_drive; X X{ X if((logic_low_drive > logic_high_drive) && X (logic_low_drive > logic_dontcare_drive)) { X node->next_drive = logic_low_drive; X node->next_value = LOGIC_LOW; X } else if((logic_high_drive > logic_low_drive) && X (logic_high_drive > logic_dontcare_drive)) { X node->next_drive = logic_high_drive; X node->next_value = LOGIC_HIGH; X } else if((logic_dontcare_drive > logic_low_drive) && X (logic_dontcare_drive > logic_high_drive)) { X node->next_drive = logic_dontcare_drive; X node->next_value = LOGIC_DONTCARE; X } else { X (void) ResolveConflict(node, X logic_low_drive, logic_high_drive, logic_dontcare_drive); X } X (void) RemoveStatic(node); X} X X/* XThis function determines the drive and value for a node in the case of Xa conflict between the logic values. X*/ X Xvoid XResolveConflict(node, logic_low_drive, logic_high_drive, logic_dontcare_drive) XNODE *node; Xfloat logic_low_drive; Xfloat logic_high_drive; Xfloat logic_dontcare_drive; X X{ X node->next_drive = NO_DRIVE; X if(((logic_low_drive == logic_high_drive) && X (logic_low_drive > NO_DRIVE)) || X ((logic_low_drive == logic_dontcare_drive) && X (logic_low_drive > NO_DRIVE)) || X ((logic_high_drive == logic_dontcare_drive) && X (logic_high_drive > NO_DRIVE))) { X node->next_value = LOGIC_DONTCARE; X } X} X X/* XThis function clears the drive for a node if the drive has decreased beyond Xthe threshold of recognition. X*/ X Xvoid XRemoveStatic(node) XNODE *node; X X{ X if((node->next_drive > NO_DRIVE) && (node->next_drive < MIN_DRIVE)) { X node->next_drive = NO_DRIVE; X } X} X X/* XThis function recursively traverses all electrically connected nodes, Xsorting their capacitances according to their logic values. X*/ X Xvoid XAccumulateCSValue(node, Xlogic_low_capacitance, logic_high_capacitance, logic_dontcare_capacitance) XNODE *node; Xfloat *logic_low_capacitance; Xfloat *logic_high_capacitance; Xfloat *logic_dontcare_capacitance; X X{ X MOSFET *mosfet; X X if((node->present_drive == NO_DRIVE) && !node->acquired) { X node->acquired = 1; X node->set = 0; X (void) SortCapacitance(node, logic_low_capacitance, X logic_high_capacitance, logic_dontcare_capacitance); X for(mosfet = node->mosfet_queue->head; mosfet != ((MOSFET *) NIL); X mosfet = mosfet->link) { X if((int) MosfetOn(node, mosfet)) { X if(node == mosfet->term[1]) { X (void) AccumulateCSValue(mosfet->term[2], X logic_low_capacitance, logic_high_capacitance, X logic_dontcare_capacitance); X } else if(node == mosfet->term[2]) { X (void) AccumulateCSValue(mosfet->term[1], X logic_low_capacitance, logic_high_capacitance, X logic_dontcare_capacitance); X } X } X } X } X} X X/* XThis function examines the logic value of the given node and updates the Xcorresponding cumulative capacitance. X*/ X Xvoid XSortCapacitance(node, Xlogic_low_capacitance, logic_high_capacitance, logic_dontcare_capacitance) XNODE *node; Xfloat *logic_low_capacitance; Xfloat *logic_high_capacitance; Xfloat *logic_dontcare_capacitance; X X{ X if(node->present_value == LOGIC_LOW) { X *logic_low_capacitance += node->capacitance; X } else if(node->present_value == LOGIC_HIGH) { X *logic_high_capacitance += node->capacitance; X } else if(node->present_value == LOGIC_DONTCARE) { X *logic_dontcare_capacitance += node->capacitance; X } X} X X/* XThis function decides on the new charge sharing logic value based on the Xindividual capacitances of the possible logic values. X*/ X Xshort XDetermineCSValue(logic_low_capacitance, logic_high_capacitance, Xlogic_dontcare_capacitance) Xfloat logic_low_capacitance; Xfloat logic_high_capacitance; Xfloat logic_dontcare_capacitance; X X{ X if(logic_low_capacitance > X ((logic_high_capacitance + logic_dontcare_capacitance) * CAP_FACTOR)) { X return(LOGIC_LOW); X } else X if(logic_high_capacitance > X ((logic_low_capacitance + logic_dontcare_capacitance) * CAP_FACTOR)) { X return(LOGIC_HIGH); X } else X if(logic_dontcare_capacitance > X ((logic_low_capacitance + logic_high_capacitance) * CAP_FACTOR)) { X return(LOGIC_DONTCARE); X } else { X return(LOGIC_DONTCARE); X } X} X X/* XThis function recursively traverses all electrically connected nodes, Xsetting their logic values to the given logic value. X*/ X Xvoid XSetCSValue(node, node_queue, value) XNODE *node; XNQUEUE *node_queue; Xshort value; X X{ X MOSFET *mosfet; X X if((node->present_drive == NO_DRIVE) && !node->set) { X node->acquired = 0; X node->set = 1; X node->next_value = value; X (void) NodeStats(node, node_queue); X for(mosfet = node->mosfet_queue->head; mosfet != ((MOSFET *) NIL); X mosfet = mosfet->link) { X if((int) MosfetOn(node, mosfet)) { X if(node == mosfet->term[1]) { X (void) SetCSValue(mosfet->term[2], node_queue, value); X } else if(node == mosfet->term[2]) { X (void) SetCSValue(mosfet->term[1], node_queue, value); X } X } X } X } X} X X/* XThis routine updates the drive and value of the given node and generates Xnew events if the state of the node has changed. X*/ X Xvoid XNodeStats(node, node_queue) XNODE *node; XNQUEUE *node_queue; X X{ X if((node->next_drive != node->present_drive) || X (node->next_value != node->present_value)) { X (void) GenerateEvents(node, node_queue); X } X node->present_drive = node->next_drive; X node->present_value = node->next_value; X} X X/* XThis function records the new events by locating the perturbed nodes Xand appending them onto the node queue. X*/ X Xvoid XGenerateEvents(node, node_queue) XNODE *node; XNQUEUE *node_queue; X X{ X MOSFET *mosfet; X X for(mosfet = node->mosfet_queue->head; mosfet != ((MOSFET *) NIL); X mosfet = mosfet->link) { X if(node == mosfet->term[0]) { X if(!mosfet->term[1]->perturbed && X (mosfet->term[1]->present_drive < SUPER_DRIVE)) { X mosfet->term[1]->perturbed = 1; X (void) NQPut(node_queue, mosfet->term[1]); X } X if(!mosfet->term[2]->perturbed && X (mosfet->term[2]->present_drive < SUPER_DRIVE)) { X mosfet->term[2]->perturbed = 1; X (void) NQPut(node_queue, mosfet->term[2]); X } X } else if(node == mosfet->term[1]) { X if(!mosfet->term[2]->perturbed && X (mosfet->term[2]->present_drive < SUPER_DRIVE)) { X mosfet->term[2]->perturbed = 1; X (void) NQPut(node_queue, mosfet->term[2]); X } X } else if(node == mosfet->term[2]) { X if(!mosfet->term[1]->perturbed && X (mosfet->term[1]->present_drive < SUPER_DRIVE)) { X mosfet->term[1]->perturbed = 1; X (void) NQPut(node_queue, mosfet->term[1]); X } X } X } X if(!node->perturbed && (node->present_drive < SUPER_DRIVE)) { X node->perturbed = 1; X (void) NQPut(node_queue, node); X } X} X X/* XThis function assigns the input values to corresponding nodes at Xthe beginning of the run of each input vector. X*/ X Xvoid XAssignInputs(input_queue, input_index, node_queue) XSQUEUE *input_queue; Xint input_index; XNQUEUE *node_queue; X X{ X SIGNAL *input; X X for(input = input_queue->head; input != ((SIGNAL *) NIL); X input = input->link) { X if(input_index < (int) strlen(input->value_sequence)) { X if(input->value_sequence[input_index] == '0') { X input->node->next_value = LOGIC_LOW; X } else if(input->value_sequence[input_index] == '1') { X input->node->next_value = LOGIC_HIGH; X } else if((input->value_sequence[input_index] == 'X') || X (input->value_sequence[input_index] == 'x')) { X input->node->next_value = LOGIC_DONTCARE; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No meaningful bit string specified "); X (void) fprintf(stdout, "for input '%s'. Exit 1.\n", X input->name); X (void) exit(1); X } X } else { X if(input->value_sequence[(int) strlen(input->value_sequence) - 1] X == '0') { X input->node->next_value = LOGIC_LOW; X } else X if(input->value_sequence[(int) strlen(input->value_sequence) - 1] X == '1') { X input->node->next_value = LOGIC_HIGH; X } else X if((input->value_sequence[(int) strlen(input->value_sequence) - 1] X == 'X') || X (input->value_sequence[(int) strlen(input->value_sequence) - 1] X == 'x')) { X input->node->next_value = LOGIC_DONTCARE; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No meaningful bit string specified "); X (void) fprintf(stdout, "for input '%s'. Exit 1.\n", X input->name); X (void) exit(1); X } X } X (void) NodeStats(input->node, node_queue); X } X} X X/* XThis function assigns the clock values to corresponding nodes at Xthe beginning of the run of each clock vector. X*/ X Xvoid XAssignClocks(clock_queue, clock_index, node_queue) XSQUEUE *clock_queue; Xint clock_index; XNQUEUE *node_queue; X X{ X SIGNAL *clock; X X for(clock = clock_queue->head; clock != ((SIGNAL *) NIL); X clock = clock->link) { X if(clock_index < (int) strlen(clock->value_sequence)) { X if(clock->value_sequence[clock_index] == '0') { X clock->node->next_value = LOGIC_LOW; X } else if(clock->value_sequence[clock_index] == '1') { X clock->node->next_value = LOGIC_HIGH; X } else if((clock->value_sequence[clock_index] == 'X') || X (clock->value_sequence[clock_index] == 'x')) { X clock->node->next_value = LOGIC_DONTCARE; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No meaningful bit string specified "); X (void) fprintf(stdout, "for clock '%s'. Exit 1.\n", X clock->name); X (void) exit(1); X } X } else { X if(clock->value_sequence[(int) strlen(clock->value_sequence) - 1] X == '0') { X clock->node->next_value = LOGIC_LOW; X } else X if(clock->value_sequence[(int) strlen(clock->value_sequence) - 1] X == '1') { X clock->node->next_value = LOGIC_HIGH; X } else X if((clock->value_sequence[(int) strlen(clock->value_sequence) - 1] X == 'X') || X (clock->value_sequence[(int) strlen(clock->value_sequence) - 1] X == 'x')) { X clock->node->next_value = LOGIC_DONTCARE; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No meaningful bit string specified "); X (void) fprintf(stdout, "for clock '%s'. Exit 1.\n", X clock->name); X (void) exit(1); X } X } X (void) NodeStats(clock->node, node_queue); X } X} X X/* XThis function assigns the preset values to corresponding nodes at Xthe beginning of the simulation. X*/ X Xvoid XAssignPreset(preset_queue, node_queue) XSQUEUE *preset_queue; XNQUEUE *node_queue; X X{ X SIGNAL *preset; X X for(preset = preset_queue->head; preset != ((SIGNAL *) NIL); X preset = preset->link) { X if(preset->value_sequence[0] == '0') { X preset->node->next_value = LOGIC_LOW; X } else if(preset->value_sequence[0] == '1') { X preset->node->next_value = LOGIC_HIGH; X } else if((preset->value_sequence[0] == 'X') || X (preset->value_sequence[0] == 'x')) { X preset->node->next_value = LOGIC_DONTCARE; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "No meaningful bit string specified "); X (void) fprintf(stdout, "for preset '%s'. Exit 1.\n", X preset->name); X (void) exit(1); X } X (void) NodeStats(preset->node, node_queue); X } X} X X/* XThis function assigns the output symbols to outputs, using the values of Xcorresponding nodes, at the end of the run of each input vector. X*/ X Xvoid XAssignOutputs(output_queue, output_index) XSQUEUE *output_queue; Xint output_index; X X{ X SIGNAL *output; X X for(output = output_queue->head; output != ((SIGNAL *) NIL); X output = output->link) { X if(output->node->present_value == LOGIC_LOW) { X if(output->node->present_drive > NO_DRIVE) { X output->value_sequence[output_index] = '0'; X } else { X output->value_sequence[output_index] = 'L'; X } X } else if(output->node->present_value == LOGIC_HIGH) { X if(output->node->present_drive > NO_DRIVE) { X output->value_sequence[output_index] = '1'; X } else { X output->value_sequence[output_index] = 'H'; X } X } else if(output->node->present_value == LOGIC_DONTCARE) { X output->value_sequence[output_index] = 'X'; X } else { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Illegal output logic value %d %s[%d]. "); X (void) fprintf(stdout, "Exit 1.\n", X output->node->present_value, output->name, output_index); X (void) exit(1); X } X } X} SHAR_EOF chmod 0666 runsim.c || echo "restore of runsim.c fails" fi if test -f state.c; then echo "File state.c exists"; else echo "x - extracting state.c (Text)" sed 's/^X//' << 'SHAR_EOF' > state.c && X/* X******************************************************************************* XAuthor: X Alex Sherstinsky, X Microsystems Technology Laboratories, X Building 39, Room 611, X Massachusetts Institute Of Technology, X 77 Massachusetts Avenue, X Cambridge, MA 02139 X Telephone: (617)253-0710 X Electronic Mail Address: shers@caf.mit.edu XCopyright 1988 Massachusetts Institute Of Technology XAll rights reserved. XThis program may not be distributed to other organizations without the Xpermission of the author. In no case may it be distributed outside the XUnited States and Canada. This program is supplied "as is", without any Xkind of warranty, and M.I.T. does not promise to support it in any way. XThis program is not to be incorporated into a commercial product, or access Xto it sold, without prior written agreement from the author. X******************************************************************************* XSLIC X******************************************************************************* X*/ X#include <stdio.h> X#include <strings.h> X#include <math.h> X X#include "func.h" X#include "tech.h" X#include "queue.h" X#include "hash.h" X#include "runsim.h" X#include "state.h" X X/* XThis function allocates and builds the state space for the simulator. X*/ X Xvoid XBuildState(sim_file, drive_file, Xinput_queue, clock_queue, preset_queue, output_queue, Xmos_count, node_count, input_count, clock_count, output_count, Xinput_duration, clock_duration) XFILE *sim_file; XFILE *drive_file; XSQUEUE **input_queue; XSQUEUE **clock_queue; XSQUEUE **preset_queue; XSQUEUE **output_queue; Xint *mos_count; Xint *node_count; Xint *input_count; Xint *clock_count; Xint *output_count; Xint *input_duration; Xint *clock_duration; X X{ X *input_queue = (SQUEUE *) SQInit("input_queue"); X *clock_queue = (SQUEUE *) SQInit("clock_queue"); X *preset_queue = (SQUEUE *) SQInit("preset_queue"); X *output_queue = (SQUEUE *) SQInit("output_queue"); X (void) BuildDrive(drive_file, *input_queue, input_count, input_duration, X *clock_queue, clock_count, clock_duration, *preset_queue, X *output_queue, output_count); X (void) BuildNetwork(sim_file, mos_count, node_count, X *input_queue, *clock_queue, *preset_queue, *output_queue); X} X X/* XThis function reads the ".drive" file, containing specific directions for the Xsimulation. It sorts the various types of signals (inputs, clocks, and Xoutputs) into their respective queues, reporting their count as well. XIt also records the maximum duration of inputs and clocks (in the units of Xon-chip clock pulses for inputs and in the units of off-chip clock pulses, or Xsimply, bits, for clocks). X*/ X Xvoid XBuildDrive(drive_file, input_queue, input_count, input_duration, Xclock_queue, clock_count, clock_duration, preset_queue, Xoutput_queue, output_count) XFILE *drive_file; XSQUEUE *input_queue; Xint *input_count; Xint *input_duration; XSQUEUE *clock_queue; Xint *clock_count; Xint *clock_duration; XSQUEUE *preset_queue; XSQUEUE *output_queue; Xint *output_count; X X{ X char *drive_line = (char *) malloc((unsigned) (MAXBITS + COMMAND_LENGTH) * X sizeof(char)); X char signal_type; X char *signal_name = (char *) malloc((unsigned) MAX_TOKEN_LENGTH * X sizeof(char)); X char *signal_value_sequence = (char *) malloc((unsigned) MAXBITS * X sizeof(char)); X X for(; (char *) fgets(drive_line, MAXBITS + COMMAND_LENGTH, X drive_file) != NULL;) { X if((*drive_line == 'I') || (*drive_line == 'i') || X (*drive_line == 'C') || (*drive_line == 'c') || X (*drive_line == 'P') || (*drive_line == 'p')) { X (void) sscanf(drive_line, "%c %s %s", &signal_type, signal_name, X signal_value_sequence); X } else if((*drive_line == 'O') || (*drive_line == 'o')) { X (void) sscanf(drive_line, "%c %s", &signal_type, signal_name); X } else if(*drive_line == '|') { X signal_type = '\0'; X (void) strcpy(signal_name, ""); X (void) strcpy(signal_value_sequence, ""); X } else { X (void) fprintf(stdout, "Error: Illegal command %c. Exit 1.\n", X *drive_line); X (void) exit(1); X } X if((signal_type == 'I') || (signal_type == 'i')) { X (*input_count)++; X *input_duration = (int) MaxInt(*input_duration, X (int) strlen(signal_value_sequence)); X (void) SQPut(input_queue, (SIGNAL *) X MakeSignal('i', signal_name, signal_value_sequence, X ((NODE *) NIL), MAXBITS)); X } else if((signal_type == 'C') || (signal_type == 'c')) { X (*clock_count)++; X *clock_duration = (int) MaxInt(*clock_duration, X (int) strlen(signal_value_sequence)); X (void) SQPut(clock_queue, (SIGNAL *) X MakeSignal('c', signal_name, signal_value_sequence, X ((NODE *) NIL), MAXBITS)); X } else if((signal_type == 'P') || (signal_type == 'p')) { X (void) SQPut(preset_queue, (SIGNAL *) X MakeSignal('t', signal_name, signal_value_sequence, X ((NODE *) NIL), MAXBITS)); X } else if((signal_type == 'O') || (signal_type == 'o')) { X (*output_count)++; X (void) SQPut(output_queue, (SIGNAL *) X MakeSignal('o', signal_name, (char *) AllocateString(MAXBITS), X ((NODE *) NIL), MAXBITS)); X } X } X} X X/* XThis routine builds the network of nodes and mosfets and establishes the Xappropriate connections between the external terminals (inputs, clocks, and Xoutputs) and nodes. X*/ X Xvoid XBuildNetwork(sim_file, mos_count, node_count, Xinput_queue, clock_queue, preset_queue, output_queue) XFILE *sim_file; Xint *mos_count; Xint *node_count; XSQUEUE *input_queue; XSQUEUE *clock_queue; XSQUEUE *preset_queue; XSQUEUE *output_queue; X X{ X NHASHTAB *node_hash_table; X X node_hash_table = (NHASHTAB *) NHashInit("node_hash_table"); X (void) ReadSimNetlist(sim_file, mos_count, node_hash_table); X *node_count = node_hash_table->node_count; X (void) ConnectInputsNodes(input_queue, node_hash_table); X (void) ConnectClocksNodes(clock_queue, node_hash_table); X (void) ConnectPresetNodes(preset_queue, node_hash_table); X (void) ConnectOutputsNodes(output_queue, node_hash_table); X} X X/* XThis function reads the ".sim" file, during which it builds a hash table of Xnodes and a queue of mosfets. It also adds capacitances found in the ".sim" Xfile to respective nodes. X*/ X Xvoid XReadSimNetlist(sim_file, mos_count, node_hash_table) XFILE *sim_file; Xint *mos_count; XNHASHTAB *node_hash_table; X X{ X char *sim_line; X char **token_array; X int index; X NODE *(node[3]); X MOSFET *(mosfet[3]); X float width; X float length; X X sim_line = (char *) malloc((unsigned) SIM_LINE_LENGTH * sizeof(char *)); X token_array = (char **) malloc((unsigned) MAX_TOKENS * sizeof(char *)); X for(index = 0; index < MAX_TOKENS; index++) { X token_array[index] = (char *) malloc((unsigned) MAX_TOKEN_LENGTH * X sizeof(char)); X } X for(; (char *) fgets(sim_line, SIM_LINE_LENGTH, sim_file) != NULL;) { X (void) ParseSimLine(token_array, sim_line); X if((*(token_array[0]) == NMOS) || (*(token_array[0]) == PMOS) || X (*(token_array[0]) == ENMOS) || (*(token_array[0]) == DNMOS)) { X (void) ReadMosfet(node_hash_table, token_array[1], token_array[2], X token_array[3], node, mosfet, mos_count, *(token_array[0]), X (width = (float) atof(token_array[5])) / X (length = (float) atof(token_array[4]))); X (void) CombineMosfet(node[0]); X (void) CombineMosfet(node[1]); X (void) CombineMosfet(node[2]); X node[0]->capacitance += width * length * COX; X } else if(*(token_array[0]) == CAPACITOR) { X (void) ReadCapacitor(node_hash_table, X token_array[1], (float) atof(token_array[3])); X } X } X} X X/* XThis function parses a single line from the ".sim" file into tokens. X*/ X Xvoid XParseSimLine(token_array, sim_line) Xchar **token_array; Xchar *sim_line; X X{ X int token_index = 0; X int char_count = 0; X X for(; ((*sim_line != '\0') && (token_index < MAX_TOKENS));) { X if(*sim_line != ' ') { X token_array[token_index][char_count++] = *(sim_line)++; X } else { X for(token_array[token_index][char_count] = '\0', X token_index++, char_count = 0; (*sim_line == ' '); sim_line++) { X ; X } X } X } X} X X/* XThis function puts (if necessary) each node of a new mosfet into the Xnode hash table and attributes the mosfet to the nodes. X*/ X Xvoid XReadMosfet(node_hash_table, gate_terminal_name, source_terminal_name, Xdrain_terminal_name, node, mosfet, mos_count, device, strength) XNHASHTAB *node_hash_table; Xchar *gate_terminal_name; Xchar *source_terminal_name; Xchar *drain_terminal_name; XNODE **node; XMOSFET **mosfet; Xint *mos_count; Xchar device; Xfloat strength; X X{ X node[0] = (NODE *) NHashPut(node_hash_table, gate_terminal_name, X &(mosfet[0]), device, strength); X node[1] = (NODE *) NHashPut(node_hash_table, source_terminal_name, X &(mosfet[1]), device, strength); X node[2] = (NODE *) NHashPut(node_hash_table, drain_terminal_name, X &(mosfet[2]), device, strength); X (*mos_count)++; X mosfet[0]->term[0] = node[0]; X mosfet[0]->term[1] = node[1]; X mosfet[0]->term[2] = node[2]; X if(node[1] != node[0]) { X mosfet[1]->term[0] = node[0]; X mosfet[1]->term[1] = node[1]; X mosfet[1]->term[2] = node[2]; X } X if((node[2] != node[0]) && (node[2] != node[1])) { X mosfet[2]->term[0] = node[0]; X mosfet[2]->term[1] = node[1]; X mosfet[2]->term[2] = node[2]; X } X} X X/* XThis function adds a capacitance (lumped to substrate) found in the ".sim" Xfile to the given node. The capacitances reported in the ".sim" file are not Xassociated with mosfets. This routine assumes that the units of capacitance Xin the ".sim" file are fF. The node to which the capacitance is connected Xmust have been previously specified in the ".sim" file as a mosfet terminal. X*/ X Xvoid XReadCapacitor(node_hash_table, node_name, capacitance) XNHASHTAB *node_hash_table; Xchar *node_name; Xfloat capacitance; X X{ X NODE *node; X X if((node = (NODE *) NHashGet(node_hash_table, READ, X node_name, ((MOSFET **) NIL), '\0', 0.0)) == ((NODE *) NIL)) { X (void) fprintf(stdout, "Warning: "); X (void) fprintf(stdout, "Node '%s' is not connected to a mosfet. ", X node_name); X (void) fprintf(stdout, "Ignored.\n"); X } else { X node->capacitance += capacitance; X } X} X X/* XThis function combines a mosfet newly encountered in the ".sim" file with Xa previously found mosfet if the terminal connections of the two mosfets Xare the same. This accomplishes the unfolding of folded mosfet structures. X*/ X Xvoid XCombineMosfet(node) XNODE *node; X X{ X MQUEUE *mosfet_queue; X MOSFET *tail; X MOSFET *mosfet; X X mosfet_queue = node->mosfet_queue; X for(mosfet = mosfet_queue->head, tail = mosfet_queue->tail; X mosfet != tail; mosfet = mosfet->link) { X if((mosfet->mosfet_type == tail->mosfet_type) && X (mosfet->term[0] == tail->term[0]) && X (((mosfet->term[1] == tail->term[1]) && X (mosfet->term[2] == tail->term[2])) || X ((mosfet->term[1] == tail->term[2]) && X (mosfet->term[2] == tail->term[1])))) { X mosfet->strength += tail->strength; X } X } X} X X/* XThis routine connects input signals to their corresponding nodes. X*/ X Xvoid XConnectInputsNodes(input_queue, node_hash_table) XSQUEUE *input_queue; XNHASHTAB *node_hash_table; X X{ X SIGNAL *input; X X for(input = input_queue->head; input != ((SIGNAL *) NIL); X input = input->link) { X if((input->node = (NODE *) NHashGet(node_hash_table, READ, X input->name, ((MOSFET **) NIL), '\0', 0.0)) == ((NODE *) NIL)) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Input '%s' does not exist. Exit 1.\n", X input->name); X (void) exit(1); X } X input->node->present_drive = input->node->next_drive = SUPER_DRIVE; X input->node->capacitance = SUPER_CAPACITANCE; X } X} X X/* XThis routine connects clock signals to their corresponding nodes. X*/ X Xvoid XConnectClocksNodes(clock_queue, node_hash_table) XSQUEUE *clock_queue; XNHASHTAB *node_hash_table; X X{ X SIGNAL *clock; X X for(clock = clock_queue->head; clock != ((SIGNAL *) NIL); X clock = clock->link) { X if((clock->node = (NODE *) NHashGet(node_hash_table, READ, X clock->name, ((MOSFET **) NIL), '\0', 0.0)) == ((NODE *) NIL)) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Clock '%s' does not exist. Exit 1.\n", X clock->name); X (void) exit(1); X } X clock->node->present_drive = clock->node->next_drive = SUPER_DRIVE; X clock->node->capacitance = SUPER_CAPACITANCE; X } X} X X/* XThis routine connects preset signals to their corresponding nodes. X*/ X Xvoid XConnectPresetNodes(preset_queue, node_hash_table) XSQUEUE *preset_queue; XNHASHTAB *node_hash_table; X X{ X SIGNAL *preset; X X for(preset = preset_queue->head; preset != ((SIGNAL *) NIL); X preset = preset->link) { X if((preset->node = (NODE *) NHashGet(node_hash_table, READ, X preset->name, ((MOSFET **) NIL), '\0', 0.0)) == ((NODE *) NIL)) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Preset '%s' does not exist. Exit 1.\n", X preset->name); X (void) exit(1); X } X } X} X X/* XThis routine connects output signals to their corresponding nodes. X*/ X Xvoid XConnectOutputsNodes(output_queue, node_hash_table) XSQUEUE *output_queue; XNHASHTAB *node_hash_table; X X{ X SIGNAL *output; X X for(output = output_queue->head; output != ((SIGNAL *) NIL); X output = output->link) { X if((output->node = (NODE *) NHashGet(node_hash_table, READ, X output->name, ((MOSFET **) NIL), '\0', 0.0)) == ((NODE *) NIL)) { X (void) fprintf(stdout, "Error: "); X (void) fprintf(stdout, "Output '%s' does not exist. Exit 1.\n", X output->name); X (void) exit(1); X } X } X} SHAR_EOF chmod 0644 state.c || echo "restore of state.c fails" fi exit 0