18-348 Lab #5

Spring 2015

NOTE: Lab 5 consists of two components (Lab 5 Part A and Lab 5 Part B).

Relevant lectures:
- Part A: Lecture 8. Memory and Memory Bus
- Part B: Lecture 9. Economics and Code Optimization

Links to all files referenced in the lab and prelab can be found in the Files section at the end of this document.

Caution -- this lab has the most challenging hardware construction portion of the course -- start early on building your hardware!!


Pre-Lab 5 - Part A:

Goal: To familiarize you with the operation of a bidirectional memory bus.

Discussion:
A bidirectional memory bus provides an interface between a CPU and a block of memory. It is bidirectional because it allows the CPU to both write values to the memory and read values from the memory. The bus is operated using a pair of control lines - the Addr.H/Data.L line and the Write.H/Read.L line. Asserting Addr.H indicates that a memory address is being driven on the bus, while asserting Data.L indicates that data is being driven on the bus. Asserting Write.H indicates the CPU is driving data on the bus to write a memory address, while asserting Read.L indicates the CPU will read the data asserted on the bus by the memory or I/O device.

Memory Bus timing diagram

Figure 1:  Memory Bus Timing Diagram.

Procedure:
None. This section only involves answering questions.

Questions:
For each question below, assume the memory bus is configured as shown in the memory bus schematic.

1.  For Figure 1, in 15 words or fewer per item, briefly describe what is happening at each of T1 through T6, including whether that time instant is part of a read cycle or part of a write cycle.
T1:
T2:
T3:
T4:
T5:
T6:

2.  Suppose the current state of the memory is reflected by the values in the table below:

Address
Value
$9C
$A4
$CC
Undefined

We want to read the value at address $9C, then write the one's complement of that value to address $CC.  Based on this sequence, indicate the value on the Address/Data bus at each time (use the values listed in the timing diagram in Figure 1 above, e.g. Address1, Address2, Data1, Data2).  Additionally, indicate which element in the circuit is driving the value on the Address/Data bus.  You should refer to the chips by their designation in the schematic (e.g. "U14" refers to the 74LS373 latch).


Value
Driving Element
Address1


Data1


Address2


Data2


3. Using the values you obtained in question 2, identify the values of these internal lines of the memory bus circuit at the corresponding time instance. (Note: we are asking for the pin output values, and not the value "inside" the register if it isn't being driven onto the output pins.) Use a hexadecimal notation to indicate a range (0 is the LSB).  For example, if Q7, Q6 and Q3 are 1 and the rest of the values are 0, then the value you would enter is "$C8".  Use a "Z" to indicate high-impedance/disabled output. Use an "X" if the value is unknown, such as when it depends on operations that occurred before the timing diagram started.

Time
U14 Q7:0
(Address Latch)
U9 Q7:0
(Data Register)
U7 B7:0
(Read Buffer)
T1



T2



T3



T4



T5



T6



4. (Bonus) Submit a revised schematic that shows the setup for decoding the addresses $A3 for read and $B3 for write. Include only connections to U14, U10, U11, U16A and U15A -- you can omit the rest because they should be the same. If you have to add an inverter or two then do so. NEATLY hand-drawn of just those chips and their connections and scanned is OK. Better is probably to edit or draw over the existing schematic. (For example, white-out connections and draw new ones.)


Pre-Lab 5 - Part B:

Goal:

Discussion:

The function of a compiler is to translate high level code (in this case, C code) to assembly.  In order to do this and do it efficiently, the compiler must manage resources such as stack memory, registers, and code allocation. But no compiler is perfect, and embedded system compilers are often very far from perfect. You can help the compiler by writing code that it is good at optimizing. In this lab, you will take a function which adds an array of numbers and implement a new C language version of the function so that it compiles more efficiently.

Procedure:

Part 1:

  1. Create a new C project.  Be sure to include the Full Chip Simulator as a build target.  Download prelab_5b_skeleton.c.  Rename it to prelab_5b_andrewid.c (with your appropriate andrew ID) and replace the main.c file in your project with it.
  2. Implement the ptr_add( ) function using pointer math instead of array references. This course assumes you know C; if you are rusty on pointers a web search on the keywords (C pointer tutorial) will reveal many sources of information. (Note: you will have to comment out the function ptr_add2 for this part to get the code to compile cleanly.)
  3. You are NOT permitted to use loop unrolling to speed up the code. (Loop unrolling generally involves making copies of lines of code to perform repeated operations in-line to avoid loop overhead. If you aren't sure if you are doing loop unrolling, ask a TA.)
  4. Your code must work with any valid input and outupt parameters (e.g., with an array that is a different size). You are NOT permitted to modify the parameter inputs (the "signature") of the functions. You are NOT permitted to directly access global variables that might be passed to the routine, bypassing the parameter passing mechanism.
  5. Verify the compiler options.  Select Edit > Full-Chip Simulation Settings from the menu (you must have the full-chip simulator as the current target).  Navigate to Target > Compiler for HC12 .  The value in "Command Line Arguments" SHALL be " -CpuHCS12 -D__NO_FLOAT__ -Ms "
  6. Run your ptr_add( ) function using the full-chip simulator.  Verify that it gives the same result as subscr_add( ).
  7. Use the simulator to measure the number of cycles the subroutine takes to run.  Your cycle count shall include all the compiler-generated setup and cleanup code   The simplest way to measure this is to place a breakpoint in the C-code at the function call, record the initial cycle count value, then Single Step Over (F10) the function call.   For full credit, optimize the subroutine code in C so that it executes in fewer than 1560 cycles (this shouldn't be too tricky if you use pointer code).

Bonus (Optional):

  1. For bonus credit, implement ptr_add2( ). You are NOT permitted to use loop unrolling to speed up the code. (Loop unrolling is a valid optimization in many contexts, but to keep this lab simple enough to fit within available time and still teach the relevant concepts, we have to impose this constraint on optimization.)
  2. For this part, you may make any changes to code and enable additional compiler optimizations as you wish.  Use the " Options" button in the Compiler for HC12 area of the simulation settings (see step 3 in part 1).
  3. Run the code and verify that the results for ptr_add2( ) correspond to those for subscr_add( ).
  4. Measure the cycle count to execute the function as described in step 5 of part 1.  To receive bonus credit, your implementation must execute in fewer than 960 cycles.

Questions:

Note that all questions from this section MUST reflect the results you obtain with the default compiler settings, as described in Part 1, Step 3.

  1. Record the values returned for each function and the number of cycles for execution.  For reference, the values for subscr_add( ) have been included.
    Function Name
    Return value
    # of cycles
    subscr_add( )
    15150
    2236
    ptr_add( )


  2. Disassemble the C-code and measure the footprint (number of program instruction bytes consumed by the entire subroutine) of the code for each function (from the function label to the RTS).  Record the values in the table below.
    Function Name
    Footprint
    (decimal number of bytes)
    subscr_add( )

    ptr_add( )

  3. (Bonus) For this question, you may modify compiler settings. Fill in the table below for the ptr_add2( ) function.
    Function Name
    Return value
    # of cycles
    Memory Footprint
    (decimal bytes)
    ptr_add2( )


Hand-in Checklist (65 + 13 points):

All non-code submissions shall be in a single PDF document.

Part A:

  1. (20 points) Answers to the questions above.
  2. (Bonus: 4 points) Answer the bonus question.

Part B:

  1. (25 pts) Submit code for prelab_5b.c. Code must conform to course style sheet to obtain full credit.
  2. (20 pts) Turn in the answers to questions 1 & 2 above
  3. (Bonus: 9 pts) Include the implementation of ptr_add2( ) in your prelab_5b.c.  Turn in the answers to the bonus question 3.  The code must be present and the answers to the bonus questions must be included with your writeup to obtain any bonus credit.

The pre-lab for this assignment is intentionally simple because the lab itself will be moderately time consuming. We strongly suggest you also start wiring the circuit on Friday, and not wait until Monday to begin construction. This is the most complicated hardware you will construct for this course, and if you are not experienced it might take some time to get right.

Refer to the LAB FAQ for more information on lab hand-in procedures and file type requirements.  You MUST follow these procedures or we will not accept your submissions.


Lab 5 - Part A

Goal: Demonstrate that you can integrate the MCU with an external bidirectional memory bus that you build.

Discussion: 

You will implement read/write interface for the MCU. We have provided you with a project shell. It contains three files of interest - main.c, EmuIO.h, and EmuIO.c. main.c contains a simple program that reads from memory location $9C and writes the value it reads to memory location $CC. EmuIO.h contains function prototypes to interface with memory bus. EmuIO.c contains the function definitions for the functions prototyped in EmuIO.h.

Your job is to implement the emu_IO_init(), write_byte(), and read_byte() functions in EmuIO.c so that the main function will operate correctly. Use PTT as the 8-bit bidirectional bus (pin PT0 should correspond to the LSB of the data bus), PORTA0 as Addr.H/Data.L control line, and PORTB4 as the Write.H/Read.L control line.

Hints:

Procedure:

Part 1:

  1. Make sure the project board is powered down and disconnected from the PC. Set all jumpers to default positions.
  2. Disconnect the USER jumpers on the APS12C128 module.
  3. Disconnect the UFEA jumpers on the project board.
  4. Wire the board according to the memory bus schematic and the instructions above.
  5. Follow the lab safety procedures to check your circuit before powering the project board.

Part 2:

  1. Download the lab_5a_c.zip file. Extract the project and open it in Code Warrior.
  2. Implement the functions in EmuIO.c with the following prototypes:
  3. Values read from the switch shall use the following convention. This may require software manipulation of data values to attain correct value polarity.
  4. Values written to the LED display shall use the following convention. This may require software manipulation of data values to attain correct value polarity.
  5. Write a program to read switch values and put the switch value out on the LEDs. Test to see that it works properly by changing one switch at a time and observing correct LED changes.

(Bonus) Part 3:

  1. Set the switch value to $45.  Check that the value $45 is placed on the LEDs. Using a logic probe, measure values listed in the following table.
  2. Single step through the program until you reach the appropriate T1 through T6 point and measure signals at that point. (hint: this is a measurement of the values you predicted would be present in the pre-lab 5 part A).
  3. If there are any differences between this table and your prelab predicted values, explain why (maximum 200 words)

U14 Q7:0 U9 Q7:0 U7 B7:0
T1



T2



T3



T4



T5



T6



(Bonus) Part 4:

Write a program that has the LEDs "chase" each other (i.e., some sort of circular pattern) each other. Vary the speed to 256 different speeds using the DIP switch settings. For a DIP switch input of 0 the pattern should be stopped, and for a setting of 255 the pattern should be so fast as to be blurred.

Part A - Demo Checklist: (60 + 5 points)

  1. (60 points) Demo the program to the TA.
  2. (Bonus: 5 points) Demo the bonus program 2 (part 4) to the TA.
    There are no demo points for Bonus 1 (part 3).

Lab 5 - Part B

There is no lab procedure for lab 5 part B.  You are only required to demo the execution times of your code to the TA using the simulator in the lab.

Part B - Demo Checklist: (35 + 5 points)

To receive credit, the cycle times for your demo must be less than or equal to the values you included in your prelab writeup.  If your demo takes more cycles than the values reflected in your prelab, you will not get credit for that part of the prelab or the demo.  (To ensure fairness, trivial differences of fewer than 10 clock cycles difference will be ignored in enforcing this requirement so long as your prelab analysis was performed in good faith.)

  1. (35 pts)  Demo either partner's prelab_5b.c from your prelab with the default compiler options (see Part 1, Step 3 of the prelab).  Demonstrate the cycle count for subscr_add( ) and ptr_add( ) to the TA.  Verify that the return values match.  The TA may ask you to change the values in the array.
  2. (Bonus: 5 pts)  Demo either partner's prelab_5b.c with any compiler optimizations you wish.  Demonstrate the cycle count of ptr_add2( ) to the TA.

Hand-in Checklist: (90 + 13 points)

Part A:

  1. (5 points) List any problems you encountered in the lab and pre-lab, and suggestions for future improvement of this lab. If none, then state so to get these points.
  2. (75 points) Submit a listing of your code for Part 2. Submit only the EmuIO.c file. Code must follow the coding standard for the course to receive full credit.
  3. (Bonus: 5 points) Complete the table in Part 3 and answer the accompanying question
  4. (Bonus: 5 points) Submit a listing of your bonus program from Part 4. (You must successfully demo to receive the lab writeup bonus.)

Part B:

  1. (5 points) List any problems you encountered in the pre-lab, and suggestions for future improvement of this lab. If none, then state so to get these points.
  2. (5 points) Submit code files containing subscr_add() and ptr_add() functions. Code must be fully commented to receive full credit.
  3. (Bonus: 3 points) Submit code files containing ptr_add2() function. Code must be fully commented to receive full credit.

NOTE: Code listings for lab 5 part B may differ from the prelab, especially for ptr_add2(), if you discover further optimizations after prelab submission.

Refer to the LAB FAQ for more information on lab hand-in procedures and file type requirements.  You MUST follow these procedures or we will not accept your submissions.


Hints and Suggestions:

Part A:

Part B:

FILES for this lab:

Part A:

Part B:

Relevant reading:

Part A:

Part B:

Also, see the course materials repository page.


Change notes for 2015: