"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
