Programming Assignment 5 - Hyperthreading!

Advanced Programming II, Spring 2004


Due Date

This assignment is due by 2:00 p.m. on Tuesday, 27 April.

See the assignment turn-in page (last modified on 9 February 2004) for instructions on turning in your assignment.

Background

Operating systems are usually responsible for multiplexing the CPU so that it appears that more than one process is running simultaneously. Hyperthreading is a technique that moves process multiplexing into the CPU so that more than one process can actually run simultaneously.

A hyperthreading CPU has an almost traditional architecture . It has functional units (an adder, a multiplier, and so on) and the functional units share access to the same set of CPU registers and to primary store. The architecture has eight CPU registers named r0 through r7; addresses in primary store are referenced by the names of the associated variables (which are assumed to be different from the register names). The initial value of primary-store locations and the registers is an arbitrary value; different locations and registers may have different values (or they may not - it's arbitrary).

A CPU instruction is either a move instruction or an operator instruction. All instructions execute in one clock tick. A move instruction has the form

move dst src

and moves the value stored in src to the location given by dst. Both src and dst can be either memory addresses or registers, with the restriction that both cannot be memory addresses; that is at least one must be a register.

An operator instruction has the form

opr dst src

where opr is one of the usual operators +, - and so on and both src and dst are registers. An operator instruction performs the computation

dst = dst opr src

Each operator has its own functional unit; that is, the add operator + uses the addition functional unit, the division operator / uses the division functional unit and so on.

The three parts of a CPU or move instruction are separated from each other by at least one non-newline space character. Memory locations are referred to using C++-syntax variable names.

The translation from high-level language statements to instructions is straightforward. For example, the high-level statement

a = b + c

can be translated into the instructions

move r0  b
move r1  c
+    r1 r0
move  a r1

Hyperthreading occurs when the CPU issues and executes two instructions at the same time; the instructions can be from the same program or from two different programs. Two instructions can be executed simultaneously if they use disjoint sets of resources (registers and functional units). For example, two add instructions could not be issued at the same time because they would conflict over the adder; similarly, two instructions that used register i, either as a source or target, could not be issued together.

A hyperthread schedule is a sequence of composite instructions, in which each composite instruction is either a single CPU instruction or a pair of non-conflicting CPU instructions. For example, the simple program

move r0  b
move r1  c

produces the hyperthread schedule

move r0  b ; move r1  c

A composite instruction also executes in one clock tick, but it executes all its component simple instructions in parallel.

The Problem

Write a hyperthread scheduler that inputs from std-in a pair of programs and outputs to std-out the shortest possible hyperthread schedule that performs the same computations as the input programs.

Valid hyperthread schedules should obey these constraints:

Input

The input will be a pair of programs. The two programs are separated by one or more empty lines.

A program consists of a sequence of one or more CPU instructions. Each instruction appears in a single line, and a single line contains exactly one instruction. Instructions in a program appear consecutively; there is no blank line between instructions in a program.

Operators can be any of the standard C++ binary operators except for the short-circuit operators && and ||; see Appendix A of Deitel and Deitel for details. Assume there is a functional unit for each operator.

Output

Output should be a single hyperthread schedule, which consists of a sequence of one or more composite issues. Each composite issue appears in a single line, and a single line contains exactly one composite issue. Composite issues in a schedule appear consecutively; there is no blank line between issues in a schedule.

A composite issue is either a single CPU instruction, or two CPU instructions separated by a semicolon.

If your program detects an input error, it should write an informative error message (starting, as always, with bang space "! ") to std-err and exit with no further processing.


This page last modified on 23 April 2004.