CS 1220 – Spring 2009
I. Requirements: Develop a digital simulator, which reads the circuit description and input vectors from
files, performs the digital simulation, and then writes the results back to file.
a. The circuit will consist of the following types of digital elements: AND gates, OR gates, NAND
gates, NOR gates, NOT gates, XOR gates, and XNOR gates. Each of these gates will have a time
delay associated with it, reflecting the delay from when an input changes until that change shows
up at the gate output.
b. The circuit will also contain input and output pads, simulating a test environment that allows the
user to set the inputs and read the outputs.
c. The circuit will be stored in a file as a list of circuit elements and the “nodes” they connect to.
Nodes can be thought of as the wires connecting the gates. The circuit file will have the following
2-input gates: gate_type delay input1_node input2_node output_node
Example: NAND 5ns 2 4 6
1-input gates: gate_type delay input_node output_node
input pads: INPUT name output_node
output pads: OUTPUT name input_node
d. The input vector will be in the following format. It will reflect the input names and the times (in
ns) they change. The same input may be changed multiple times in the input file.
INPUT name1 time value (0/1)
INPUT name2 time value
e. The output file format will be similar to the input vector. For any transition of the output pad
value, the output file should reflect a line showing the output pad name, the time (in ns, relative to
time zero), and the new value.
OUTPUT name1 time new_value
OUTPUT name2 time new_value
f. Digital logic can take on 3 values: 0, 1, and X. The outputs pads and all gate outputs should be
initialized to X at time zero.
II. Design: The design that will be implemented will be the following. We will create a series of classes
(Simulator, Event, Wire and Gate). The simulator will load two .txt files a vector and circuit file. Once it
is given the file it will parse the files line by line first creating the circuit itself (the gates and wires
connected properly). Then it will proceed and read the vector file (the list of changing value events) and
will create an event for each one of these changes read in from the vector file, and they will be added to
the event queue (priority queue) in order of time and tie value. Then after loading all the data from the
input files, it will proceed to simulate the circuit. With the provided values, the wires will change values
accordingly (as they are ordered in the priority queue). Every time that a wire changes value, the wire
will tell any of its output gates to recalculate their values to see if their values will change or not. As
gates recalculate they might change the value of the wires connected to their outputs, and will cause the
wires to “tell” the gates to recalculate. Every time a recalculate function is called, the gates will schedule
an event and add it to the event queue accordingly (again ordered by time and then tie value). The
simulation will run until there are no more events in the priority queue. As a result of the simulation, and
output file (output.txt) will be created in which all the changes to the wires will be recorded in the
following fashion (“At time x, Wire #, (INPUT/OUTPUT) (if empty the change is from the loaded
vector file) changed to VALUE”). The simulator will be wrapped in a GUI which will allow the user to
load any .txt files for the simulator to read. At the end of the simulator, a graphic will be created inside
the GUI showing the waveform of the different wires that were created from the read input files.
III. Implementation: For the project, we are creating four classes: Simulator, Event, Wire, and Gate. For
the Simulator class, we have attributes to keep track of the current time in the simulation (int sim Time),
a variable (int eventTie) used to keep track of and determine ties when events scheduled at the same
time, a priotity queue that store events (myPQ) and determines priority based on time, and an statically
allocated array to keep track of all of the pointers to all of the wiresw (Wire* wireList). This class also
provides respective gets for the simTime and tieValueand and a set method for the tieValue. It has one
default construction with no parameters that initializes simTime and tieValue to 0, initializes every
element of the wireList array to NULL, and makes sure the priority queue is empty, and if not, then
empties it. Methods are provided to load the circuit (loadCircuit) and vector (loadVector) input files
(which return a boolean depending on whether the file opened successfully), to run (simulate) and reset
(reset) the simulation, to add an event to the priority queue (addEvent), and finally to return a wire
pointer given a wire number (getWirePtrFromNum) or string input (getWirePtrFromInput). The
Simulator class does not inherit from other classes, although it does serve as a base class for the Gate
class. Next, the Event class is designed to keep track of any changing wire values. It has attributes to
keep track of the wire (Wire* eventWire) that is being changed, the value of the wire (ThreeValue
eventValue), when the event is schedule for (int eventTime), and a variable (int eventTie) used to keep
track of and determine ties when events scheduled at the same time. For all classes, the Value type will
be an enumerated data type where zero equals zero, one equals one, and X equals two. Methods
included two constructors, one with and one without parameters; get functions to get the value
(getValue), wire pointer (getWire), and time (getTime); and an overloaded less than operator so that the
queue will be able to distinguish which event takes priority, including dealing with ties. For the Wire
class, attributes include Gate pointers for both the input wire (Gate* in) and output wire (Gate*
out[MAX_FANOUT]), which is an array of up to the constant MAX_FANOUT (which in our case
equals ten). It also has attributes (int wireNum) to identify the wire number and the inputs (string
inputTitle) and outputs (string outputTitle). Finally, it has an attribute of type Value (Value wireVal) to
keep track of the current value of the wire. Its methods include two constructors, one with and one
without constructors and respective get and set functions to get and set all the attributes of the class. The
Gate class also is inherits from the Simulator class, giving it the ability to add events to the priority
queue as well as to see the current simulation time and value of the tieValue variable. For the fourth and
final class, the Gate class, its attributes include two inputs of type wire point (Wire* in1 and Wire* in2)
and one output of the same type (Wire* out). In addition, attributes include an integer to keep track of
the delay time (int delay), a string to identify the type of the gate (string gateType), and a variable of
type value to store the previous gate value (Value prevValue). Its methods include two constructors, one
with and one without constructors; set functions to set all of the member attributes (setIn1, setIn2,
setOut, setDelay, and setGateType); and a method to recalculate the output of the gate depending on the
inputs (recalculate). In conclusion, the Event class is associated with the Simulator and Gate classes, the
Wire class is associated with the Event and Gate classes, and the Gate class is associated with the Wire
class and also inherits from the Simulator class.
IV. Testing: To test the digital circuit simulator, using the circuit and vector files that were provided to
us we ran the program and received an output file and a graphic showing the waveform. We also
proceeded to by hand design the circuit that was given to us, and make sure that the output the simulator
created was correct. To ensure that the simulator indeed ran correctly, we made some changes to the
provided Circuit and Vector files and loaded them to the simulator again. We made the changes by hand
and proceeded to compare the results.
V. User’s Guide: Before the simulation can be run, the user must first load both the circuit and vector
files by clicking the Load Circuit and Load Vector buttons which will open up an open file dialog. If
each file was opened successfully, then the background color of the textbox will turn light green (or light
red if the file opening failed). After both files are loaded, the user can then press the simulate button,
which will generate an output file named “output.txt.” The output text file will list all events, with each
line being as follows: “At time T, Wire # N changed to a value of V” where T equals the time, N equals
the wire number, and V equals the value of the wire (0, 1, or X). In addition, after the simulation button
is pressed, the program will draw a waveform on the screen for each wire. At this point, the user can
reset the simulation and start over, or apply settings (left margin, time scale unit, max grid seconds) to
change the waveform drawing.
VI. Summary/Conclusion: Our code compiles without error and executes correctly. In all tests, the
digital circuit simulator produced the correct output as the one we obtained after doing the same circuit
by hand and comparing the results. During the tests there were no run-time errors and the graphic
waveform produced was congruent with the output and the hand-drawn circuit.
Signed: David Riggleman .
Ham Vivas .
VI. Lessons Learned: From this project, we were able to see the complications that can come within
programs that need multiple inclusion when compiled. It was a very good experience to write a program
in a team having two different “programmers” working together for one project. It was good to see how
exact both of them need to be in order for the program to compile correctly. Also, it was very profitable
to see and experience the importance for both programmers to have good communication between them
so that when any changes are made to the program, both know the changes and are able to change their
own code accordingly.