Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using SimpleComponents;
- namespace Machine
- {
- public class CPU16
- {
- //this "enum" defines the different control bits names
- public const int J3 = 0, J2 = 1, J1 = 2, D3 = 3, D2 = 4, D1 = 5, C6 = 6, C5 = 7, C4 = 8, C3 = 9, C2 = 10, C1 = 11, A = 12, X2 = 13, X1 = 14, Type = 15;
- public int Size { get; private set; }
- //CPU inputs
- public WireSet Instruction { get; private set; }
- public WireSet MemoryInput { get; private set; }
- public Wire Reset { get; private set; }
- //CPU outputs
- public WireSet MemoryOutput { get; private set; }
- public Wire MemoryWrite { get; private set; }
- public WireSet MemoryAddress { get; private set; }
- public WireSet InstructionAddress { get; private set; }
- //CPU components
- private ALU m_gALU;
- private Counter m_rPC;
- private MultiBitRegister m_rA, m_rD;
- private BitwiseMux m_gAMux, m_gMAMux;
- //here we initialize and connect all the components, as in Figure 5.9 in the book
- public CPU16()
- {
- Size = 16;
- Instruction = new WireSet(Size);
- MemoryInput = new WireSet(Size);
- MemoryOutput = new WireSet(Size);
- MemoryAddress = new WireSet(Size);
- InstructionAddress = new WireSet(Size);
- MemoryWrite = new Wire();
- Reset = new Wire();
- m_gALU = new ALU(Size);
- m_rPC = new Counter(Size);
- m_rA = new MultiBitRegister(Size);
- m_rD = new MultiBitRegister(Size);
- m_gAMux = new BitwiseMux(Size);
- m_gMAMux = new BitwiseMux(Size);
- m_gAMux.ConnectInput1(Instruction);
- m_gAMux.ConnectInput2(m_gALU.Output);
- m_rA.ConnectInput(m_gAMux.Output);
- m_gMAMux.ConnectInput1(m_rA.Output);
- m_gMAMux.ConnectInput2(MemoryInput);
- m_gALU.InputY.ConnectInput(m_gMAMux.Output);
- m_gALU.InputX.ConnectInput(m_rD.Output);
- m_rD.ConnectInput(m_gALU.Output);
- MemoryOutput.ConnectInput(m_gALU.Output);
- MemoryAddress.ConnectInput(m_rA.Output);
- InstructionAddress.ConnectInput(m_rPC.Output);
- m_rPC.ConnectInput(m_rA.Output);
- m_rPC.ConnectReset(Reset);
- //now, we call the code that creates the control unit
- ConnectControls();
- }
- //add here components to implement the control unit
- private BitwiseMultiwayMux m_gJumpMux;//an example of a control unit compnent - a mux that controls whether a jump is made
- private OrGate orGate;
- private NotGate notGateA;
- private AndGate andGateD;
- private AndGate andGateMW;
- private AndGate andGatePC;
- private NotGate notEQ;
- private AndGate andGT;
- private NotGate notGT1;
- private NotGate notGT2;
- private NotGate notGE;
- private OrGate orLE;
- private OrGate orGate1;
- private NotGate not1;
- private Wire zero;
- private Wire one;
- private Wire JLT;
- private Wire JEQ;
- private Wire JNE;
- private Wire JGT;
- private Wire JGE;
- private Wire JLE;
- private WireSet zeroSet;
- private WireSet oneSet;
- private WireSet JLTSet;
- private WireSet JEQSet;
- private WireSet JNESet;
- private WireSet JGTSet;
- private WireSet JGESet;
- private WireSet JLESet;
- WireSet controlBits;
- private void ConnectControls()
- {
- //1. connect control of mux 1 (selects entrance to register A)
- m_gAMux.ConnectControl(Instruction[Type]);
- //2. connect control to mux 2 (selects A or M entrance to the ALU)
- m_gMAMux.ConnectControl(Instruction[A]);
- //3. consider all instruction bits only if C type instruction (MSB of instruction is 1)
- //4. connect ALU control bits
- m_gALU.ZeroX.ConnectInput(Instruction[C1]);
- m_gALU.NotX.ConnectInput(Instruction[C2]);
- m_gALU.ZeroY.ConnectInput(Instruction[C3]);
- m_gALU.NotY.ConnectInput(Instruction[C4]);
- m_gALU.F.ConnectInput(Instruction[C5]);
- m_gALU.NotOutput.ConnectInput(Instruction[C6]);
- //5. connect control to register D (very simple)
- andGateD = new AndGate();
- m_rD.Load.ConnectInput(andGateD.Output);
- andGateD.ConnectInput1(Instruction[Type]);
- andGateD.ConnectInput2(Instruction[D2]);
- //6. connect control to register A (a bit more complicated)
- orGate = new OrGate();
- notGateA = new NotGate();
- m_rA.Load.ConnectInput(orGate.Output);
- orGate.ConnectInput1(notGateA.Output);
- orGate.ConnectInput2(Instruction[D1]);
- notGateA.ConnectInput(Instruction[Type]);
- //7. connect control to MemoryWrite
- andGateMW = new AndGate();
- MemoryWrite.ConnectInput(andGateMW.Output);
- andGateMW.ConnectInput1(Instruction[Type]);
- andGateMW.ConnectInput2(Instruction[D3]);
- //8. create inputs for jump mux
- zero = new Wire();
- one = new Wire();
- orGate1 = new OrGate();
- not1 = new NotGate();
- one = orGate1.Output;
- orGate1.ConnectInput1(Instruction[0]);
- orGate1.ConnectInput2(not1.Output);
- not1.ConnectInput(Instruction[0]);
- JLT = m_gALU.Negative;
- JEQ = m_gALU.Zero;
- notEQ = new NotGate();
- JNE = notEQ.Output;
- notEQ.ConnectInput(m_gALU.Zero);
- andGT = new AndGate();
- notGT1 = new NotGate();
- notGT2 = new NotGate();
- JGT = andGT.Output;
- andGT.ConnectInput1(notGT1.Output);
- andGT.ConnectInput2(notGT2.Output);
- notGT1.ConnectInput(m_gALU.Negative);
- notGT2.ConnectInput(m_gALU.Zero);
- notGE = new NotGate();
- JGE = notGE.Output;
- notGE.ConnectInput(m_gALU.Negative);
- orLE = new OrGate();
- JLE = orLE.Output;
- orLE.ConnectInput1(m_gALU.Negative);
- orLE.ConnectInput2(m_gALU.Zero);
- //9. connect jump mux (this is the most complicated part)
- m_gJumpMux = new BitwiseMultiwayMux(1, 3);
- zeroSet = new WireSet(1);
- zeroSet[0].ConnectInput(zero);
- oneSet = new WireSet(1);
- oneSet[0].ConnectInput(one);
- JLTSet = new WireSet(1);
- JLTSet[0].ConnectInput(JLT);
- JEQSet = new WireSet(1);
- JEQSet[0].ConnectInput(JEQ);
- JNESet = new WireSet(1);
- JNESet[0].ConnectInput(JNE);
- JGTSet = new WireSet(1);
- JGTSet[0].ConnectInput(JGT);
- JGESet = new WireSet(1);
- JGESet[0].ConnectInput(JGE);
- JLESet = new WireSet(1);
- JLESet[0].ConnectInput(JLE);
- m_gJumpMux.ConnectInput(0, zeroSet);
- m_gJumpMux.ConnectInput(1, JGTSet);
- m_gJumpMux.ConnectInput(2, JEQSet);
- m_gJumpMux.ConnectInput(3, JGESet);
- m_gJumpMux.ConnectInput(4, JLTSet);
- m_gJumpMux.ConnectInput(5, JNESet);
- m_gJumpMux.ConnectInput(6, JLESet);
- m_gJumpMux.ConnectInput(7, oneSet);
- controlBits = new WireSet(3);
- controlBits[0].ConnectInput(Instruction[J3]);
- controlBits[1].ConnectInput(Instruction[J2]);
- controlBits[2].ConnectInput(Instruction[J1]);
- m_gJumpMux.ConnectControl(controlBits);
- //10. connect PC load control
- andGatePC = new AndGate();
- m_rPC.Load.ConnectInput(andGatePC.Output);
- andGatePC.ConnectInput1(m_gJumpMux.Output[0]);
- andGatePC.ConnectInput2(Instruction[Type]);
- }
- public override string ToString()
- {
- return "A=" + m_rA + ", D=" + m_rD + ", PC=" + m_rPC + ",Ins=" + Instruction;
- }
- private string GetInstructionString()
- {
- if (Instruction[Type].Value == 0)
- return "@" + Instruction.GetValue();
- return Instruction[Type].Value + "XX " +
- "a" + Instruction[A] + " " +
- "c" + Instruction[C1] + Instruction[C2] + Instruction[C3] + Instruction[C4] + Instruction[C5] + Instruction[C6] + " " +
- "d" + Instruction[D1] + Instruction[D2] + Instruction[D3] + " " +
- "j" + Instruction[J1] + Instruction[J2] + Instruction[J3];
- }
- //use this function in debugging to print the current status of the ALU. Feel free to add more things for printing.
- public void PrintState()
- {
- Console.WriteLine("CPU state:");
- Console.WriteLine("PC=" + m_rPC + "=" + m_rPC.Output.GetValue());
- Console.WriteLine("A=" + m_rA + "=" + m_rA.Output.GetValue());
- Console.WriteLine("D=" + m_rD + "=" + m_rD.Output.GetValue());
- Console.WriteLine("Ins=" + GetInstructionString());
- Console.WriteLine("ALU=" + m_gALU);
- Console.WriteLine("inM=" + MemoryInput);
- Console.WriteLine("outM=" + MemoryOutput);
- Console.WriteLine("addM=" + MemoryAddress);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement