DIRECTORY CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Ports, Real, Rosemary, Sinix; LogicSimpleImpl: CEDAR PROGRAM IMPORTS CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, LogicUtils, Ports, Real, Rosemary, Sinix EXPORTS Logic = BEGIN OPEN LogicUtils, CoreCreate; IXRef: TYPE = REF IXRec; IXRec: TYPE = RECORD [in, out: NAT _ LAST[NAT]]; IXInit: Rosemary.InitProc = { state: IXRef _ IF oldStateAny=NIL THEN NEW[IXRec] ELSE NARROW[oldStateAny]; [state.in, state.out] _ Ports.PortIndexes[cellType.public, "I", "X"]; stateAny _ state; }; InvRoseClass: ROPE = RoseClass["Inv", IXInit, InvSimple]; Inv: PUBLIC PROC [buffered: BOOL _ FALSE] RETURNS [ct: CellType] = { name: ROPE = IF buffered THEN "InvB" ELSE "Inv"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC[IF buffered THEN "invBuffer" ELSE "inv"]; CacheStore[name, ct]; }; InvSimple: Rosemary.EvalProc = { state: IXRef _ NARROW[stateAny]; p[state.out].l _ SELECT p[state.in].l FROM L => H, H => L, ENDCASE => X; }; Buffer: PUBLIC PROC[d: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["Buffer d=%g", IO.int[d]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF d=0 THEN Error["Please specify size of buffer"]; ct _ SequenceCell[name: "Buffer", baseCell: Inv[TRUE], count: MAX[(d+1)/2, 1]]; SimulateGate[ct, InvRoseClass]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[fullName, ct]; }; CKBuffer: PUBLIC PROC[d, numRows: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["CKBuffer d=%g numRows=%g ", IO.int[d], IO.int[numRows]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF d=0 THEN Error["Please specify sizes for clock buffer"]; IF numRows=0 THEN Error["Please specify number of rows for clock buffer"]; ct _ DistributedSequence[MAX[(d+1)/2, 1], numRows]; SimulateGate[ct, InvRoseClass]; -- a simple non-inverting gate Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[fullName, ct]; }; DistributedSequence: PROC [n, numRows: NAT] RETURNS [ct: CellType] ~ { data: CoreClasses.RecordCellType; delta: NAT = MAX[numRows/n, 1]; -- if n>numRows then 1 else big steps ct _ SequenceCell[name: "CKBuffer", baseCell: Inv[TRUE], count: n]; ct _ CoreOps.Recast[ct]; IF ct.class#CoreClasses.recordCellClass THEN ERROR; data _ NARROW[ct.data]; FOR i: NAT IN [0..data.size) DO row: NAT _ ((i*delta) MOD numRows)+1; -- always in [1..numRows] CoreProperties.PutCellInstanceProp[data.instances[i], $Row, NEW[INT _ row]]; ENDLOOP; }; Rec2VRoseClass: ROPE = RoseClass["Rec2V", Rec2VInit, Rec2VSimple]; Rec2V: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "Rec2V"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["rec2V"]; SimulateGate[ct, Rec2VRoseClass]; Ports.InitPorts[ct, l, none, "I", "Vth"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[name, ct]; }; RecRef: TYPE = REF RecRec; RecRec: TYPE = RECORD [in, out, v: NAT _ LAST[NAT]]; Rec2VInit: Rosemary.InitProc = { state: RecRef _ IF oldStateAny=NIL THEN NEW[RecRec] ELSE NARROW[oldStateAny]; [state.in, state.out, state.v] _ Ports.PortIndexes[cellType.public, "I", "X", "Vth"]; stateAny _ state}; Rec2VSimple: Rosemary.EvalProc = { state: RecRef _ NARROW[stateAny]; p[state.out].l _ SELECT p[state.v].l FROM H => Ports.NotL[p[state.in].l], L => L, ENDCASE => X; p[state.in].d _ driveWeak; -- weak pullup is part of the input structure p[state.in].l _ H; }; RecTTLRoseClass: ROPE = RoseClass["RecTTL", IXInit, InvSimple]; RecTTL: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "RecTTL"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["recTTL"]; SimulateGate[ct, RecTTLRoseClass]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[name, ct]; }; DriverRoseClass: ROPE = RoseClass["Driver", IXInit, DriverSimple]; Driver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ { fullName: ROPE = IO.PutFR["Driver d=%g", IO.int[d]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; SELECT d FROM <=0 => Error["Please specify strength of driver"]; <=4 => ct _ SCBlock[Extract["driver4.sch"]]; <=8 => ct _ SCBlock[Extract["driver8.sch"]]; ENDCASE => { -- use constant amplification in 2 stages, correct up to 64 n2: NAT = (d+3)/4; -- second stage: 1 inverter may drive 4, round up n1: NAT = Real.Round[Real.SqRt[n2]]; -- first stage, sqrt of second stage ct _ Extract["driver.sch", LIST[["n1", n1], ["n2", n2]]]; }; SimulateMacro[ct, DriverRoseClass]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[fullName, ct]; }; DriverSimple: Rosemary.EvalProc = { state: IXRef _ NARROW[stateAny]; p[state.out].l _ p[state.in].l; }; InvDriver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ { fullName: ROPE = IO.PutFR["InvDriver d=%g", IO.int[d]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; SELECT d FROM <=0 => Error["Please specify strength of inverting driver"]; <=4 => ct _ SCBlock[Extract["invDriver4.sch"]]; <=8 => ct _ SCBlock[Extract["invDriver8.sch"]]; ENDCASE => ct _ Extract["invDriver.sch", LIST[["drv", d]]]; -- use direct driver SimulateMacro[ct, InvRoseClass]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X"]; CacheStore[fullName, ct]; }; SymDriverRoseClass: ROPE = RoseClass["SymDriver", SymDriverInit, SymDriverSimple]; SymDriver: PUBLIC PROC [d: NAT] RETURNS [ct: CellType] ~ { fullName: ROPE = IO.PutFR["SymDriver d=%g", IO.int[d]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; SELECT d FROM <=0 => Error["Please specify strength of symmetrical driver"]; <=3 => ct _ SCBlock[Extract["symDriver3.sch"]]; <=6 => ct _ SCBlock[Extract["symDriver6.sch"]]; ENDCASE => { -- use constant amplification in 3 stages, correct up to 64 n2: NAT = (d+3)/4; -- last inverting stage: 1 inverter may drive 4, round up d1: NAT = d+n2; -- logic drive of initial non-inverting driver ct _ Extract["symDriver.sch", LIST[["n2", n2], ["d1", d1]]]; }; SimulateMacro[ct, SymDriverRoseClass]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, drive, "X", "nX"]; CacheStore[fullName, ct]; }; SymDriverRef: TYPE = REF SymDriverRec; SymDriverRec: TYPE = RECORD [in, out, nout: NAT _ LAST[NAT]]; SymDriverInit: Rosemary.InitProc = { state: SymDriverRef _ IF oldStateAny=NIL THEN NEW[SymDriverRec] ELSE NARROW[oldStateAny]; [state.in, state.out, state.nout] _ Ports.PortIndexes[cellType.public, "I", "X", "nX"]; stateAny _ state; }; SymDriverSimple: Rosemary.EvalProc = { state: SymDriverRef _ NARROW[stateAny]; p[state.out].l _ p[state.in].l; p[state.nout].l _ SELECT p[state.in].l FROM L => H, H => L, ENDCASE => X; }; TstDriverRoseClass: ROPE = RoseClass["TstDriver", TstInit, TstDriverSimple]; TstDriver: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "TstDriver"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["tstDriver"]; SimulateGate[ct, TstDriverRoseClass]; Ports.InitPorts[ct, l, none, "I", "EN", "NEN", "X"]; CacheStore[name, ct]; }; TristateI: PUBLIC PROC RETURNS [ct: CellType] ~ { fullName: ROPE = "TristateI"; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; ct _ SCBlock[Extract["3BufferI.icon"]]; CacheStore[fullName, ct]; }; TristateNI: PUBLIC PROC RETURNS [ct: CellType] ~ { fullName: ROPE = "TristateNI"; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; ct _ SCBlock[Extract["3BufferNI.icon"]]; CacheStore[fullName, ct]; }; TstRef: TYPE = REF TstRec; TstRec: TYPE = RECORD [in, out, en, nEn: NAT _ LAST[NAT]]; TstInit: Rosemary.InitProc = { state: TstRef _ IF oldStateAny=NIL THEN NEW[TstRec] ELSE NARROW[oldStateAny]; [state.in, state.out, state.en, state.nEn] _ Ports.PortIndexes[cellType.public, "I", "X", "EN", "NEN"]; stateAny _ state; }; TstDriverSimple: Rosemary.EvalProc = { -- by Pradeep state: TstRef _ NARROW[stateAny]; SELECT TRUE FROM p[state.en].l#L AND p[state.in].l#L => { -- N-Section of TstDriver p[state.out].d _ drive; p[state.out].l _ IF p[state.en].l=H AND p[state.in].l=H THEN L ELSE X; }; p[state.nEn].l#H AND p[state.in].l#H => { -- P-Section of TstDriver p[state.out].d _ drive; p[state.out].l _ IF p[state.nEn].l=L AND p[state.in].l=L THEN H ELSE X; }; ENDCASE => p[state.out].d _ none; }; B4: TYPE = {and, nand, or, nor}; nameInLib: ARRAY B4 OF ROPE = [and: "and", nand: "nand", or: "or", nor: "nor"]; nameOfCT: ARRAY B4 OF ROPE = [and: "And", nand: "Nand", or: "Or", nor: "Nor"]; rootCT: ARRAY B4 OF B4 = [and: nor, nand: nand, or: nand, nor: nor]; leafCT: ARRAY B4 OF B4 = [and: nand, nand: and, or: nor, nor: or]; B4Small: PROC [b4: B4, n: NAT] RETURNS [ct: CellType] ~ { fullName: ROPE = IO.PutFR["%g n=%g", IO.rope[nameOfCT[b4]], IO.int[n]]; sc: CellType; pas: LIST OF PA; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; sc _ MakeSC[IO.PutFR["%g%g", IO.rope[nameInLib[b4]], IO.int[n]]]; pas _ LIST[["I-A", "I[0]"], ["I-B", "I[1]"]]; IF n>2 THEN pas _ CONS[["I-C", "I[2]"], pas]; IF n>3 THEN pas _ CONS[["I-D", "I[3]"], pas]; ct _ Cell[name: IO.PutFR["%g%g", IO.rope[nameOfCT[b4]], IO.int[n]], public: Wires["Vdd", "Gnd", Seq["I", n], "X"], instances: LIST[InstanceList[sc, pas]]]; CacheStore[fullName, ct]; }; B4Large: PROC [b4: B4, n: NAT] RETURNS [ct: CellType] ~ { fullName: ROPE; input: Wire; n1: NAT = n/2; SELECT n FROM 0 => Error[IO.PutFR["Please specify the number of inputs of the `%g' gate", IO.rope[nameInLib[b4]]]]; 1 => RETURN [Extract[IF b4=and OR b4=or THEN "wrappedInvPair.sch" ELSE "wrappedInv.sch"]]; <=4 => RETURN [B4Small[b4, n]]; ENDCASE => NULL; -- general case, see below fullName _ IO.PutFR["%g n=%g", IO.rope[nameOfCT[b4]], IO.int[n]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; input _ Seq["I", n]; ct _ Cell[name: IO.PutFR["%g%g", IO.rope[nameOfCT[b4]], IO.int[n]], instances: LIST[ Instance[B4Small[rootCT[b4], 2], ["I", Wires["One", "Two"]]], Instance[B4Large[leafCT[b4], n1], ["X", "One"], ["I", Range[input, 0, n1]]], Instance[B4Large[leafCT[b4], n-n1], ["X", "Two"], ["I", Range[input, n1, n-n1]]] ], public: Wires["Vdd", "Gnd", input, "X"], onlyInternal: Wires["One", "Two"]]; CacheStore[fullName, ct]; }; And: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct _ B4Large[and, n]}; Nand: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct _ B4Large[nand, n]}; Or: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct _ B4Large[or, n]}; Nor: PUBLIC PROC[n: NAT] RETURNS [ct: CellType] = {ct _ B4Large[nor, n]}; Xor2: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "Xor2"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["xor2"]; CacheStore[name, ct]; }; Xnor2: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "Xnor2"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["xnor2"]; CacheStore[name, ct]; }; A22o2i: PUBLIC PROC[] RETURNS [ct: CellType] = { name: ROPE = "A22o2i"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["a22o2i"]; CacheStore[name, ct]; }; O22a2i: PUBLIC PROC[] RETURNS [ct: CellType] = { name: ROPE = "O22a2i"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["o22a2i"]; CacheStore[name, ct]; }; A21o2i: PUBLIC PROC[] RETURNS [ct: CellType] = { name: ROPE = "A21o2i"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["a21o2i"]; CacheStore[name, ct]; }; O21a2i: PUBLIC PROC[] RETURNS [ct: CellType] = { name: ROPE = "O21a2i"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["o21a2i"]; CacheStore[name, ct]; }; FlipFlopRoseClass: ROPE = RoseClass["FlipFlop", FFInit, FFSimple, TRUE]; FlipFlop: PUBLIC PROC [metaStableResistant: BOOL _ FALSE] RETURNS [ct: CellType] = { name: ROPE = IF metaStableResistant THEN "FlipFlopMR" ELSE "FlipFlop"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ IF metaStableResistant THEN SCBlock[Extract["ffMR.sch"]] ELSE MakeSC["ff"]; SimulateGate[ct, FlipFlopRoseClass]; Ports.InitPorts[ct, l, none, "D", "CK"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"]; CacheStore[name, ct]; }; FFRef: TYPE = REF FFRec; FFRec: TYPE = RECORD [ ffD, ffQ, ffNQ, ffClock: NAT _ LAST[NAT], master, slave: Ports.Level]; FFInit: Rosemary.InitProc = { state: FFRef _ IF oldStateAny=NIL THEN NEW[FFRec] ELSE NARROW[oldStateAny]; state.master _ state.slave _ X; [state.ffD, state.ffQ, state.ffNQ, state.ffClock] _ Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK"]; p[state.ffQ].l _ p[state.ffNQ].l _ X; stateAny _ state; }; FFSimple: Rosemary.EvalProc = { state: FFRef _ NARROW[stateAny]; IF ~clockEval THEN SELECT p[state.ffClock].l FROM L => state.master _ p[state.ffD].l; -- load master bit H => state.slave _ state.master; -- load slave bit ENDCASE => state.slave _ state.master _ X; -- random clock p[state.ffQ].l _ state.slave; p[state.ffNQ].l _ Ports.NotL[state.slave]; }; FlipFlopEnableRoseClass: ROPE = RoseClass["FlipFlopEnable", FFenInit, FFenSimple, TRUE]; FlipFlopEnable: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "FlipFlopEnable"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["ffEn"]; SimulateGate[ct, FlipFlopEnableRoseClass]; Ports.InitPorts[ct, l, none, "D", "CK", "en", "nEn"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"]; CacheStore[name, ct]; }; FFenRef: TYPE = REF FFenRec; FFenRec: TYPE = RECORD [ ffD, ffQ, ffNQ, ffClock, ffen, ffnEn: NAT _ LAST[NAT], master, slave: Ports.Level]; FFenInit: Rosemary.InitProc = { state: FFenRef _ IF oldStateAny=NIL THEN NEW[FFenRec] ELSE NARROW[oldStateAny]; state.master _ state.slave _ X; [state.ffD, state.ffQ, state.ffNQ, state.ffClock, state.ffen, state.ffnEn, ] _ Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK", "en", "nEn"]; p[state.ffQ].l _ p[state.ffNQ].l _ X; stateAny _ state; }; FFenSimple: Rosemary.EvalProc = { state: FFenRef _ NARROW[stateAny]; IF ~clockEval THEN SELECT p[state.ffClock].l FROM L => state.master _ Ports.OrL[ -- load master bit Ports.AndL[p[state.ffD].l, p[state.ffen].l], Ports.AndL[state.slave, p[state.ffnEn].l] ]; H => state.slave _ state.master; -- load slave bit ENDCASE => state.slave _ state.master _ X; -- random clock p[state.ffQ].l _ state.slave; p[state.ffNQ].l _ Ports.NotL[state.slave]; }; FlipFlopAsyncResetRoseClass: ROPE = RoseClass["FlipFlopAsyncReset", FFARInit, FFARSimple, TRUE]; FlipFlopAsyncReset: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "FlipFlopAsyncReset"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ SCBlock[Extract["ffAR.sch"]]; SimulateGate[ct, FlipFlopAsyncResetRoseClass]; Ports.InitPorts[ct, l, none, "D", "CK", "r"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"]; CacheStore[name, ct]; }; FFARRef: TYPE = REF FFARRec; FFARRec: TYPE = RECORD [ ffD, ffQ, ffNQ, ffClock, ffR: NAT _ LAST[NAT], master, slave: Ports.Level]; FFARInit: Rosemary.InitProc = { state: FFARRef _ IF oldStateAny=NIL THEN NEW[FFARRec] ELSE NARROW[oldStateAny]; state.master _ state.slave _ X; [state.ffD, state.ffQ, state.ffNQ, state.ffClock, state.ffR] _ Ports.PortIndexes[cellType.public, "D", "Q", "NQ", "CK", "r"]; p[state.ffQ].l _ p[state.ffNQ].l _ X; stateAny _ state; }; FFARSimple: Rosemary.EvalProc = { state: FFARRef _ NARROW[stateAny]; SELECT p[state.ffR].l FROM L => IF ~clockEval THEN SELECT p[state.ffClock].l FROM -- normal mode of operation L => state.master _ p[state.ffD].l; -- load master bit H => state.slave _ state.master; -- load slave bit ENDCASE => state.slave _ state.master _ X; -- random clock H => state.slave _ state.master _ L; -- asynchronous reset ENDCASE => state.slave _ state.master _ X; -- mushy reset p[state.ffQ].l _ state.slave; p[state.ffNQ].l _ Ports.NotL[state.slave]; }; RSRoseClass: ROPE = RoseClass["RSFlipFlop", RSInit, RSSimple]; RS: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "RSFlipFlop"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ CoreClasses.CreateUnspecified[name: name, public: Wires["Vdd", "Gnd", "R", "S", "Q", "nQ"]]; SimulateGate[ct, RSRoseClass]; Ports.InitPorts[ct, l, none, "R", "S"]; Ports.InitPorts[ct, l, drive, "Q", "NQ"]; CacheStore[name, ct]; }; RSRef: TYPE = REF RSRec; RSRec: TYPE = RECORD [ r, s, q, nq: NAT _ LAST[NAT], bit: Ports.Level]; -- a copy of Q RSInit: Rosemary.InitProc = { state: RSRef _ IF oldStateAny=NIL THEN NEW[RSRec] ELSE NARROW[oldStateAny]; state.bit _ X; [state.r, state.s, state.q, state.nq] _ Ports.PortIndexes[cellType.public, "R", "S", "Q", "nQ"]; p[state.q].l _ p[state.nq].l _ X; stateAny _ state; }; RSSimple: Rosemary.EvalProc = { state: RSRef _ NARROW[stateAny]; SELECT TRUE FROM p[state.r].l=H => { state.bit _ p[state.q].l _ L; p[state.nq].l _ Ports.NotL[p[state.s].l]; }; p[state.r].l=L AND p[state.s].l=H => { state.bit _ p[state.q].l _ H; p[state.nq].l _ L; }; p[state.r].l=L AND p[state.s].l=L => { p[state.q].l _ state.bit; p[state.nq].l _ Ports.NotL[state.bit]; }; ENDCASE => state.bit _ p[state.q].l _ p[state.nq].l _ X; }; StorageRoseClass: ROPE = RoseClass["Storage", StorageInit, StorageSimple]; Storage: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "Storage"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ CoreClasses.CreateUnspecified[name: name, public: Wires["Vdd", "Gnd", "bit", "nbit"]]; SimulateGate[ct, StorageRoseClass]; Ports.InitPorts[ct, l, none, "bit", "nbit"]; [] _ Rosemary.SetWire[wire: FindWire[ct.public, "bit"], memory: TRUE]; [] _ Rosemary.SetWire[wire: FindWire[ct.public, "nbit"], memory: TRUE]; CacheStore[name, ct]; }; StorageRef: TYPE = REF StorageRec; StorageRec: TYPE = RECORD [bit, nBit: NAT _ LAST[NAT]]; StorageInit: Rosemary.InitProc = { state: StorageRef _ IF oldStateAny=NIL THEN NEW[StorageRec] ELSE NARROW[oldStateAny]; [state.bit, state.nBit] _ Ports.PortIndexes[cellType.public, "bit", "nbit"]; p[state.bit].l _ X; p[state.bit].d _ driveWeak; p[state.nBit].l _ X; p[state.nBit].d _ driveWeak; stateAny _ state; }; StorageSimple: Rosemary.EvalProc = {NULL}; -- cf. Pradeep DLatchRoseClass: ROPE = RoseClass["DLatch", DLInit, DLSimple]; DLatch: PUBLIC PROC RETURNS [ct: CellType] = { name: ROPE = "DLatch"; ct _ CacheFetch[name]; IF ct#NIL THEN RETURN[ct]; ct _ MakeSC["dLatch"]; SimulateGate[ct, DLatchRoseClass]; Ports.InitPorts[ct, l, none, "D", "S"]; Ports.InitPorts[ct, l, drive, "Q"]; CacheStore[name, ct]; }; DLRef: TYPE = REF DLRec; DLRec: TYPE = RECORD [ dlD, dlQ, dlS: NAT _ LAST[NAT], mem: Ports.Level]; DLInit: Rosemary.InitProc = { state: DLRef _ IF oldStateAny=NIL THEN NEW[DLRec] ELSE NARROW[oldStateAny]; state.mem _ X; [state.dlD, state.dlQ, state.dlS] _ Ports.PortIndexes[cellType.public, "D", "Q", "S"]; p[state.dlQ].l _ X; stateAny _ state; }; DLSimple: Rosemary.EvalProc = { state: DLRef _ NARROW[stateAny]; IF p[state.dlS].l=H THEN state.mem _ p[state.dlD].l ELSE IF p[state.dlS].l=X THEN IF p[state.dlD].l#state.mem THEN state.mem _ X; p[state.dlQ].l _ state.mem; }; Tr2: PUBLIC PROC [type: ATOM] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["Tr2 type=$%g", IO.atom[type]]; name: ROPE; dr: Ports.Drive _ drive; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; SELECT type FROM $pd => name _ "pd"; $pdw => {name _ "pdw"; dr _ driveWeak}; $pu => name _ "pu"; $puw => {name _ "puw"; dr _ driveWeak}; ENDCASE => ERROR; ct _ MakeSC[name]; -- no eval proc for this guy IF type = $pdw OR type = $puw THEN CoreProperties.PutCellTypeProp[ct, $MintDiscardMe, $TRUE]; Ports.InitPorts[ct, l, none, "I"]; Ports.InitPorts[ct, l, dr, "X"]; CacheStore[fullName, ct]; }; MintHackExtractProc: Sinix.ExtractProc ~ { [result, props] _ Sinix.Extract[obj, mode, NIL, userData]; props _ CoreProperties.PutProp[props, $MintDiscardMe, $TRUE]; }; PullUpRoseClass: ROPE = RoseClass["PullUp", PUInit, PUSimple]; PullUp: PUBLIC PROC [n: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["PullUp n=%g", IO.int[n]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; ct _ CoreClasses.CreateUnspecified[name: "PullUp", public: Wires[IF n=0 THEN "out" ELSE Seq["out", n]]]; SimulateGate[ct, PullUpRoseClass]; Ports.InitPorts[ct, IF n=0 THEN l ELSE ls, driveWeak, "out"]; CacheStore[fullName, ct]; }; PUInit: Rosemary.InitProc = { state: IXRef _ IF oldStateAny=NIL THEN NEW[IXRec] ELSE NARROW[oldStateAny]; state.out _ Ports.PortIndex[cellType.public, "out"]; IF p[state.out].levelType=l THEN p[state.out].l _ H ELSE Ports.SetLS[p[state.out].ls, H]; stateAny _ state; }; PUSimple: Rosemary.EvalProc = { state: IXRef _ NARROW[stateAny]; IF p[state.out].levelType=l THEN p[state.out].l _ H ELSE Ports.SetLS[p[state.out].ls, H]; }; Sinix.RegisterExtractProc[$MintHackExtractProc, MintHackExtractProc]; END. ²LogicSimpleImpl.mesa Copyright Σ 1986, 1987 by Xerox Corporation. All rights reserved. Last Edited by: Louis Monier October 28, 1987 12:03:45 pm PST Last Edited by: McCreight July 13, 1987 2:54:16 pm PDT Jean-Marc Frailong November 13, 1987 6:53:34 pm PST Bertrand Serlet March 30, 1987 10:36:12 pm PST Christian LeCocq October 17, 1986 6:05:34 pm PDT Barth, October 10, 1986 5:38:40 pm PDT Alfred Permuy September 11, 1986 10:19:56 pm PDT Pradeep Sindhu September 11, 1986 11:38:39 pm PDT This package contains all basic cells present in the library (nand2, flip-flop, ...) and very simple macros: n-inputs and gates, buffer of arbitrary size, ... Common types of publics -- All these types and procedures are common to a lot of the cells in this implementation Inverters and receivers Inverters -- The vanilla inverter (optionally with double power output) with explicit layout Raw inverting buffer -- A sequence of double-power inverters. A buffer of drive d is equivalent to d inverters connected in parallel. This is old stuff that should now be obsolete and be replaced by the inverting driver Clock buffer: forces the buffers to be distributed among the rows -- Distributes the n instances evenly among the rows 2 Volt receiver -- A Rec2V is a 2-volt receiver with adjustable threshold for DynaBus interface. TTL receiver -- An inverter with a low input threshold. Drivers All drivers are able to drive d inverter inputs reasonably fast without exceeding 2 loads on their inputs. The current structure of drivers is a compromise. Strict correction would require the following implementation using constant amplification ratios to load d inverters on output: - direct driver, using 2 stages of buffers ideal: stage1: d**0.333333, stage2: d**0.666666 current: stage1: stage2**0.5, stage2: d/4 (rounded up) - inverting driver, using 3 stages: ideal: stage1: d**0.25, stage2: d**0.5, stage3: d**0.75 current: stage1: 1, stage2: stage3**0.5, stage3: d/4 (rounded up) Although those approximations are not ideal, they do save some space. A little further analysis is in order. Non-inverting driver Inverting driver Symmetrical driver Tristate Driver And, Nand, Or, Nor Common part Compute the celltype for those that have explicit layout Compute all 4 generic functions -- and -> nor2(nand) -- nand -> nand2(and) -- or -> nand2(nor) -- nor -> nor2(or) Here comes the general case Interface calls Complex gates Xor2 Xnor2 A22o2i and O22a2i A21o2i and O21a2i Flip-Flops & other storage elements Edge-Triggered Flip-Flop (one input, one clock, complementary outputs) -- of course state.master is the inverse of the physical master level in the current CMosB implementation, but nobody has access to the real value, so let's keep things simple... Edge-Triggered Flip-Flop (with data enable) -- of course state.master is the inverse of the physical master level in the current CMosB implementation, but nobody has access to the real value, so let's keep things simple... Edge-Triggered Flip-Flop (with asynchronous reset) RS Flip-Flop (not a SC) Storage (not a SC) Latch (1 input) Pull-ups and pull-down Real pull up/down, normal size and weak -- Extracts the transistor normally, but makes it invisible to Mint Logical pull-up, no layout ΚA– "cedar" style˜codešœ™KšœB™BK™=K™6K™3K™.K™0K™&K™0K™1K™K™—šœŸ™ŸK™K™—KšΟk œ1œ2˜pK˜•StartOfExpansion[]šΠblœœ˜Kšœ1œ*˜fKšœ˜ Kšœœœ˜$—head™KšΟcY™YKšœœœ˜š œœœ œœœ˜0K˜—šΟnœ˜Kš œœ œœœœœ˜KKšœE˜EKšœ˜Kšœ˜——™™ KšŸR™RKš  œœ'˜9š  œœœ œœœ˜DKš œœœ œœ˜0K˜Kšœœœœ˜Kšœ œ œ œ˜5K˜Kšœ˜—š  œ˜ Kšœœ ˜ Kšœœœœ˜HKšœ˜——šœ™KšŸΖ™Ζš  œœœœœ˜6Kšœ œœœ ˜4K˜Kšœœœœ˜Kšœœ(˜3Kšœ0œ œ˜OKšœ˜KšœF˜FKšœ˜Kšœ˜——šœA™Aš  œœœ œœ˜AKš œ œœ$œ œ˜SK˜Kšœœœœ˜Kšœœ0˜;Kšœ œ9˜JKšœœ˜3Kšœ Ÿ˜>KšœF˜FKšœ˜Kšœ˜—K™4š œœœœ˜FKšœ!˜!KšœœœŸ%˜EKšœ2œ ˜CK˜Kšœ&œ˜3Kšœœ ˜šœœœ˜Kšœœœ Ÿ˜?Kšœ<œœ ˜LKšœ˜—K˜——™KšŸP™PKš œœ.˜Bš œœœœ˜-Kšœœ ˜Kšœ˜Kšœœœœ˜Kšœ˜Kšœ!˜!KšœM˜MKšœ˜Kšœ˜K˜—Kšœœœ˜Kš œœœœœœ˜4š  œ˜ Kš œœ œœœ œœ˜MKšœU˜UKšœ˜—š  œ˜"Kšœœ ˜!šœœ˜)Kšœ˜Kšœ˜Kšœ˜ —KšœŸ-˜HKšœ˜Kšœ˜——™ KšŸ*™*Kš œœ*˜?š œœœœ˜.Kšœœ ˜Kšœ˜Kšœœœœ˜Kšœ˜Kšœ"˜"KšœF˜FKšœ˜Kšœ˜———™™jK™—™±™*K™/K™6—™#K™7K™A——™lK™—šœ™Kš œœ-˜Bš  œœœœœ˜7Kšœ œœœ ˜4K˜Kšœœœœ˜šœ˜ Kšœ2˜2Kšœ,˜,Kšœ,˜,šœŸ;˜HKšœœ Ÿ1˜DKšœœŸ$˜IKšœœ˜9Kšœ˜——Kšœ#˜#KšœF˜FKšœ˜K˜K˜—š  œ˜#Kšœœ ˜ Kšœ˜Kšœ˜——šœ™š   œœœœœ˜:Kšœ œœœ ˜7K˜Kšœœœœ˜šœ˜ Kšœ<˜˜>Kšœ/˜/Kšœ/˜/šœŸ;˜HKšœœ Ÿ9˜LKšœœ Ÿ.˜>Kšœœ˜šœœœœ˜*Kšœœ˜Kšœ˜Kšœœœœ˜šœ/˜/Kšœ2˜2—Kšœ˜KšœQ˜QKšœ˜Kšœ˜K˜—Kšœœœ˜šœœœ˜Kšœ œœœ˜KšœŸ˜!—K˜š œ˜Kš œœ œœœœœ˜KKšœ˜Kšœ`˜`Kšœ!˜!Kšœ˜Kšœ˜K˜—š œ˜Kšœœ ˜ šœœ˜šœ˜Kšœ˜Kšœ)˜)K˜—šœœ˜&Kšœ˜Kšœ˜K˜—šœœ˜&Kšœ˜Kšœ&˜&K˜—Kšœ1˜8—Kšœ˜——šœœ™Kš œœ4˜Jš œœœœ˜/Kšœœ ˜Kšœ˜Kšœœœœ˜šœ/˜/Kšœ,˜,—Kšœ#˜#Kšœ,˜,Kšœ@œ˜FKšœAœ˜GKšœ˜Kšœ˜K˜—Kšœ œœ ˜"Kš œ œœ œœœ˜7š  œ˜"Kš œœ œœœ œœ˜UKšœL˜LKšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜Kšœ˜K˜—Kš  œœŸ˜9—™Kš œœ)˜>š œœœœ˜.Kšœœ ˜Kšœ˜Kšœœœœ˜Kšœ˜Kšœ"˜"KšœK˜KKšœ˜Kšœ˜K˜—Kšœœœ˜šœœœ˜Kšœœœœ˜Kšœ˜—K˜š œ˜Kš œœ œœœœœ˜KKšœ˜KšœV˜VKšœ˜Kšœ˜Kšœ˜K˜—š œ˜Kšœœ ˜ š œœœœœ˜RKšœœ˜/—Kšœ˜Kšœ˜———™šœ'™'š  œœœœœ˜8Kšœ œœœ ˜9Kšœœ˜ Kšœ˜K˜Kšœœœœ˜šœ˜Kšœ˜Kšœ'˜'Kšœ˜Kšœ'˜'Kšœœ˜—KšœŸ˜/Kšœ œ œ;˜]KšœC˜CKšœ˜Kšœ˜K˜—K™Cš œ˜*Kšœ+œ ˜:Kšœ=˜=K˜——™Kš œœ)˜>š  œœœœœ˜7Kšœ œœœ ˜4Kšœ˜Kšœœœœ˜KšœAœœœ˜hKšœ"˜"Kšœœœœ˜=Kšœ˜Kšœ˜—K˜š œ˜Kš œœ œœœœœ˜KKšœ4˜4Kšœœœ!˜YKšœ˜Kšœ˜K˜—š œ˜Kšœœ ˜ Kšœœœ!˜YKšœ˜—K˜KšœE˜E˜K˜———Kšœ˜—…—OXvK