Combinatorial.mesa 
Copyright Ó 1987 by Xerox Corporation. All rights reversed.
Created by Bertrand Serlet August 24, 1987 9:59:31 pm PDT
Bertrand Serlet September 10, 1987 11:22:49 am PDT
DIRECTORY Core, CoreFlat, Ports, Rope;
Combinatorial: CEDAR DEFINITIONS = BEGIN
Purpose
The aim of this interface is to define how the notion of combinatorial cells is implemented, to define a syntax for boolean expressions, and to define generic operations for manipulating combinatorial cells.
The property $Combinatorial, which value is a REF BOOL, expresses whether the cell is combinatorial or not. Any CellType can carry this property, not just record cells. Each output has an $Output property which value is a ROPE expressing the value of the expression.
The syntax for expressions is (infix):
expr  == var | ~expr | (expr) | expr + expr | expr * expr | oper(expr1, ..., exprn) | int
oper  == IO.tokenID
var  == anything that can originate from CoreOps.GetFullWireName
The order of precedence is ~, *, +.
The only admissible variables are the full names of input, structured or not. In particular an output cannot use other outputs. Outputs are restricted to atomic wires.
Certain restrictions apply on certain operators. For example +, ~, * only deal with sub-expressions or atomic inputs (no structured inputs nor integers). The root expression cannot be an int.
Atomic wires not Gnd not Vdd and not output are inputs. There is no tri-state wire in a combinatorial cell.
Predicates
IsCombinatorial: PROC [cell: Core.CellType] RETURNS [BOOL];
Returns TRUE if cell is marked combinatorial.
IsNonCombinatorial: PROC [cell: Core.CellType] RETURNS [BOOL];
Returns TRUE if cell is marked non-combinatorial.
NotCombinatorial: ERROR [cell: Core.CellType];
Exception raised by several functions of this interface.
Typing of wires
WireType: TYPE = {input, output, gnd, vdd};
EnumerateTypedWires: PROC [cc: Core.CellType, each: PROC [Core.Wire, ROPE, WireType] RETURNS [quit: BOOLFALSE]] RETURNS [quit: BOOL];
Enumerate each atomic wire with its full name and its type.
In case of DAGs, wires may be enumerated twice.
Raises NotCombinatorial if cc is not combinatorial.
GetTypedWires: PROC [cc: Core.CellType, type: WireType] RETURNS [Core.Wires];
Returns all atomic wires of this type.
No duplication in the returned list.
Raises NotCombinatorial if cc is not combinatorial.
GetWireType: PROC [cc: Core.CellType, wire: Core.Wire] RETURNS [type: WireType];
Not a very efficient function.
Raises NotCombinatorial if cc is not combinatorial.
Parse Trees and Creation Conveniences
ROPE: TYPE = Rope.ROPE;
ParseTree: TYPE = REF; -- Union of ROPE (for variables), REF ParseOperRec and REF INT
ParseTrees: TYPE = LIST OF ParseTree;
ParseOperRec: TYPE = RECORD [oper: ROPE, params: ParseTrees];
Oper: PROC [oper: ROPE, params: ParseTrees] RETURNS [ParseTree];
Not: PROC [tree: ParseTree] RETURNS [ParseTree];
And: PROC [trees: ParseTrees] RETURNS [ParseTree];
Or: PROC [trees: ParseTrees] RETURNS [ParseTree];
And2: PROC [tree1, tree2: ParseTree] RETURNS [ParseTree];
Or2: PROC [tree1, tree2: ParseTree] RETURNS [ParseTree];
Parsing/Unparsing of Expressions
IncorrectExpression: ERROR [expr, msg: ROPE];
ParseExpression: PROC [expr: ROPE] RETURNS [tree: ParseTree];
Might raise IncorrectExpression.
UnParseExpression: PROC [tree: ParseTree] RETURNS [expr: ROPE];
RenameVariables: PROC [tree: ParseTree, var: PROC [ROPE] RETURNS [ROPE]] RETURNS [ParseTree];
ParseOutput: PROC [wire: Core.Wire] RETURNS [tree: ParseTree];
Convenience only.
Might raise IncorrectExpression.
Defining new Operators
RecastProc: TYPE = PROC [params: LIST OF REF] RETURNS [tree: ParseTree];
RegisterOperator: PROC [oper: ROPE, recast: RecastProc];
FetchOperator: PROC [oper: ROPE] RETURNS [recast: RecastProc];
Recast: PROC [ParseTree] RETURNS [ParseTree];
Convenience function that assumes the tree is a REF ParseOperRec, searches the corresponding RecastProc and applies it.
Simulation of Combinatorial cells
A standard Rosemary EvalProc is defined for simulating combinatorial cells. It is registered under the name "Combinatorial", and should be stored on cell types, e.g. by using BindCombinatorial.
BindCombinatorial: PROC [cc: Core.CellType];
Initializes ports and does a Rosemary.BindCellType.
CheckTransistorsAgainstExpressions: PROC [cc: Core.CellType, checkXValues: BOOLTRUE];
Compares transistor level simulation against expression level for all possible values of the inputs, including X if checkXValues.
Might raise CheckUnsuccessful.
CheckUnsuccessful: SIGNAL [level1, level2: Ports.Level];
Statically Making Combinatorial Cells
InputOutputProblem: SIGNAL [type: ATOM, root: Core.CellType, flatWire: CoreFlat.FlatWire ← NIL];
Type is one of the following: $OutputLoop, $OutputOfTwoCombinatorialCells, $NonPublicInput
MakeCombinatorial: PROC [cell: Core.CellType];
Assumes that cell is combinatorial or only made of combinatorial sub cells and recursively makes all those cells combinatorial.
This is symbolic simulation!
Might raise InputOutputProblem. It is OK to proceed, but an ERROR NotCombinatorial will be raised before making the cell combinatorial.
AttemptMakeCombinatorial: PROC [cell: Core.CellType] RETURNS [trans, ok, notOK: INT ← 0];
Same as previous but catches NotCombinatorial.
Splitting Cells into Combinatorial and Non
SplitCombinatorial: PUBLIC PROC [cell: Core.CellType, flatten: PROC [ct: Core.CellType] RETURNS [BOOL]] RETURNS [record: Core.CellType];
Splits a cellType into combinatorial logic and other cell.
Instance 0 contains all the combinatorial logic. This instance is made combinatorial, and might raise the corresponding exceptions.
flatten returns FALSE if argument should not be further flattened.
ct and record conform.
END.