DIRECTORY Combinatorial, Convert, Core, CoreClasses, CoreFlat, CoreOps, CoreProperties, GList, IO, List, Ports, Process, RefTab, Rope, Rosemary, SymTab, TerminalIO; CombinatorialImpl: CEDAR PROGRAM IMPORTS Convert, CoreClasses, CoreFlat, CoreOps, CoreProperties, GList, IO, List, Ports, Process, RefTab, Rope, Rosemary, SymTab, TerminalIO EXPORTS Combinatorial ~ BEGIN OPEN Combinatorial; IsCombinatorial: PUBLIC PROC [cell: Core.CellType] RETURNS [BOOL] = { value: REF BOOL = NARROW [CoreProperties.GetCellTypeProp[cell, $Combinatorial]]; RETURN [value#NIL AND value^]; }; IsNonCombinatorial: PUBLIC PROC [cell: Core.CellType] RETURNS [BOOL] = { value: REF BOOL = NARROW [CoreProperties.GetCellTypeProp[cell, $Combinatorial]]; RETURN [value#NIL AND NOT value^]; }; NotCombinatorial: PUBLIC ERROR [cell: Core.CellType] = CODE; EnumerateTypedWires: PUBLIC PROC [cc: Core.CellType, each: PROC [Core.Wire, ROPE, WireType] RETURNS [quit: BOOL _ FALSE]] RETURNS [quit: BOOL] = { EachWire: CoreOps.EachWireProc = { name: ROPE = CoreOps.GetFullWireName[cc.public, wire]; SELECT TRUE FROM wire.size#0 => RETURN; Rope.Equal[name, "Gnd"] => quit _ each[wire, name, gnd]; Rope.Equal[name, "Vdd"] => quit _ each[wire, name, vdd]; GetOutput[wire]#NIL => quit _ each[wire, name, output]; ENDCASE => quit _ each[wire, name, input]; }; IF NOT IsCombinatorial[cc] THEN ERROR NotCombinatorial[cc]; quit _ CoreOps.VisitWireSeq[cc.public, EachWire]; }; GetTypedWires: PUBLIC PROC [cc: Core.CellType, type: WireType] RETURNS [wires: Core.Wires _ NIL] = { Each: PROC [wire: Core.Wire, name: ROPE, tt: WireType] RETURNS [quit: BOOL _ FALSE] = { IF tt=type AND NOT CoreOps.Member[wires, wire] THEN wires _ CONS [wire, wires]; }; [] _ EnumerateTypedWires[cc, Each]; }; GetWireType: PUBLIC PROC [cc: Core.CellType, wire: Core.Wire] RETURNS [type: WireType] = { Each: PROC [ww: Core.Wire, name: ROPE, tt: WireType] RETURNS [quit: BOOL _ FALSE] = { type _ tt; quit _ ww=wire; }; [] _ EnumerateTypedWires[cc, Each]; }; PutOutput: PUBLIC PROC [wire: Core.Wire, expr: ROPE] = { CoreProperties.PutWireProp[wire, $Output, expr]; }; GetOutput: PUBLIC PROC [wire: Core.Wire] RETURNS [ROPE _ NIL] = { RETURN [CoreOps.FixStupidRef[CoreProperties.GetWireProp[wire, $Output]]]; }; Oper: PUBLIC PROC [oper: ROPE, params: ParseTrees] RETURNS [ParseTree] = {RETURN [NEW [ParseOperRec _ [oper, params]]]}; Not: PUBLIC PROC [tree: ParseTree] RETURNS [ParseTree] = {RETURN [Oper["~", LIST [tree]]]}; And: PUBLIC PROC [trees: ParseTrees] RETURNS [ParseTree] = {RETURN [Oper["*", trees]]}; Or: PUBLIC PROC [trees: ParseTrees] RETURNS [ParseTree] = {RETURN [Oper["+", trees]]}; And2: PUBLIC PROC [tree1, tree2: ParseTree] RETURNS [ParseTree] = {RETURN [And[LIST [tree1, tree2]]]}; Or2: PUBLIC PROC [tree1, tree2: ParseTree] RETURNS [ParseTree] = {RETURN [Or[LIST [tree1, tree2]]]}; IncorrectExpression: PUBLIC ERROR [expr, msg: ROPE] = CODE; ParseExpression: PUBLIC PROC [expr: ROPE] RETURNS [tree: ParseTree _ NIL] = { stream: IO.STREAM _ IO.RIS[expr]; tokenKind: IO.TokenKind; token: ROPE; Scan: PROC = { ENABLE IO.EndOfStream => {tokenKind _ tokenEOF; CONTINUE}; [tokenKind, token] _ IO.GetCedarTokenRope[stream]; }; IsChar: PROC [char: CHAR] RETURNS [ok: BOOL] = { ok _ tokenKind=tokenSINGLE AND Rope.Length[token]=1 AND Rope.Fetch[token]=char; }; ParseTerm: PROC RETURNS [tree: ParseTree] = { SELECT TRUE FROM tokenKind=tokenDECIMAL OR tokenKind=tokenOCTAL OR tokenKind=tokenHEX => tree _ NEW [INT _ Convert.IntFromRope[token]]; IsChar['(] => { Scan[]; tree _ ParseExpr[]; IF NOT IsChar[')] THEN ERROR IncorrectExpression[expr, "Missing )"]; }; IsChar['~] => { Scan[]; RETURN [Not[ParseTerm[]]]; }; IsChar['[] OR tokenKind=tokenID => { variable: ROPE _ NIL; params: ParseTrees _ NIL; WHILE tokenKind=tokenID OR NOT (tokenKind=tokenEOF OR IsChar[',] OR IsChar['+] OR IsChar['*] OR IsChar['(] OR IsChar[')]) DO variable _ Rope.Cat[variable, token]; Scan[]; ENDLOOP; IF NOT IsChar['(] THEN RETURN [variable]; Scan[]; UNTIL tokenKind=tokenEOF OR IsChar[')] DO params _ CONS [ParseExpr[], params]; IF IsChar[')] THEN EXIT; IF NOT IsChar[',] THEN ERROR IncorrectExpression[expr, ", or ) expected"]; Scan[]; ENDLOOP; tree _ Oper[variable, List.Reverse[params]]; }; ENDCASE => ERROR IncorrectExpression[expr, Rope.Cat["Incorrect token :", token]]; Scan[]; }; ParseAnds: PROC RETURNS [tree: ParseTree] = { ands: ParseTrees _ LIST [ParseTerm[]]; WHILE IsChar['*] DO Scan[]; ands _ CONS[ParseTerm[], ands] ENDLOOP; tree _ IF ands.rest=NIL THEN ands.first ELSE And[List.Reverse[ands]]; }; ParseExpr: PROC RETURNS [tree: ParseTree] = { ors: ParseTrees _ LIST [ParseAnds[]]; WHILE IsChar['+] DO Scan[]; ors _ CONS[ParseAnds[], ors] ENDLOOP; tree _ IF ors.rest=NIL THEN ors.first ELSE Or[List.Reverse[ors]]; }; Scan[]; tree _ ParseExpr[]; IF ISTYPE [tree, REF INT] THEN ERROR IncorrectExpression[expr, "Cannot be just an integer"]; IF tokenKind#tokenEOF THEN ERROR IncorrectExpression[expr, "Too much left"]; }; UnParseExpression: PUBLIC PROC [tree: ParseTree] RETURNS [expr: ROPE _ NIL] = { WITH tree SELECT FROM var: Rope.ROPE => expr _ var; refInt: REF INT => expr _ IO.PutR1[IO.int[refInt^]]; rptr: REF ParseOperRec => IF Rope.Equal[rptr.oper, "~"] THEN expr _ Rope.Cat["~", UnParseExpression[rptr.params.first]] ELSE { char: BOOL = Rope.Equal[rptr.oper, "*"] OR Rope.Equal[rptr.oper, "+"]; FOR params: ParseTrees _ rptr.params, params.rest WHILE params#NIL DO expr _ IF expr=NIL THEN IF char THEN "(" ELSE Rope.Cat[rptr.oper, "("] ELSE IF char THEN Rope.Cat[expr, rptr.oper] ELSE Rope.Cat[expr, ", "]; expr _ Rope.Cat[expr, UnParseExpression[params.first]]; ENDLOOP; expr _ Rope.Cat[expr, ")"]; }; ENDCASE => ERROR; }; RenameVariables: PUBLIC PROC [tree: ParseTree, var: PROC [ROPE] RETURNS [ROPE]] RETURNS [ParseTree] = { WITH tree SELECT FROM rope: ROPE => RETURN [var[rope]]; refInt: REF INT => RETURN [refInt]; rptr: REF ParseOperRec => { news: ParseTrees _ NIL; FOR params: ParseTrees _ rptr.params, params.rest WHILE params#NIL DO news _ CONS [RenameVariables[params.first, var], news]; ENDLOOP; RETURN [Oper[rptr.oper, List.Reverse[news]]]; }; ENDCASE => ERROR; }; ParseOutput: PUBLIC PROC [wire: Core.Wire] RETURNS [tree: ParseTree] = { RETURN [ParseExpression[GetOutput[wire]]]; }; opers: SymTab.Ref _ SymTab.Create[]; RegisterOperator: PUBLIC PROC [oper: ROPE, recast: RecastProc] = { [] _ SymTab.Store[opers, oper, NEW [RecastProc _ recast]]; }; FetchOperator: PUBLIC PROC [oper: ROPE] RETURNS [recast: RecastProc] = { refProc: REF RecastProc _ NARROW [SymTab.Fetch[opers, oper].val]; recast _ IF refProc=NIL THEN NIL ELSE refProc^; }; Recast: PUBLIC PROC [tree: ParseTree] RETURNS [ParseTree] = { rptr: REF ParseOperRec = NARROW [tree]; RETURN [FetchOperator[rptr.oper][rptr.params]]; }; FindPort: PROC [rootWire: Core.WireSeq, rootPort: Ports.Port, searched: Core.Wire] RETURNS [found: Ports.Port _ NIL] = { SearchWire: Ports.EachWirePortPairProc = { found _ port; quit _ wire=searched; }; IF NOT Ports.VisitBinding[rootWire, rootPort, SearchWire] THEN found _ NIL; }; FindPorts: PROC [rootWire: Core.WireSeq, rootPort: Ports.Port, searched: Core.Wires] RETURNS [ports: LIST OF Ports.Port _ NIL] = { FOR wires: Core.Wires _ searched, wires.rest WHILE wires#NIL DO port: Ports.Port = FindPort[rootWire, rootPort, wires.first]; IF port=NIL THEN ERROR; ports _ CONS [port, ports]; ENDLOOP; ports _ NARROW [GList.Reverse[ports]]; }; RosemaryState: TYPE = REF RosemaryStateRec; RosemaryStateRec: TYPE = RECORD [ SEQUENCE size: NAT OF RECORD [port: Ports.Port, roseValue: RoseValue] ]; RoseValue: TYPE = REF; -- union of Ports.Port and NAndNode NAndNode: TYPE = REF NAndNodeRec; NAndNodeRec: TYPE = RECORD [nodes: SEQUENCE size: NAT OF RoseValue]; RoseMakeNot: PROC [roseValue: RoseValue] RETURNS [RoseValue] = { notRoseValue: NAndNode; WITH roseValue SELECT FROM nand: NAndNode => IF nand.size=1 THEN RETURN [nand[0]]; ENDCASE => {}; notRoseValue _ NEW [NAndNodeRec[1]]; notRoseValue[0] _ roseValue; RETURN [notRoseValue]; }; RoseMakeMaybeNot: PROC [roseValue: RoseValue, negate: BOOL _ FALSE] RETURNS [RoseValue] = { RETURN [IF negate THEN RoseMakeNot[roseValue] ELSE roseValue]; }; RoseMakeNand: PROC [roseValues: LIST OF RoseValue, negate: BOOL _ FALSE] RETURNS [RoseValue] = { count: NAT _ List.Length[roseValues]; roseValue: NAndNode _ NEW [NAndNodeRec[count]]; IF count=1 THEN RETURN [RoseMakeMaybeNot[roseValues.first, NOT negate]]; FOR i: NAT IN [0 .. count) DO roseValue[i] _ RoseMakeMaybeNot[roseValues.first, negate]; roseValues _ roseValues.rest; ENDLOOP; RETURN [roseValue]; }; RosemaryParses: PROC [params: ParseTrees, var: PROC [ROPE] RETURNS [RoseValue]] RETURNS [roseValues: LIST OF RoseValue _ NIL] = { WHILE params#NIL DO roseValues _ CONS [RosemaryParse[params.first, var], roseValues]; params _ params.rest; ENDLOOP; }; RosemaryParse: PROC [tree: ParseTree, var: PROC [ROPE] RETURNS [RoseValue]] RETURNS [roseValue: RoseValue] = { roseValue _ WITH tree SELECT FROM rope: ROPE => var[rope], rptr: REF ParseOperRec => SELECT TRUE FROM Rope.Equal[rptr.oper, "~"] => RoseMakeNot[RosemaryParse[rptr.params.first, var]], Rope.Equal[rptr.oper, "*"] => RoseMakeNot[RoseMakeNand[RosemaryParses[rptr.params, var]]], Rope.Equal[rptr.oper, "+"] => RoseMakeNand[RosemaryParses[rptr.params, var], TRUE], ENDCASE => RosemaryParse[Recast[tree], var], ENDCASE => ERROR; }; RoseEval: PROC [roseValue: RoseValue] RETURNS [level: Ports.Level _ L] = { WITH roseValue SELECT FROM port: Ports.Port => level _ port.l; nand: NAndNode => FOR i: NAT IN [0 .. nand.size) DO SELECT RoseEval[nand[i]] FROM L => RETURN [H]; H => {}; ENDCASE => level _ X; ENDLOOP; ENDCASE => ERROR; }; CombinatorialInit: Rosemary.InitProc = { RoseVar: PROC [var: ROPE] RETURNS [roseValue: RoseValue] = { roseValue _ FindPort[cellType.public, p, CoreOps.FindWire[cellType.public, var]]; IF roseValue=NIL THEN ERROR; }; outputs: Core.Wires _ GetTypedWires[cellType, output]; count: NAT _ GList.Length[outputs]; state: RosemaryState _ NEW [RosemaryStateRec[count]]; FOR i: NAT IN [0 .. count) DO state[i].port _ FindPort[cellType.public, p, outputs.first]; state[i].roseValue _ RosemaryParse[ParseOutput[outputs.first], RoseVar]; outputs _ outputs.rest; ENDLOOP; stateAny _ state; }; CombinatorialEval: Rosemary.EvalProc = { state: RosemaryState = NARROW [stateAny]; FOR i: NAT IN [0 .. state.size) DO state[i].port.l _ RoseEval[state[i].roseValue] ENDLOOP; }; CheckUnsuccessful: PUBLIC SIGNAL [level1, level2: Ports.Level] = CODE; BindCombinatorial: PUBLIC PROC [cc: Core.CellType] = { BlastPortData: CoreOps.EachWireProc = {CoreProperties.PutWireProp[wire, $PortData, NIL]}; Each: PROC [wire: Core.Wire, name: ROPE, type: WireType] RETURNS [quit: BOOL _ FALSE] = { SELECT type FROM input => { [] _ Ports.InitPort[wire: wire, levelType: l, initDrive: none]; Ports.InitTesterDrive[wire: wire, initDrive: force]; }; output => { [] _ Ports.InitPort[wire: wire, levelType: l, initDrive: drive]; Ports.InitTesterDrive[wire: wire, initDrive: expect]; }; gnd => { [] _ Ports.InitPort[wire: wire, levelType: l, initDrive: none]; [] _ Rosemary.SetFixedWire[wire, L]; }; vdd => { [] _ Ports.InitPort[wire: wire, levelType: l, initDrive: none]; [] _ Rosemary.SetFixedWire[wire, H]; }; ENDCASE => ERROR; }; [] _ CoreOps.VisitWireSeq[cc.public, BlastPortData]; [] _ EnumerateTypedWires[cc, Each]; [] _ Rosemary.BindCellType[cellType: cc, roseClassName: "Combinatorial"]; [] _ CoreFlat.CellTypeCutLabels[cc, "LogicMacro", "Logic"]; }; CheckTransistorsAgainstExpressions: PUBLIC PROC [cc: Core.CellType, checkXValues: BOOL _ TRUE] = { TryAll: PROC [inputsToFix: Core.Wires] = { Process.Yield[]; IF inputsToFix=NIL THEN { Rosemary.Settle[simulation1]; Rosemary.Settle[simulation2]; FOR outs: Core.Wires _ outputs, outs.rest WHILE outs#NIL DO p1: Ports.Port = FindPort[cc.public, port1, outs.first]; p2: Ports.Port = FindPort[cc.public, port2, outs.first]; IF p1.l#p2.l THEN SIGNAL CheckUnsuccessful[p1.l, p2.l]; ENDLOOP; } ELSE FOR level: Ports.Level IN Ports.Level DO p1: Ports.Port = FindPort[cc.public, port1, inputsToFix.first]; p2: Ports.Port = FindPort[cc.public, port2, inputsToFix.first]; IF level=X AND NOT checkXValues THEN LOOP; p1.l _ level; p2.l _ level; TryAll[inputsToFix.rest]; ENDLOOP; }; inputs: Core.Wires = GetTypedWires[cc, input]; outputs: Core.Wires = GetTypedWires[cc, output]; port1: Ports.Port = Ports.CreatePort[cc, TRUE]; port2: Ports.Port = Ports.CreatePort[cc, TRUE]; simulation1: Rosemary.Simulation _ Rosemary.Instantiate[cc, port1]; simulation2: Rosemary.Simulation _ Rosemary.Instantiate[cc, port2, CoreFlat.CreateCutSet[flatCells: LIST [NEW [CoreFlat.FlatCellTypeRec _ CoreFlat.rootCellType]]]]; Rosemary.Initialize[simulation1]; Rosemary.Initialize[simulation2]; TryAll[inputs]; }; InputOutputWarning: PROC [type: ATOM, root: Core.CellType, flatWire: CoreFlat.FlatWire] = { TerminalIO.PutF["*** %g in cell %g with %g.\n", IO.atom[type], IO.rope[CoreOps.GetCellTypeName[root]], IO.rope[CoreFlat.WirePathRope[root, flatWire^]]]; SIGNAL InputOutputProblem[type, root, flatWire]; }; InputOutputProblem: PUBLIC SIGNAL [type: ATOM, root: Core.CellType, flatWire: CoreFlat.FlatWire] = CODE; TranslateOutputs: PROC [root, actual, public: Core.WireSeq, eachOutput: PROC [act: Core.Wire, tree: ParseTree]] = { table: RefTab.Ref _ CoreOps.CreateBindingTable[public, actual]; RenameVar: PROC [old: ROPE] RETURNS [new: ROPE] = { pub: Core.Wire _ CoreOps.FindWire[public, old]; act: Core.Wire = NARROW [RefTab.Fetch[table, pub].val]; RETURN [CoreOps.GetFullWireName[root, act]]; }; EachWirePair: CoreOps.EachWirePairProc = { IF GetOutput[publicWire]=NIL THEN RETURN; eachOutput[actualWire, RenameVariables[ParseOutput[publicWire], RenameVar]]; }; [] _ CoreOps.VisitBindingSeq[actual, public, EachWirePair]; }; MakeCombinatorial: PUBLIC PROC [cell: Core.CellType] = { signalled: Core.Wires _ NIL; Process.Yield[]; IF IsCombinatorial[cell] THEN RETURN; IF IsNonCombinatorial[cell] THEN ERROR NotCombinatorial[cell]; SELECT cell.class FROM CoreClasses.transistorCellClass => ERROR NotCombinatorial[cell]; CoreClasses.unspecifiedCellClass => ERROR NotCombinatorial[cell]; CoreClasses.recordCellClass => { table: RefTab.Ref _ RefTab.Create[]; -- maps internal wires to their ParseTree, expressed with variables as part of the internal rct: CoreClasses.RecordCellType = NARROW [cell.data]; count: INT _ 0; ReplaceVars: PROC [tree: ParseTree, forbidden: Core.Wires] RETURNS [ParseTree] = { WITH tree SELECT FROM rope: ROPE => { wire: Core.Wire _ CoreOps.FindWire[rct.internal, rope]; aux: ParseTree = RefTab.Fetch[table, wire].val; IF wire=NIL THEN ERROR; IF aux=NIL THEN { inputName: ROPE = CoreOps.GetFullWireName[cell.public, wire]; IF inputName=NIL THEN { IF NOT CoreOps.Member[signalled, wire] THEN { InputOutputWarning[$NonPublicInput, cell, NEW [CoreFlat.FlatWireRec _ [wire: wire]]]; signalled _ CONS [wire, signalled]; }; }; RETURN [inputName]; }; IF CoreOps.Member[forbidden, wire] THEN { IF NOT CoreOps.Member[signalled, wire] THEN { InputOutputWarning[$OutputLoop, cell, NEW [CoreFlat.FlatWireRec _ [wire: wire]]]; -- Loop! signalled _ CONS [wire, signalled]; }; RETURN [rope]; }; RETURN [ReplaceVars[aux, CONS [wire, forbidden]]]; }; refInt: REF INT => RETURN [refInt]; rptr: REF ParseOperRec => { news: ParseTrees _ NIL; FOR params: ParseTrees _ rptr.params, params.rest WHILE params#NIL DO news _ CONS [ReplaceVars[params.first, forbidden], news]; ENDLOOP; RETURN [Oper[rptr.oper, List.Reverse[news]]]; }; ENDCASE => ERROR; }; EachOutput: PROC [act: Core.Wire, tree: ParseTree] = { prev: ParseTree = RefTab.Fetch[table, act].val; IF prev#NIL THEN { IF NOT CoreOps.Member[signalled, act] THEN { InputOutputWarning[$OutputOfTwoCombinatorialCells, cell, NEW [CoreFlat.FlatWireRec _ [wire: act]]]; signalled _ CONS [act, signalled]; }; }; [] _ RefTab.Store[table, act, tree]; }; SetOutput: CoreOps.EachWireProc = { tree: ParseTree = RefTab.Fetch[table, wire].val; IF tree=NIL THEN RETURN; -- Not an output, proceed! PutOutput[wire, UnParseExpression[ReplaceVars[tree, LIST [wire]]]]; count _ count + 1; }; FOR i: NAT IN [0 .. rct.size) DO MakeCombinatorial[rct[i].type]; TranslateOutputs[rct.internal, rct[i].actual, rct[i].type.public, EachOutput]; ENDLOOP; IF signalled#NIL THEN ERROR NotCombinatorial[cell]; [] _ CoreOps.VisitWireSeq[cell.public, SetOutput]; IF count=0 THEN TerminalIO.PutF["*** Cell %g made combinatorial, but has no output.\n", IO.rope[CoreOps.GetCellTypeName[cell]]]; CoreProperties.PutCellTypeProp[cell, $Combinatorial, NEW [BOOL _ TRUE]]; BindCombinatorial[cell]; TerminalIO.PutF["Cell %g made combinatorial. %g outputs.\n", IO.rope[CoreOps.GetCellTypeName[cell]], IO.int[count]]; }; ENDCASE => { count: INT _ 0; EachOutput: PROC [act: Core.Wire, tree: ParseTree] = { PutOutput[act, UnParseExpression[tree]]; count _ count + 1; }; recasted: Core.CellType _ CoreOps.Recast[cell]; MakeCombinatorial[recasted]; TranslateOutputs[cell.public, cell.public, recasted.public, EachOutput]; IF count=0 THEN TerminalIO.PutF["*** Cell %g made combinatorial, but has no output.\n", IO.rope[CoreOps.GetCellTypeName[cell]]]; CoreProperties.PutCellTypeProp[cell, $Combinatorial, NEW [BOOL _ TRUE]]; BindCombinatorial[cell]; TerminalIO.PutF["Cell %g made combinatorial. %g outputs.\n", IO.rope[CoreOps.GetCellTypeName[cell]], IO.int[count]]; }; }; AttemptMakeCombinatorial: PUBLIC PROC [cell: Core.CellType] RETURNS [trans, ok, notOK: INT _ 0] = { Each: CoreFlat.UnboundFlatCellProc = { IF IsCombinatorial[cell] OR IsNonCombinatorial[cell] THEN RETURN; SELECT cell.class FROM CoreClasses.transistorCellClass => trans _ trans + 1; ENDCASE => { CoreFlat.NextUnboundCellType[cell: cell, target: target, flatCell: flatCell, instance: instance, index: index, parent: parent, flatParent: flatParent, data: data, proc: Each ! ANY => GOTO GRRR]; MakeCombinatorial[cell ! NotCombinatorial, InputOutputProblem => GOTO GRRR]; ok _ ok + 1; EXITS GRRR => {notOK _ notOK + 1; CoreProperties.PutCellTypeProp[cell, $Combinatorial, NEW [BOOL _ FALSE]]}; }; }; Each[cell]; }; SearchRefTab: PROC [x: RefTab.Ref, val: RefTab.Val] RETURNS [found: BOOL, key: RefTab.Key _ NIL] = { fval: RefTab.Val _ val; fkey: RefTab.Key _ NIL; EachPair: RefTab.EachPairAction = {fkey _ key; quit _ val=fval}; found _ RefTab.Pairs[x, EachPair]; key _ fkey; }; InternalIsCombinatorial: PROC [cell: Core.CellType] RETURNS [BOOL] = { MakeCombinatorial[cell ! NotCombinatorial, InputOutputProblem => GOTO GRRR]; RETURN [TRUE]; EXITS GRRR => {CoreProperties.PutCellTypeProp[cell, $Combinatorial, NEW [BOOL _ FALSE]]; RETURN [FALSE]}; }; ConsIfNotMember: PROC [wire: Core.Wire, wires: Core.Wires] RETURNS [Core.Wires] = { FOR list: Core.Wires _ wires, list.rest WHILE list#NIL DO IF list.first=wire OR CoreOps.RecursiveMember[list.first, wire] THEN RETURN [wires]; ENDLOOP; RETURN [CONS [wire, wires]]; }; WireUse: TYPE = {PublicUse, CombUse, NonCombUse}; WireUses: TYPE = ARRAY WireUse OF BOOL _ ALL [FALSE]; AddIntType: PROC [intType: RefTab.Ref, int: Core.Wire, type: WireUse] = { wireUses: REF WireUses _ NARROW [RefTab.Fetch[intType, int].val]; IF wireUses=NIL THEN wireUses _ NEW [WireUses]; wireUses[type] _ TRUE; [] _ RefTab.Store[intType, int, wireUses]; FOR i: NAT IN [0 .. int.size) DO AddIntType[intType, int[i], type] ENDLOOP; }; MakeNewSeq: PROC [old: Core.WireSeq, oldToNew: RefTab.Ref] RETURNS [new: Core.WireSeq] = { new _ CoreOps.CreateWires[size: old.size]; FOR j: NAT IN [0 .. new.size) DO new[j] _ CoreOps.CopyWireUsingTable[old[j], oldToNew]; ENDLOOP; }; SplitCombinatorial: PUBLIC PROC [record: Core.CellType] RETURNS [split: Core.CellType _ NIL] = { rct: CoreClasses.RecordCellType = NARROW [record.data]; intTable: RefTab.Ref = RefTab.Create[]; -- maps internals of record to internals of split public: Core.WireSeq = MakeNewSeq[record.public, intTable]; intType: RefTab.Ref = RefTab.Create[]; -- maps internals of split to WireUses combs: LIST OF CoreClasses.CellInstance _ NIL; -- new combinatorial instances nonCombs: LIST OF CoreClasses.CellInstance _ NIL; -- new non-combinatorial instances combInt, combPub, combAct: Core.Wires _ NIL; combCT: Core.CellType; combInstance: CoreClasses.CellInstance; combNewInt: RefTab.Ref = RefTab.Create[]; -- maps internals of split to internals of combCT internals: Core.Wires _ NIL; CreateNew: PROC [int: Core.Wire] RETURNS [new: Core.Wire] = { new _ NARROW [RefTab.Fetch[combNewInt, int].val]; IF new#NIL THEN RETURN; new _ CoreOps.CreateWires[int.size]; [] _ RefTab.Store[combNewInt, int, new]; FOR i: NAT IN [0 .. int.size) DO new[i] _ CreateNew[int[i]] ENDLOOP; }; EachIntTypeCreateNew: RefTab.EachPairAction = { wireUses: REF WireUses = NARROW [val]; IF wireUses[CombUse] THEN [] _ CreateNew[NARROW [key]]; }; EachIntType: RefTab.EachPairAction = { int: Core.Wire = NARROW [key]; wireUses: REF WireUses = NARROW [val]; IF wireUses[CombUse] THEN { new: Core.Wire _ NARROW [RefTab.Fetch[combNewInt, int].val]; combInt _ ConsIfNotMember[new, combInt]; IF NOT wireUses[NonCombUse] AND NOT wireUses[PublicUse] THEN RETURN; internals _ ConsIfNotMember[int, internals]; combInt _ ConsIfNotMember[new, combInt]; IF NOT CoreOps.Member[combPub, new] THEN { combAct _ CONS [int, combAct]; combPub _ CONS [new, combPub]; }; } ELSE internals _ ConsIfNotMember[int, internals]; }; FOR i: NAT IN [0 .. rct.size) DO ct: Core.CellType = rct[i].type; actual: Core.WireSeq = MakeNewSeq[rct[i].actual, intTable]; instance: CoreClasses.CellInstance = CoreClasses.CreateInstance[actual, ct]; IF InternalIsCombinatorial[ct] THEN combs _ CONS [instance, combs] ELSE nonCombs _ CONS [instance, nonCombs]; ENDLOOP; FOR i: NAT IN [0 .. public.size) DO AddIntType[intType, public[i], PublicUse] ENDLOOP; FOR list: LIST OF CoreClasses.CellInstance _ combs, list.rest WHILE list#NIL DO FOR i: NAT IN [0 .. list.first.actual.size) DO AddIntType[intType, list.first.actual[i], CombUse] ENDLOOP; ENDLOOP; FOR list: LIST OF CoreClasses.CellInstance _ nonCombs, list.rest WHILE list#NIL DO FOR i: NAT IN [0 .. list.first.actual.size) DO AddIntType[intType, list.first.actual[i], NonCombUse] ENDLOOP; ENDLOOP; [] _ RefTab.Pairs[intType, EachIntTypeCreateNew]; [] _ RefTab.Pairs[intType, EachIntType]; FOR list: LIST OF CoreClasses.CellInstance _ combs, list.rest WHILE list#NIL DO actual: Core.WireSeq _ CoreOps.CreateWires[list.first.actual.size]; FOR i: NAT IN [0 .. actual.size) DO actual[i] _ NARROW [RefTab.Fetch[combNewInt, list.first.actual[i]].val]; IF actual[i]=NIL THEN ERROR; ENDLOOP; list.first.actual _ actual; ENDLOOP; combCT _ CoreClasses.CreateRecordCell[ public: CoreOps.CreateWire[combPub], internal: CoreOps.CreateWire[combInt], instances: combs, giveNames: TRUE ]; MakeCombinatorial[combCT ! InputOutputProblem => { wire: Core.Wire _ flatWire.wire; newInt: Core.Wire _ NARROW [SearchRefTab[combNewInt, wire].key]; oldInt: Core.Wire _ NARROW [SearchRefTab[intTable, newInt].key]; IF root#combCT OR oldInt=NIL THEN ERROR; InputOutputWarning[type, record, NEW [CoreFlat.FlatWireRec _ [wire: oldInt]]]; RESUME; }]; combInstance _ CoreClasses.CreateInstance[actual: CoreOps.CreateWire[combAct], type: combCT]; split _ CoreClasses.CreateRecordCell[ public: public, internal: CoreOps.CreateWire[internals], instances: CONS [combInstance, nonCombs], giveNames: TRUE ]; TerminalIO.PutF[ "Splitting done for %g: combinatorial cell with %g outputs and %g non combinatorial cells.\n", IO.rope[CoreOps.GetCellTypeName[record]], IO.int[GList.Length[GetTypedWires[combCT, output]]], IO.int[GList.Length[nonCombs]] ]; }; Xor2Recast: RecastProc = { p1: REF = params.first; p2: REF = params.rest.first; tree _ Or2[And2[p1, Not[p2]], And2[p2, Not[p1]]]; }; [] _ Rosemary.Register["Combinatorial", CombinatorialInit, CombinatorialEval]; RegisterOperator["xor2", Xor2Recast]; END. τCombinatorialImpl.mesa Copyright Σ 1987 by Xerox Corporation. All rights reversed. Created by Bertrand Serlet August 24, 1987 9:59:31 pm PDT Bertrand Serlet September 17, 1987 3:39:32 pm PDT Predicates Typing of wires Creation Conveniences Parsing of Expressions assumes that tokenKind and token are already set. Leaves them set at the end. We have a function here! Defining new Operators Simulation of Combinatorial cells Why isn't this one in Rosemary??? note initialization to L important for the case when we have a nand! Hack to get rid of properties added by Logic! We create two simulations We initialize both For each input, we loop Statically Making Combinatorial Cells it must be an input! Splitting Combinatorial Cells Initialization ΚU˜– "Cedar" stylešœ™Jšœ<™K˜K˜—šž œœœœœœœ˜`Jšœœ˜%Kšœœ˜/Kšœ œœ%œ ˜Hšœœœœ˜Kšœ;˜;Kšœ˜Kšœ˜—Kšœ ˜K˜K˜—šžœœœœœœœœ œ˜šœœœ˜Jšœ œ0˜AJšœ˜Jšœ˜—J˜J˜—š ž œœœœœœ˜nšœ œœ˜!Jšœœ˜šœœœœ˜*šœ˜Jšœ3˜3—šœ˜Jšœ<˜<—šœ˜Jšœ/œ˜5—šœ ˜Jšœ!˜!——Jšœœ˜—J˜J˜—šžœœœ˜JKšœD™Dšœ œ˜Kšœ#˜#šœœœœ˜3šœ˜Kšœœ˜Kšœ˜Kšœ˜Kšœ˜——Kšœœ˜—K˜K˜—šžœ˜(šžœœœœ˜šœ ˜Kšœ#œ˜@Kšœ$œ˜A˜ Kšœ%Ÿ[˜€Kšœ"œ ˜5Kšœœ˜šž œœ*œ˜Ršœœ˜šœœ˜Jšœ7˜7Jšœ/˜/Jšœœœœ˜šœœœ˜Jšœ™Jšœ œ.˜=šœ œœ˜šœœ!œ˜-Jšœ*œ)˜VJšœ œ˜#Jšœ˜—J˜—Jšœ˜J˜—šœ!œ˜)šœœ!œ˜-Jšœ&œ)Ÿ˜ZJšœ œ˜#Jšœ˜—Jšœ˜J˜—Jšœœ˜2Jšœ˜—Jšœœœœ ˜%šœœ˜Jšœœ˜šœ/œœ˜EKšœœ.˜9Jšœ˜—Jšœ'˜-J˜—Jšœœ˜—K˜—šž œœ&˜6Jšœ/˜/šœœœ˜šœœ œ˜,Jšœ9œ'˜cJšœ œ˜"Jšœ˜—J˜—Jšœ$˜$K˜—šž œ˜#Jšœ0˜0Jš œœœœŸ˜3Kšœ4œ ˜CK˜K˜—šœœœ˜ Kšœ˜KšœN˜NKšœ˜—Kšœ œœœ˜3Kšœ2˜2Kšœ œIœ&˜€Kšœ5œœœ˜HJšœ˜Jšœ>œ&œ ˜uK˜—šœ˜Kšœœ˜šž œœ&˜6Kšœ(˜(K˜K˜—Kšœ0˜0Kšœ˜KšœH˜HKšœ œIœ&˜€Kšœ5œœœ˜HJšœ˜Jšœ>œ&œ ˜uK˜——K˜K˜—š žœœœœœ ˜cšžœ"˜&Kšœœœœ˜Ašœ ˜Kšœ5˜5šœ˜J–[cell: Core.CellType, target: CoreFlat.FlatCellTypeRec, flatCell: CoreFlat.FlatCellTypeRec, instance: CoreClasses.CellInstance, index: NAT, parent: Core.CellType, flatParent: CoreFlat.FlatCellTypeRec, data: REF ANY, proc: CoreFlat.UnboundFlatCellProc]šœ°œœœ˜ΒJšœAœœ˜LKšœ ˜ Kš œœMœœœ˜lK˜——K˜—Kšœ ˜ K˜——™š ž œœ"œ œœ˜dKšœ˜Kšœœ˜Kšžœ8˜@Kšœ"˜"Kšœ ˜ K˜K˜—šžœœœœ˜FKšœAœœ˜LKšœœ˜Kšœœ:œœœœœ˜iK˜K˜—šžœœ&œ˜Sšœ%œœ˜9K–+[wire: Core.Wire, candidate: Core.Wire]šœœ+œœ ˜TKšœ˜—Kšœœ˜K˜K˜—Kšœ œ$˜1š œ œœ œœœœ˜5K˜—šž œœ9˜IJšœ œ œ"˜AJšœ œœ œ ˜/Jšœœ˜Jšœ*˜*Jš œœœœ#œ˜KJ˜J˜—šž œœ+œ˜ZKšœ*˜*šœœœœ˜!Kšœ6˜6Kšœ˜—K˜K˜—š žœœœœœ˜`Kšœ"œ˜7Jšœ(Ÿ1˜YKšœ;˜;Jšœ'Ÿ&˜MJšœœœœŸ˜MJšœ œœœŸ"˜TKšœ(œ˜,Kšœ˜Kšœ'˜'Kšœ*Ÿ1˜[Kšœœ˜šž œœœ˜=Kšœœ%˜1Kšœœœœ˜Kšœ$˜$Kšœ(˜(Kš œœœœœ˜DK˜—šžœ˜/Jšœ œ œ˜&Jšœœœ˜7J˜—šž œ˜&Jšœœ˜Jšœ œ œ˜&šœ˜šœ˜Kšœœ%˜