In Java, C++, or C#, write a program to simulate a digital circuit. You program should have an abstract class named CircuitElement with subclasses Gate, Wire and Battery. Abstract class Gate has abstract subclasses BinaryGate and UnaryGate. UnaryGate has subclasses NotGate and BufferGate. BinaryGate has subclasses OrGate and AndGate. Wire should have a Boolean member variable named value initialized to false and a String member variable named name. Gate should have a Wire member variable named output. UnaryGate should have a Wire member variable named input. BinaryGate should have Wire member variables named input1 and input2. Battery should have two collections (e.g., ArrayList) of Wire instances, one named high and the other named low.
Your program should accept as a command-line argument the name of a file that contains a digital circuit specification. It reads the file, creates the Wire, Battery, and Gate instances specified in the file, then runs the simulation until no Wire values change. Finally it prints out the values of all Wires.
The circuit spec file lists object instances, one per line. Each line starts with the class name followed by instance variable name and value. You may assume that Wires will always be given first, then Batteries, and finally Gates. Collection type values are given in parentheses. Wire type member variables are specified by giving the name of the Wire. For example, the following circuit spec creates a half-adder and should be stored in a file named half_adder11.cir:
WIRE name a WIRE name b WIRE name c WIRE name d WIRE name e WIRE name f WIRE name sum WIRE name carry BATTERY high (a b) low () NOTGATE input a output c NOTGATE input b output d ANDGATE input1 a input2 d output e ANDGATE input1 b input2 c output f ORGATE input1 e input2 f output sum ANDGATE input1 a input2 b output carry
Your program should print out the names of all the Wires in the same order as given in the circuit spec file. Each name should be followed by an "=", the value of the wire printed as a 1 for true and 0 for false and a space before the next name. For example, your program should print for the above half-adder:
a=1 b=1 c=0 d=0 e=0 f=0 sum=0 carry=1
Test your program by creating a series of test circuit spec files that all contain exactly one Gate type and all possible inputs for that Gate. For example, for an AndGate, you will need four files, each with the two input Wires connected to different combinations of high or low of the Battery. Name each file after the Gate type and the input values. For example, the following spec file should be named AndGate10.cir:
WIRE name A WIRE name B WIRE name Out BATTERY high (A) low (B) ANDGATE input1 A input2 B output Out
Your circuit simulator does not have to do any error checking such as the same Wire connected to either multiple Batteries and/or multiple Gate outputs, Gates with missing inputs and/or outputs, Gates with Wire names that were not specified as Wires earlier in the file, extraneous nonsensical characters in the input file, input file missing or read protected, etc.
Record a sample run with multiple calls to your program with inputs: each of your test circuit spec files and the above half_adder11.cir and the three other possible half_adder??.cir variants. Start your assignment NOW since this is a long assignment. My solution is about 250 lines long (about 215 not including blank lines). Your solution will most likely be longer.
I would recommend (recommendations are not assignment specs and you are free to implement another way -- note that when I use"should" above, those are not recommendations, but are strict assignment specs that you must follow) that you also create a class Circuit to store a Java LinkedHashMap of all Wires (to make it easier to print out all wires and look up a Wire given a String name), all Gates (see below) and all Batteries. I recommend a Wire method for printing a Wire and a Gate method named compute for computing and setting the new value of the output Wire based on the value(s) of the input Wire(s). The compute method of Gate would be abstract with actual implementations at the leaf classes such as NotGate. Initially in the simulation, I recommend you set the values of all Wires listed in the high collections of all Batteries to true (since all Wire values are initialized to false, you can ignore the low collection of a Battery). I recommend you have a "global" variable (e.g., a static member variable of Circuit) named changed that keeps track of whether compute has changed the value of the output Wire. Then you can have a loop that initially sets changed to false, calls compute on each of the collection of Gates, and repeats if changed is true. Of course each compute method is responsible for setting changed to true if its computed value for the output Wire is different from the old value of that Wire. I recommend the Java Scanner class to parse the input file. If you don't know regular expressions, then you can just use the scanner next() method to grab the next word from the input and/or the scanner nextLine() method to grab the rest of the line from the input and then use String manipulation to do the rest.
To submit your assignment, zip all of your source code files (your .java or .cpp or .cs and any .h files), all of your .cir circuit spec files and the transcript of a sample run and email the zip archive to our TA, dwkang@hawaii.edu.