Designing and implementing a Simpletron using C#

The last problem in Chapter 8 of Deitel’s Visual C# 2005: How to Program 2/e is to design and implement a simple machine-language processor called a Simpletron. I won’t go into the basics of the machine in great detail, since the book does so at great length. It is a really interesting problem, but there isn’t a great deal of information regarding C# implementations on the web, so hopefully this post will serve to fill part of that void. There are 2 parts to the problem:

1) Implement the Simpletron class in an extensible manner – This teaches you how to use Arrays in yet another way. Essentially in this problem, the Arrays are used both as RAM ( memory ) and as registers to hold changing values.

2) Enhance the Simpletron by adding the capability to perform additional operations – This portion of the problem forces the student to understand the nuances of low-level CPU operation.

I’ll only be posting code for part 1. Since this problem is often used in academic settings, I won’t be posting the other code, but what I’ll do instead is post errata I’ve found in the advanced problem, and my own interpretations of the enhancement requests. I found the wording in the book to be quite vague regarding how far to go with the modifications, so I hope this proves helpful. I searched fruitlessly for many hours with finding anything, so maybe someone else will be spared my pain. 🙂

Code outline for the Simpletron:

namespace Exercise8._32 {
    class Simpletron {
        // Input/output operations
        private const int READ = 10;
        private const int WRITE = 11;

        // Load/store operations
        private const int LOAD = 20;
        private const int STORE = 21;

        // Arithmetic operations
        private const int ADD = 30;
        private const int SUBTRACT = 31;
        private const int DIVIDE = 32;
        private const int MULTIPLY = 33;

        // Transfer of control operations
        private const int BRANCH = 40;
        private const int BRANCHNEG = 41;
        private const int BRANCHZERO = 42;
        private const int HALT = 43;

        private const int SIZE_OF_MEMORY = 100;
        private const int MIN_MEMORY_RANGE = -9999;
        private const int MAX_MEMORY_RANGE = +9999;
        private const int STOP_PROGRAM = -99999;

        private int accumulator;
        private int instructionCounter;
        private int operationCode;
        private int operand;
        private int instructionRegister;

        private int[] memory;

        public Simpletron() {
            memory = new int[SIZE_OF_MEMORY];
            accumulator = 0;
            instructionCounter = 0;
            operationCode = 0;
            operand = 0;
            instructionRegister = 0;
        }

        public void Run() {
            DisplayWelcomeMessage();
            UserDialogue();
            ExecuteProgram();
            DisplayMemoryDump();
        }

        private void DisplayWelcomeMessage() {

        }

        private void DisplayMemoryDump() {

        }

        private void UserDialogue() {

        }

        private int ValidateUserInput(int currentUserInput) {

        }


        private void ExecuteProgram() {

        }

        private int EvaluateOperationCode(int currentOperationCode,
                                          int currentOperand) {

        }

        private int AccumulatorOverflowValidation(int currentOperationResult) {

        }
    }
}

You can see that I have a Run method that is the primary execution method inside the class. There are also various validation methods that are called inside of some of the major methods. This code could have been placed inside of the main methods, but since it is called by many times, I thought it was wise to separate this code out. I would like to say that the particulars of the implementation aren’t super important – in this part of the problem, the main issue is the design. Another important thing to remember is to consistently use Test Driven Development. After each piece of code was created, I would run a few programs stressing those functions to ensure that the program was working correctly. It’s important that you test at least 3-4 variations of data to make sure that you are not designing only for a subset of your data.

I could have automated the testing by creating an overload of the run method that bypassed the userinput method, but for the scale of this project, performing the testing manually wasn’t time intensive. I would like to stress that had we wanted to continue modifying the program, we would have wanted to create automation at that point.

Okay, part 2 – the advanced section. I’d like to point out an errata on page 407: “In Exercises 25.10 and 25.11, we propose building a compiler that converts programs written in a high-level programming language (a variation of Basic) to Simpletron Machine Language. Some of the following modifications and enhancements may be required to execute the programs produced by the compiler: “ Well, I looked these problems up hoping for some clarification, but they don’t exist. 🙂

I believe requests a), b), c), and e) to be pretty self-explanatory. Below is some additional information that I believe will help with the remaining modifications.

d) Modify the simulator to use hexadecimal values rather than integer values to represent SML instructions – This modification is kind of weird, because if you followed the book, you almost certainly used an integer Array as your memory structure. It’s also kind of redundant to ask us to store things as Hex, since the computer is doing that anyway, but to shoehorn hex into your existing memory array would be a nightmare. And to what end? So I ended up interpreting this request to mean that on output, you should display all memory registers as Hex. I also added a section to the beginning asking the user which format: Decimal or Hex they would prefer. I know for troubleshooting I wanted Decimal since that is how I wrote the programs!

f) Modify the simulator to process floating-point values in addition to integer values – This one is a doozy. There are 2 possible ways to interpret this – Add a double memory array, accumulator, and a whole new set of instructions. The other is to continue to use integer memory and registers and instead encode the floating point data to fit within an integer field. I used the latter interpretation, since the former is kind of cheesy. One point in favor of the latter is that it will teach you an important lesson about CPU’s. Hint: Up until Intel’s 386 DX processors, all CPUs only had a single accumulator register. I really enjoyed this modification.

g) and h) Modify the simulator to handle string input – The only thing I need to mention is pay attention to this sentence in the clue the book gives you: Each two-digit integer represents the ASCII decimal equivalent of a character. That is the most important sentence in the clue. If you look up an ASCII table, you’ll see that they all have decimal representations, but that there are some with more than 2 digit representations. For instance, “h” or lower case h, is 104, so it’s impossible to fit into a 2 decimal bit memory location. If you did part f as I did, this problem might be easier for you, since similar thinking ( i.e. encoding/shifting ) is required.

Hope this helps! I had loads of fun solving this problem, and I hope that these hints help you focus on the important parts of the problem.

Advertisements

5 thoughts on “Designing and implementing a Simpletron using C#

  1. Pingback: 2010 in review | Fly Rice

  2. can u please help me with our special project which is similar to your objective which is to make a simpletron using C#.

      • Memory m = new Memory();

        m.LoadtoMemory(99, 7);
        m.LoadtoMemory(0, 876);
        m.LoadtoMemory(20, 4300);
        m.LoadtoMemory(1, 2222);
        m.LoadtoMemory(9, 12345);//invalid data(4 digits only)
        m.LoadtoMemory(100, 0); //invalid memory location 100
        m.LoadtoMemory(3, -4300);
        m.Dump();
        Console.ReadKey();

        Hi Agan, I think this will help you to make your project 😉
        Call this method in a LoadMemory.

  3. Hi agan I think this will help you

    public void MemoryLoader()
    {

    Memory m = new Memory();
    m.accumulator(LoadtoMemory);
    m.programCounter(LoadtoMemory);
    m.instructionRegister(LoadtoMemory);
    m.operationCode(LoadtoMemory);
    m.operand(LoadtoMemory);

    if(accumulator >= 0)
    {
    if (accumulator.ToString().Length == 1)
    Console.WriteLine(“Accumulator: \t +000” + accumulator);
    else if (accumulator.ToString().Length == 2)
    Console.WriteLine(“Accumulator: \t +00” + accumulator);
    else if (accumulator.ToString().Length == 3)
    Console.WriteLine(“Accumulator: \t +0” + accumulator);
    else
    Console.WriteLine(“Accumulator: \t +” + accumulator);
    }
    else
    {
    dummyAccum = Math.Abs(accumulator);
    if (dummyAccum.ToString().Length == 1)
    Console.WriteLine(“Accumulator: \t -000” + dummyAccum);
    else if (dummyAccum.ToString().Length == 2)
    Console.WriteLine(“Accumulator: \t -00” + dummyAccum);
    else if (dummyAccum.ToString().Length == 3)
    Console.WriteLine(“Accumulator: \t -0” + dummyAccum);
    else
    Console.WriteLine(“Accumulator: \t -” + dummyAccum);
    }

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s