[comp.lsi.cad] Source Code For a New Switch Level Simulator

shers@mit-caf.MIT.EDU (Alex Sherstinsky) (11/06/88)

The "shar" file below contains the documentation and source code
for SLIC -- Switch Level Integrated Circuits Simulator. 
This new simulator has advantages and disadvantages compared with
already existing switch level simulators.  
It is distributed free of charge to anyone who will be willing to 
use it and send comments, suggestions, and criticism to the author.
Best Wishes,
Alex Sherstinsky (shers@caf.mit.edu)
---- Cut Here and unpack ----
#!/bin/sh
# shar:	Shell Archiver  (v1.22)
#	Packed Sat Nov  5 00:27:14 EST 1988 by bogart!shers
#	from directory /a/shers/ADC/Sa/Demodulator/SimCode/Slic
#
#	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 
X		       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                           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:  netlist 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 netlist and compare  it  with  the  netlist  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),  and  precharged  logic.
X
XHowever,  the simulator makes no attempt to model the actual cir-
X
Xcuit timing; the simulator cannot be used to measure the speed of
X
Xa  circuit,  and  it may yield incorrect results when the circuit
X
Xbehavior is sensitive to delays.  Even though a wide  variety  of
X
Xcircuits  can  be  modeled at the switch level, there remains one
X
Ximportant circuit phenomenon that SLIC does not capture  (because
X
Xof  the  lack  of  timing  in  its switch level model): transient
X
Xcharge sharing.  Circuits which rely on this phenomenon to  over-
X
Xride  a  feedback  value cannot be modeled.  The user must either
X
Xredesign these circuits, or change the timing of control 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 handle timing, such as SPICE
X
X    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.  A special stress is on the fact that SLIC  has
X
X    no problems with transmission gates and can detect W/L design
X
X    errors  in  such  circuits  as  the  famous  six   transistor
X
X    "exclusive OR" (6tXOR) 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 a circuit level (i.e.,
X
Xspecifying  directionality  for  mosfets,  resizing  node capaci-
X
Xtances, etc.).  However, for some feedback  circuits,  one  might
X
Xneed to use the P command (explained later) to initialize certain
X
Xnodes at the beginning of the simulation run  in  order  to  help
X
XSLIC converge.
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 2 and
X| 4, one clock is active, while in in phases 1
X| and 3, both clocks are inactive.
X| These inactive phases are required to model the
X| nonoverlapping period of the clocks.
X|
XC phi1 0100
XC phi2 0001
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 a switch
X        that can connect its source and drain terminals depending
X        on the state of its gate terminal.
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  between  source
X
Xand  drain  controlled by the state of its gate electrode as fol-
X
Xlows:
X
X
Xgate      n-type       p-type      depletion
X0         open         closed      closed
X1         closed       open        closed
XX         unknown      unknown     closed
X
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.  The input
X
Xnodes have 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 values, which will last for at
X
Xleast one step, but no drive.
X
X
X     A simulation of a network with SLIC involves two  processes:
X
Xpropagation of drive and charge sharing.
X
X
X     First, drive is propagated from external inputs to  as  many
X
Xnodes  in  the  network as possible.  Modulated by mosfets, drive
X
Xflows  throughout  the  network,  thereby  updating  nodal  logic
X
Xvalues.   During  one step, all mosfets attached to each node are
X
Xevaluated using the switch level  model.   The  evaluation  of  a
X
Xmosfet amounts to computing the drive the given mosfet is capable
X
Xof imparting to the node, based on the logic  values  and  drives
X
Xpresent  at  the  mosfet's terminals.  For each logic value (low,
X
Xhigh, don't-care), the maximum drive available  from  the  node's
X
Xmosfets  is  computed.  The  highest  of  these  drives  and  the
X
Xcorresponding logic value are assigned  to  be  the  node's  next
X
Xdrive  and logic value.  Drive and logic values for all nodes are
X
Xupdated at the end of the step, meaning that all mosfets  have  a
X
Xdelay  equal  to the duration of the step.  The use of unit-delay
X
Xmosfets eliminates races caused  by  the  simulator.  The  mosfet
X
Xevaluation  and  node  updating  loops are repeated until neither
X
Xdrive nor logic value change for any node in the network, or  the
X
Xstep limit is exceeded.
X
X
X     Second, charge sharing is attempted among the nodes that are
X
Xnot  driven.  When  a  set of connected storage nodes is isolated
X
Xfrom any input nodes, they are charged to a logic state dependent
X
Xonly on the state(s) of the node(s) with the largest capacitance.
X
XThus the value on a more capacitive node will always override the
X
Xvalue  on a less capacitive one.  Charge sharing sub-networks are
X
Xformed from electrically connected (i.e., separated by conducting
X
Xmosfets)  groups  of non driven nodes.  The capacitances of every
X
Xnode in a charge sharing sub-network can be found charged to  one
X
Xof  the  three  possible  logic values: low, high, or don't-care.
X
XThus for each group, three  equivalent  capacitances  are  formed
X
Xaccording  to  the  logic  level.   The final charge shared logic
X
Xvalue for all nodes in the group is decided based on the relative
X
Xsizes 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                           References
X
XUser manuals for ESIM, RSIM, and COSMOS.
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 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 10007/*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 mos_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 changed;/*flag indicating whether node drive or value changed*/
X    short touched;/*flag indicating whether node has to be re-evaluated*/
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 *mos_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 * MakeMos();
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_ITER 128/*max number of iterations allowed to settle network*/
X#define SUPER_DRIVE 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 ProcessDrivenNetwork();
Xint ProcessCSNetwork();
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();
Xint UpdateNetwork();
Xint UpdateCSNetwork();
Xvoid AssignDrive();
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, mos_type, strength)
XNHASHTAB *nhashtab;
Xchar *node_name;
XMOSFET **mosfet;
Xchar mos_type;
Xfloat strength;
X
X{
X    int hash_number;
X    MQUEUE *mos_queue;
X    NODE *node;
X
X    if(mos_type == PMOS) {
X	strength /= STRENGTH_RATIO;
X    } else if(!((mos_type == NMOS) || 
X    (mos_type == ENMOS) || (mos_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    mos_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, 0.0, 0, 0, 0, 0,
X	mos_queue = (MQUEUE *) MQInit("mos_queue")));
X	(void) MQPut(mos_queue, (*mosfet) = (MOSFET *) 
X	MakeMos(mos_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, mos_type, strength)
XNHASHTAB *nhashtab;
Xint write;
Xchar *node_name;
XMOSFET **mosfet;
Xchar mos_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->mos_queue, *mosfet =
X		    (MOSFET *) MakeMos(mos_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 mos_count = 0;
X    NQUEUE *node_queue;
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    &node_queue, &input_queue, &clock_queue, &preset_queue, &output_queue, 
X    &mos_count, &node_count, &input_count, &clock_count, 
X    &output_count, &input_duration, &clock_duration);
X    if((mos_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:  No input values specified.  \
X	Exit 1.\n");
X	(void) exit(1);
X    } else if(input_duration > MAXBITS) {
X	(void) fprintf(stdout, "Error:  Input bit string too long.  \
X	Exit 1.\n");
X	(void) exit(1);
X    } else if((clock_count != 0) && (clock_duration == 0)) {
X	(void) fprintf(stdout, "Error:  No clock values specified.  \
X	Exit 1.\n");
X	(void) exit(1);
X    } else if(clock_duration > MAXBITS) {
X	(void) fprintf(stdout, "Error:  Clock bit string too long.  \
X	Exit 1.\n");
X	(void) exit(1);
X    } else if(output_count == 0) {
X	(void) fprintf(stdout, "No outputs indicated to display.  \
X	Exit 0.\n");
X	(void) exit(0);
X    } else {
X	(void) RunSim(node_queue, input_queue, clock_queue, preset_queue, 
X	output_queue, input_duration, clock_duration);
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 *
XMakeMos(mos_type, gate_node, source_node, drain_node, 
Xgate_value, source_value, drain_value, 
Xsource_drive, drain_drive, strength)
Xchar mos_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->mos_type = mos_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, touched, changed, acquired, set, mos_queue)
Xchar *name;
Xshort present_value;
Xshort next_value;
Xfloat present_drive;
Xfloat next_drive;
Xfloat capacitance;
Xshort changed;
Xshort touched;
Xshort acquired;
Xshort set;
XMQUEUE *mos_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->changed = changed;
X    chunk->touched = touched;
X    chunk->acquired = acquired;
X    chunk->set = set;
X    chunk->mos_queue = mos_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(node_queue, input_queue, clock_queue, preset_queue, output_queue,
Xinput_duration, clock_duration)
XNQUEUE *node_queue;
XSQUEUE *input_queue;
XSQUEUE *clock_queue;
XSQUEUE *preset_queue;
XSQUEUE *output_queue;
Xint input_duration;
Xint clock_duration;
X
X{
X    int input_index;
X    int clock_index;
X 
X    (void) AssignDrive(input_queue, clock_queue);
X    (void) AssignPreset(preset_queue);
X    for(input_index = 0; input_index < input_duration; input_index++) {
X	(void) AssignInputs(input_queue, input_index);
X	if(clock_duration > 0) {
X	    for(clock_index = 0; clock_index < clock_duration; clock_index++) {
X		(void) AssignClocks(clock_queue, clock_index);
X		(void) ApplyInputVector(node_queue);
X	    }
X	} else {
X	    (void) ApplyInputVector(node_queue);
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.
XFirst, drive is propagated from the external inputs to as many nodes in 
Xthe network as possible.  
XSecond, charge 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)
XNQUEUE *node_queue;
X
X{
X    int num_iter;
X    int network_stable;
X
X    for(num_iter = 0, network_stable = 0; 
X    (!network_stable && (num_iter < MAX_ITER)); num_iter++) {
X	(void) ProcessDrivenNetwork(node_queue);
X	network_stable = (int) ProcessCSNetwork(node_queue); 
X    }
X    if(num_iter == MAX_ITER) {
X	(void) fprintf(stdout, "Error:  \
X	The circuit does not converge.  Exit 1.\n");
X	(void) exit(1);
X    }
X}
X
X/*
XThis function distributes drive to as many nodes in the network as possible.  
XSuper drive, originating from external inputs, is modulated by mosfets
Xin the network.  Drive propagates throughout the network, thereby
Xupdating nodal logic values.
X*/
X
Xvoid
XProcessDrivenNetwork(node_queue)
XNQUEUE *node_queue;
X
X{
X    int num_iter;
X    NODE *node;
X    int network_stable;
X
X    for(num_iter = 0, network_stable = 0; 
X    (!network_stable && (num_iter < MAX_ITER)); num_iter++) {
X	for(node = node_queue->head; node != ((NODE *) NIL); 
X	node = node->link) {
X	    (void) MosfetAction(node);
X	    if(node->touched) {
X		(void) EvaluateNode(node);
X	    }
X	}
X	network_stable = (int) UpdateNetwork(node_queue);
X    }
X    if(num_iter == MAX_ITER) {
X	(void) fprintf(stdout, "Error:  \
X	The circuit does not converge.  Exit 1.\n");
X	(void) exit(1);
X    }
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
Xint
XProcessCSNetwork(node_queue)
XNQUEUE *node_queue;
X
X{
X    NODE *node;
X    float logic_low_capacitance;
X    float logic_high_capacitance;
X    float logic_dontcare_capacitance;
X
X    for(node = node_queue->head; node != ((NODE *) NIL); 
X    node = node->link) {
X	if((node->present_drive == NO_DRIVE) && !node->acquired) {
X	    logic_low_capacitance = 0.0;
X	    logic_high_capacitance = 0.0;
X	    logic_dontcare_capacitance = 0.0;
X	    (void) AccumulateCSValue(node, &logic_low_capacitance, 
X	    &logic_high_capacitance, &logic_dontcare_capacitance);
X	    (void) SetCSValue(node, 
X	    (short) DetermineCSValue(logic_low_capacitance, 
X	    logic_high_capacitance, logic_dontcare_capacitance));
X	}
X    }
X    return((int) UpdateCSNetwork(node_queue));
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    node->touched = 0;
X    for(mosfet = node->mos_queue->head; mosfet != ((MOSFET *) NIL); 
X    mosfet = mosfet->link) {
X	if(mosfet->term[0]->changed || mosfet->term[1]->changed ||
X	mosfet->term[2]->changed) {
X	    node->touched = 1;
X	    if((int) MosfetOn(mosfet)) {
X		(void) MosfetActive(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.
X*/
X
Xint 
XMosfetOn(mosfet)
XMOSFET *mosfet;
X
X{
X    if((((mosfet->mos_type == NMOS) || (mosfet->mos_type == ENMOS)) &&
X    (mosfet->term[0]->present_value == LOGIC_HIGH)) ||
X    (mosfet->mos_type == DNMOS) ||
X    ((mosfet->mos_type == PMOS) &&
X    (mosfet->term[0]->present_value == LOGIC_LOW))) {
X	return(1);
X    } else {
X	return(0);
X    }
X}
X
X/*
XThis function simulates the action of a mosfet when a strong channel exists 
Xbetween its source and drain terminals.
X*/
X
Xvoid
XMosfetActive(mosfet)
XMOSFET *mosfet;
X
X{
X    NODE *source;
X    NODE *drain;
X
X    source = mosfet->term[1];
X    drain = mosfet->term[2];
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) + (1.0 / source->present_drive))));
X	mosfet->value[2] = source->present_value;
X    } else {
X	mosfet->drive[1] = NO_DRIVE;
X    }
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) + (1.0 / drain->present_drive))));
X	mosfet->value[1] = drain->present_value;
X    } else {
X	mosfet->drive[0] = NO_DRIVE;
X    }
X}
X
X/*
XThis function simulates the action of a mosfet when no channel (high channel 
Ximpedance, or "high Z") exists between its source and drain terminals.
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, 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    MOSFET *mosfet;
X
X    for(mosfet = node->mos_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    } else if(node != mosfet->term[0]) {
X	(void) fprintf(stdout, "Error:  Illegal node connection.  Exit 1.\n");
X	(void) exit(1);
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, 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    if(node->present_drive < SUPER_DRIVE) {
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, logic_low_drive,
X	    logic_high_drive, logic_dontcare_drive);
X	}
X	(void) RemoveStatic(node);
X    }
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    node->changed = 1;
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	node->changed = 1;
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->acquired) {
X	node->acquired = 1;
X	(void) SortCapacitance(node, logic_low_capacitance, 
X	logic_high_capacitance, logic_dontcare_capacitance);
X	for(mosfet = node->mos_queue->head; mosfet != ((MOSFET *) NIL);
X	mosfet = mosfet->link) {
X	    if((int) MosfetOn(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, value)
XNODE *node;
Xshort value;
X
X{
X    MOSFET *mosfet;
X
X    if(!node->set) {
X	node->set = 1;
X	node->next_value = value;
X	for(mosfet = node->mos_queue->head; mosfet != ((MOSFET *) NIL);
X	mosfet = mosfet->link) {
X	    if((int) MosfetOn(mosfet)) {
X		if(node == mosfet->term[1]) {
X		    (void) SetCSValue(mosfet->term[2], value);
X		} else if(node == mosfet->term[2]) {
X		    (void) SetCSValue(mosfet->term[1], value);
X		}
X	    }
X	}
X    }
X}
X
X/*
XThis routine updates the drive and value of each node in the network prior to 
Xthe next iteration.
X*/
X
Xint
XUpdateNetwork(node_queue)
XNQUEUE *node_queue;
X
X{
X    NODE *node;
X    int network_stable;
X
X    for(node = node_queue->head, network_stable = 1; 
X    node != ((NODE *) NIL); node = node->link) {
X	if((node->next_drive != node->present_drive) ||
X	(node->next_value != node->present_value)) {
X	    node->changed = 1;
X	    network_stable = 0;
X	} else {
X	    node->changed = 0;
X	}
X	node->present_drive = node->next_drive;
X	node->present_value = node->next_value;
X    }
X    return(network_stable);
X}
X
X/*
XThis function updates the values of the nodes that participated in 
Xcharge sharing.
X*/
X
Xint 
XUpdateCSNetwork(node_queue)
XNQUEUE *node_queue;
X
X{
X    NODE *node;
X    int network_stable;
X
X    for(node = node_queue->head, network_stable = 1; 
X    node != ((NODE *) NIL); node = node->link) {
X	if(node->next_value != node->present_value) {
X	    node->changed = 1;
X	    network_stable = 0;
X	} else {
X	    node->changed = 0;
X	}
X	node->present_value = node->next_value;
X	node->acquired = node->set = 0;
X    }
X    return(network_stable);
X}
X
X/*
XThis function assigns the maximal drive to inputs and clocks.
X*/
X
Xvoid 
XAssignDrive(input_queue, clock_queue)
XSQUEUE *input_queue;
XSQUEUE *clock_queue;
X
X{
X    SIGNAL *signal;
X
X    for(signal = input_queue->head; signal != ((SIGNAL *) NIL);
X    signal = signal->link) {
X	signal->node->changed = 1;
X	signal->node->present_drive = signal->node->next_drive = SUPER_DRIVE;
X    }
X    for(signal = clock_queue->head; signal != ((SIGNAL *) NIL);
X    signal = signal->link) {
X	signal->node->changed = 1;
X	signal->node->present_drive = signal->node->next_drive = SUPER_DRIVE;
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)
XSQUEUE *input_queue;
Xint input_index;
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		No meaningful bit string specified 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		No meaningful bit string specified for input '%s'.  Exit 1.\n", 
X		input->name);
X		(void) exit(1);
X	    }
X	}
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)
XSQUEUE *clock_queue;
Xint clock_index;
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		No meaningful bit string specified 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		No meaningful bit string specified for clock '%s'.  Exit 1.\n", 
X		clock->name);
X		(void) exit(1);
X	    }
X	}
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)
XSQUEUE *preset_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	    No meaningful value specified for preset '%s'.  Exit 1.\n", 
X	    preset->name);
X	    (void) exit(1);
X	}
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	    Illegal output logic value %d %s[%d].  Exit 1.\n",
X	    output->node->present_value, output->name, output_index);
X	    (void) exit(1);
X	}
X    }
X}
SHAR_EOF
chmod 0644 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 "state.h"
X
X/*
XThis function allocates and builds the state space for the simulator.
X*/
X
Xvoid
XBuildState(sim_file, drive_file, 
Xnode_queue, input_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;
XNQUEUE **node_queue;
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, node_queue, 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, node_queue, mos_count, node_count, 
Xinput_queue, clock_queue, preset_queue, output_queue)
XFILE *sim_file;
XNQUEUE **node_queue;
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_queue = (NQUEUE *) NQInit("node_queue");
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    (void) CreateNodeQueue(*node_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] = mosfet[1]->term[0] = mosfet[2]->term[0] = 
X    node[0];
X    mosfet[0]->term[1] = mosfet[1]->term[1] = mosfet[2]->term[1] = 
X    node[1];
X    mosfet[0]->term[2] = mosfet[1]->term[2] = mosfet[2]->term[2] = 
X    node[2];
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	Node '%s' is not connected to a mosfet.  Ignored.\n", node_name);
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 *mos_queue;
X    MOSFET *tail;
X    MOSFET *mosfet;
X
X    mos_queue = node->mos_queue;
X    for(mosfet = mos_queue->head, tail = mos_queue->tail; 
X    mosfet != tail; mosfet = mosfet->link) {
X	if((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	    Input '%s' does not exist.  Exit 1.\n", input->name);
X	    (void) exit(1);
X	}
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	    Clock '%s' does not exist.  Exit 1\n.", clock->name);
X	    (void) exit(1);
X	}
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	    preset '%s' does not exist.  Exit 1.\n", 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	    Output '%s' does not exist.  Exit 1.\n", output->name);
X	    (void) exit(1);
X	}
X    }
X}
X
X/*
XThis function creates the node queue from the node hash table.
X*/
X
Xvoid 
XCreateNodeQueue(node_queue, node_hash_table)
XNQUEUE *node_queue;
XNHASHTAB *node_hash_table;
X
X{ 
X    int index;
X    NODE *node;
X    NQUEUE *nqueue;
X    
X    for(index = 0; index < HASH_SIZE; index++) {
X	for(nqueue = node_hash_table->nqueue_array[index],
X	node = (NODE *) NQGet(nqueue); 
X	node != ((NODE *) NIL); node = (NODE *) NQGet(nqueue)) {
X	    (void) NQPut(node_queue, node);
X	}
X    }
X}
SHAR_EOF
chmod 0644 state.c || echo "restore of state.c fails"
fi
exit 0