"arch" Library Interface

Logical View Report

C++ Syntax

Includes Attributes And Operations

Includes Documentation

Generated September 27, 1998

12:58:53 PM

D:\chiyuliu\RIT_Courses\ComputerArch\Arch2-2.mdl






Updated December 13, 1999 by Warren R. Carithers

Table of Contents

Table of Contents 2

Logical View Report 3

Logical View 3

Connector 3

Bus 3

CarryConnector 3

OverflowConnector 3

BusALU 3

StorageObject 4

Clearable 5

Clock 5

CPUObject 6

ClockedObject 6

Constant 6

Counter 7

Flow 7

InFlow 7

Memory 7

OutFlow 8

PseudoInput 8

PseudoOutput 9

ShiftRegister 9

Totals: 10

Logical Package Structure 1

CLASS DIAGRAM 11


Logical View Report

Logical View

Connector

A Connector is something that provides the data flow from various sources to an OutFlow. InFlows and OutFlows are always components of Connectors, so only Connectors are declared directly by client programs. Abstract superclass.

Derived from CPUObject



Public Operations:

void Connector (const char* id, int numBits)





Bus

A Bus is the standard Connector, containing one InFlow and one OutFlow. It just passes data straight through.

Derived from Connector



Public Operations:

void Bus (const char* id, int numBits)

long computeValue ()

InFlow& IN ()

OutFlow& OUT ()





CarryConnector

Derived from Connector



OverflowConnector

Derived from Connector



BusALU

ovid perform(op)

where "op" is from {op_none, op_add, op_sub, op_and, op_or, op_xor, op_not, op_extendSign, op_lshift, op_rshift, op_rashift, op_rop1, op_rop2, op_zero, op_one}

op_add: add OP1 & OP2

op_sub: subtract OP2 from OP1

op_and: and OP1 & OP2

op_or: or OP1 & OP2

op_xor: xor OP1 & OP2

op_not: complement OP1

op_extendSign: extend the sign of OP1, assuming OP2 tells us the mask of the sign bit

op_lshift: left shift OP1 by OP2's amount. sign of OP1 will stay constant.

op_rshift: right shift OP1 by OP2's amount. sign of OP1 will stay constant.

op_rop1: just pass OP1 through

op_rop2: just pass OP2 through

op_zero: value is the constant 0

op_one: value is the constant 1


perform(op) MUST be called in every clock cycle that the output will be needed, even if the operation is the same as the previous cycle. Also, it must be done after the inputs for OP1 and OP2 have been set.



InFlow &OP1()

InFlow &OP2()

reference to the two incoming paths associated with the ALU inputs


OutFlow &OUT() referejce to the outgoing path associated with the ALU output


int carry()

int overflow() condition codes from operation of previous clock cycle

Derived from Connector



Public Operations:

void BusALU (const char* id, int numBits)

void perform (Operation op)

perform the specified operation, using OP1 and OP2

(WHICH SHOULD BE ALREADY HAVE BEEN CONNECTED TO SOMETHING VIA THE PULLFROM OPERATION)

InFlow& OP1 ()

used to establish from where operand 1 is being pulled

InFlow& OP2 ()

used to establish from where operand 2 is being pulled

OutFlow& OUT ()

used to establish destination of result

OutFlow& WAS_CARRY ()

Boolean path tells whether there was a carry from the operation in the previous clock cycle

OutFlow & WAS_OVERFLOW ()

Boolean path tells whether there was a signed overflow from the operation in the previous clock cycle





StorageObject

The StorageObject is a base class for all components of the simulated CPU capable of receiving and holding binary data. It contains only some elementary operations so that it can interact with other components like data paths and the system clock.


Classes deriving off StorageObject should probably make this base class virtual to allow combining of multiple subclasses by the user to create new object types. Subclasses should also conform to the following clocking operation:


phase1:

Object computes its new value and calls value(int) to store it. The value that would be returned by value() is not yet changed.


phase2:

base class StorageObject updates real values


One example of the utility of this 2-phase approach is daisy-chained shift registers.

Derived from ClockedObject



Public Operations:

void StorageObject (const char* id, int numBits, long initVal = 0)

void enable (const InFlow* i)

This function gets called by an InFlow to announce the enabling of the data path to it. A valid connection check is done. PseudoInput uses this to do the input.

virtual long const value ()

read current value

unsigned long const uvalue ()

read current value as unsigned number

int const zero ()

short-cut predicate; tests value, does not change it.

void connectsTo (Flow& f)

Establish bus-register connection (before start of simulation).

void latchFrom (OutFlow& o)

Establish that the source of data _this_clock_cycle_ is the given "bus".

long const operator() (int startBit, int stopBit)

Extract "substring".

msb is numBits-1; lsb is 0.

long const operator() (int bit)

long const operator() ()

returns most significant bit

void backDoor (long x)

"undocumented:" function!

Sets reg. value without following normal data flow protocol.

Use only when you give up.





Clearable

Adds clr/set capability to the basic StorageObject

Derived from StorageObject



Public Operations:

void Clearable (const char id, int numBits, long value = 0)

void perform (Operation op)

choose an operation to do on the next clock

enum Operation { none = 0, clearOp, setOp}

void set ()

perform(setOp) [shorthand]

void clear ()

perform(clearOp) [shorthand]





Clock

Do not declare any instances of Clock. All functions are static. It controls the entire simulation, and holds all startup and shutdown code (for example, the version number initial greeting, and the number-of-cycles message at the end).


The clock is "wired" to all ClockedObjects (currently StorageObjects and Memory). It sends them all the phase1() and phase2() messages when Clock::tick() is invoked.

Public Operations:

static void tick ()

The application should invoke this function when everything has been set up for the next clock cycle. Calling tick sends the phase1 and phase2 signals.

static long getTime ()





CPUObject

CPUObject is an abstract base class that defines the behavior that all its subclasses share. Its properties are few: number of bits, and name. Not quite all subclasses use the bit size. The name is defined here so that diagnostic printing can be centrally defined.

Public Attributes:

static int debug





Public Operations:

void CPUObject (const char* id, int numBits)

All CPUObjects have a name for debugging purposes. It is expected that the vast majority of CPUObjects will have a size measurable in bits, so that is collected here as well. Subclasses have a more complicated state, indicated in their constructors.

const char* name ()

unsigned int size ()





ClockedObject

The ClockedObject is a base class for all components of the simulated CPU that are to be connected to the system clock.


Subclasses should conform to the following clocking operation:

phase1:

object pulls in any data from the outside that it may need.

phase2:

object updates its own state


The major subclass of ClockedObjct is StorageObject, a register. There is also Memory.

Derived from CPUObject



Public Operations:

void ClockedObject (const char* id, int numBits)





Constant

A Constant is a Connector that simply provides the same value to its OutFlow every time. It is not connected to any InFlow.

Derived from Connector



Public Operations:

void Constant (const char* id, numBits int, long value)

long computeValue ()

void const printOn (ostream& o)

OutFlow OUT ()



Counter

Adds counting capability to the basic StorageObject

Derived from StorageObject



Public Operations:

void Counter (const char* id, int numBits, long value = 0)

void perform (Operation op)

choose an operation to do on the next clock

enum Operation { decr8 = -8, decr4 = -4, decr1 = -1, none = 0, incr1 = 1, incr2 = 2, incr4 = 4, incr8 = 8}

void incr ()

perform(incr1) [shorthand]

void decr ()

perform(decr1) [shorthand]

int overflow ()

predicate to see if incr or decr caused "rollover"

(FFF..FF <--> 000..00); use after executing clock pulse





Flow

A common superclass for InFlow and OutFlow. This is only useful because it avoids some otherwise redundant code, e.g. in StorageObject. Not a class to be used by client simulations.

Derived from CPUObject



Public Operations:

void Flow (const char* id, int numBits)





InFlow

An InFlow is an object to which a StorageObject connects to send its value to other StorageObjects. Only one such object may be connected during any clock cycle. The StorageObjects will keep track of to which InFlows they are connected.

Derived from Flow



Public Operations:

void pullFrom (StorageObject& so)

Define from where I get my value during the next clock cycle.

virtual long const fetchValue ()

Called by the Connector that contains me during execution of a clock cycle (phase1, computeValue)

virtual void const printSourceInfo ()

For tracing only. DO NOT CALL.





Memory

Memory is a collection of Memory cells, arranged as an array, and individually addressable. It provides access to them through a memory address register, MAR, a WRITE InFlow, and a READ OutFlow. Multi-unit transfer and detection of improper addresses are supported.

Derived from ClockedObject, Connector



Public Operations:

void Memory (char* id, int bitsInAddr, int bitsPerWord, unsigned long maxAddr = -1, int wordsInDataPath = 1)

StorageObject& MAR ()

a reference to the memory unit's address register

InFlow& WRITE ()

a reference to the memory unit's ingoing data path for writing

OutFlow READ ()

a reference to the memory unit's outgoing data path for reading

void perform (Operation op)

to be performed on the next clock

enum Operation {none, loadOp, readOp, writeOp}

void read ()

shorthand for perform(readOp)

void write ()

shorthand for perform(writeOp)

void load (char* fileName, long defaultValue = 0)

Read in the object file named fileName.

Each line in the file is <#words> <word1> ... <wordn>, all in hex. Last line is starting address for program, ready to be latched through the READ OutFlow.

Rest of memory is initialized to the defaultValue.

void dump (unsigned long startAddr, unsigned long endAddr, ostream& o = cout)

diagnostic memory dump for debugging.

int badAddress ()

Reflects just completed read or write; this ought to be called after every such operation, e.g. to cause a trap.





OutFlow

An OutFlow is an objedct to which a StorageObject connects to get a new value on the next clock. The StorageObjects will keep track of to which OutFlows they may be connected. The other side of an OutFlow is a Connector -- where it gets its input. In the simplest case, the Connector is a Bus, which contains both an InFlow and OutFlow.

Derived from Flow



Public Operations:

virtual long fetchValue ()

called internally from a StorageObject during phase1;OutFlows get their values from their Connectors





PseudoInput

A StorageObject that gets its value from stdin every time it is an InFlow for its value.

Derived from StorageObject



Public Operations:

void PseudoInput (const char* id, int numBits)

not legal

void value (long x)

void enable (const InFlow* i)

This is where input is done.





PseudoOutput

A StorageObject that prints, on stdout, every new value it gets from an OutFlow.

Derived from StorageObject



Public Operations:

void PseudoOutput (const char* id, int numBits)





ShiftRegister

To perform a normal left shift: leftShift()


To perform a normal right shift: rightShift()


To perform a right shift that propagates the sign bit for two's complement division by two: rightArithShift()


To specify the right-hand input for a left shift: leftShiftInputIs(obj). If this call is not made when a left shift is requested, a 0 bit will be shifted in.


To specify the left-hand input for a right shift: rightShiftInputs(obj). If this call is not made when a right shift is requested, a 0 bit will be shifted in. This call is illegal in combination with rightArithShift().

Derived from StorageObject



Public Operations:

void ShiftRegister (const char* id, int numBits, long initVal = 0)

return opname ( argname)

void perform (ShiftRegister::Operation operation)

enum Operation {none = 0, right, rightArith, left}

void rightShift ()

void rightArithShift ()

void LeftShift ()

void rightShiftInputIs (StorageObject& obj)

void leftShiftInputIs (StorageObject& obj)







Totals:

2 Logical Packages

19 Classes

Logical Package Structure

Logical View