CS 2200

CS 2200 Intro to Systems and Networks
Project 2

We have just spent the last few weeks implementing our 16-bit datapath. The simple 16-bit LC-2200 is capable of performing advanced computational tasks and logical decision making. Now it is time for us to move on to something more advanced.

We have invested a great deal of time and money into developing a more powerful LC-2200 computer. This one is 32-bits and supports interrupts.

The only trouble is that the interrupts support does not appear to be completed. We are quite disappointed by this, and so it is your assignment to fully implement and test interrupts using the provided datapath and the provided version of GT-Logisim.

This project has you add the additional support needed to make all this work properly. Your job will be to hook up the interrupt acknowledge lines to the input devices, modify the datapath to support interrupt operations, and write an interrupt handler to increment the clock value at a designated memory address.

  • Interrupt Support
    1. Part 1: Initial Interrupt Hardware Support
    2. Part 2: Controller Interrupt Support
    3. Part 3: Interrupt Handler for the Clock
  • What To Turn In

  • What We've Provided

    We have provided the LC2200-32 datapath, the completed XML (or FSM) file from the previous project and a assembly file to run on the datapath. Intergenerator.circ has also been provided, which will generate an interrupt signal every so often.


    Interrupt Support

    Part 1: Initial Interrupt Hardware Support

    Initial Interrupt hardware support

    For this part of the assignment you need to add hardware support for interrupts. You have been provided with LC2200-32 processor’s datapath.

    As you may have noticed we have no way to keep track of whether or not interrupts are currently enabled or disabled. Make an interrupts enabled register (the output of this register is referred to as IE signal in the rest of the project description) controlled by LdEnInt.

    We have provided you with the hardware for the clock interrupt. Connect the given hardware to the datapath such that:

    1. It should signal the controller when it receives an interrupt
    2. If it has fired an interrupt it should continue to signal the interrupt until it receives an IntAck signal. When it receives IntAck it should drive its device index to the bus in the following cycle (or if you prefer you may use the same cycle you assert IntAck.)

    To do this you will need to build hardware around what we have already given you. You will need hardware to store the interrupt signal in case it is not immediately acknowledged, and hardware that will drive the device index onto the bus in the cycle after it has received IntACK(or if you prefer it can be the same cycle). For the device index you should use 0x1.

    To simplify running interrupts, we have started the interrupt vector table at address 0x000000 in memory. Currently, when a program is runs on the LC2200-32, it starts the PC at 0x000000. You will need to change this. Add hardware so that when the processor is reset, the PC starts on 0x000010.

    For some interrupt related instructions we will need to directly access the stack pointer. Create the hardware needed to select the register $k0 within microcode. (Hint: use only the register selection bits that the main ROM already outputs to select it)


    Part 2: Controller Interrupt Support

    In this part of the assignment you will modify the microcode of the LC2200-32. Also refer to the new register order in the machine code for R type and I type instructions. This should not directly affect your project but you will need to know this for assistance in debugging.

    We are providing you two versions of LC-2200-32: one is the flat ROM version and the other is the one that uses a microsequencer. Use the appropriate one depending on your implementation choice for project 2.

    Please refer to LC-2200-32 processor reference manual for details on the enhanced instruction set of the LC-2200 32-bit processor with interrupt support.

    You have a choice in implementing the control for interrupt handling:

    1. If you are using a flat ROM for the state machine, be aware that you will need to alter it to accommodate interrupt support. Furthermore, do not be surprised if you end up with a ridiculous amount of wasted space and redundant microcode.

      Click here if you choose to do a flat rom.
    2. For extra credit, you can implement a microsequencer which will reduce the size of your microcode significantly. This is highly recommended as it will (a) decrease the size of the microcode, (b) aid in debugging, and (c) scale well when the microcode depends on external signals (e.g., interrupts enabled, Z).

      Click here if you choose to do a microsequenced rom.
    You can choose either the flat ROM or the microsequencer approach to implementing the control. The rest of the description is agnostic to this choice.
    1. First we must modify the controller. Modify the flat ROM or add the new Interrupts ROM as described above.
      We are also adding 2 new signals for interrupt control that are generated by the main ROM (that controls the datapath):

      1. LdEnInt (This asserts the load input of the IE register),
      2. IntAck (this sends an interrupt acknowledge to the device).
      You need to extend the size of the main ROM accordingly. Make sure that you fully hook up the microcontroller before continuing. In the datapath we have provided it is not fully hooked up.
    2. Second we must add a way to check for interrupts. You can accomplish this by modifying FETCH macrostate in the following way (basically we are doing the work that needs to be done implicitly by the processor in the INT macrostate described in Chapter 4 of the textbook and class lectures in the FETCH macrostate itself):
      1. Check to see if an interrupt is raised
      2. If not, continue as normal.
      3. If yes:
        1. Save the current PC into $k0.
        2. Disable interrupts.
        3. Assert the interrupt acknowledge line, and then a cycle later (depending on how you chose to implement part 1) use the value put out on the bus by the device that received the IntAct signal, to index into the Interrupt Vector Table (kept in memory at 0x000000) and retrieve the new PC value. The new PC value retrieved from the table (i.e., loaded from the memory) is then loaded into the PC.
        4. Continue with the FETCH marcrostate.

      NOTE: To do this new conditional in the FETCH macrostate, we have supplied you with a new attribute of the state tag, onInt. onInt works in the same manner that onZ did in Project 1. After a microstate in which you enable the LdEnInt signal from the main ROM you should have two states, one will be marked with onInt="true" and the other onInt="false", depending on the state of the IE register.

      For the extra-credit version (i.e., microsequenced ROM) this new attribute will be used as follows:
          <State name=”name0” onInt=”true”>

      For the STANDARD rom, this new attribute is defined as follows:

      FETCH0:
      	ExampleSignal
      	onint FETCH1 else FETCH2

    3. Third we need the three new instructions for supporting interrupts as described in Chapter 4. These are the EI, DI, and RETI instructions. You need to write the microcode in the main ROM controlling the datapath for these three new instructions.


    Part 3: Interrupt Handler for the Clock Interface

    Now that we have interrupt support within the processor, we need to write an interrupt handler for our clock interrupt so that it will not interfere with the correct running of any user program.

    In prj2.s we provide you with a program that runs in the background. For part 3 of this project, you have to write an interrupt handler for the clock device. Refer to Chapter 4 of the textbook to see how to write a correct interrupt handler. As detailed in that chapter, your handler will first save the current value of $k0 (the return address to where you came from into this handler), and the state of the interrupted program. Prior to doing the actual work for handling the clock interrupt, the handler should enable interrupts (which would have been disabled implicitly by the processor in the FETCH macrostate). The actual work to be done in the handler is to increment a clock variable in memory. Once this work is done, the handler should restore the state of the original program and return to where it came from using RETI.

    The handler you have written should run every time the clock interrupt is triggered. The handler should be written such that interrupts can be nested (i.e., higher priority interrupts should be allowed while running the handler). With that in mind though, interrupts should be enabled for as long as possible within the handler.

    Load the starting address of the handler into the interrupt vector table at address 0x000001.

    The actual work to be done in the handler is as follows. It keeps time in memory at some well-known locations: at location 0xF00000 it stores seconds; at 0xF00001 it stores minutes, and at 0xF00002 it stores hours. Assume that the clock interrupt hardware fires every second.

    More information about this part of the project is included in prj2.s. Search for the two FIX MEs to find places where you need to modify code.

    More information on the 32 bit assembly is available in LC-2200-32.html.


    What To Turn In

    You should turnin the following files to Tsquare:

    0. The prj2.s file containing your interrupt handler and our given code.

    1. The LC-2200-32.circ file containing your LC2200 32 bit processor.

    2. The microcode_lastname.fsm file containing the microcode. microcode_lastname.xml if you make a microsequencer.

    3. The intergenerator.circ file containing the interrupt generator.




    End of CS 2200 Project 2