<> <> <> <> <> <> <<>> DIRECTORY BitOps, CoreClasses, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Ports, Rosemary, Static; LogicArithImpl: CEDAR PROGRAM IMPORTS BitOps, CoreCreate, CoreOps, CoreProperties, IO, Logic, LogicUtils, Ports, Static EXPORTS Logic = BEGIN OPEN LogicUtils, CoreCreate; <> <> AdderState: TYPE = REF AdderStateRec; AdderStateRec: TYPE = RECORD [inA, inB, sum, carryIn, carryOut: NAT _ LAST[NAT]]; AdderInit: Rosemary.InitProc = { state: AdderState _ IF oldStateAny=NIL THEN NEW[AdderStateRec] ELSE NARROW[oldStateAny]; [state.inA, state.inB, state.sum, state.carryIn, state.carryOut] _ Ports.PortIndexes[cellType.public, "A", "B", "Sum", "carryIn", "carryOut"]; stateAny _ state; }; AdderSimple: Rosemary.EvalProc = { state: AdderState _ NARROW[stateAny]; carry: Ports.Level _ p[state.carryIn].l; FOR i: NAT DECREASING IN [0..p[state.sum].ls.size) DO [carry, p[state.sum].ls[i]] _ Ports.SumL[p[state.inA].ls[i], p[state.inB].ls[i], carry]; ENDLOOP; p[state.carryOut].l _ carry; }; <> AdderRoseClass: ROPE = RoseClass["Adder", AdderInit, AdderSimple]; Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["Adder b=%g", IO.int[b]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; SELECT b FROM 0 => Error["Please specify a number of bits for the adder"]; 1 => { ct _ Extract["oneBitAdder.sch"]; -- designed by Alfred CacheStore[fullName, ct]; }; ENDCASE => { ct _ SequenceCell[baseCell: Adder[1], count: b, sequencePorts: Wires["A", "B", "Sum"], stitchPorts: LIST[["carryOut", "carryIn"]], name: "Adder"]; SimulateMacro[ct, AdderRoseClass]; Ports.InitPorts[ct, l, none, "carryIn"]; Ports.InitPorts[ct, l, drive, "carryOut"]; Ports.InitPorts[ct, ls, none, "A", "B"]; Ports.InitPorts[ct, ls, drive, "Sum"]; CacheStore[fullName, ct]; }; }; <> <32;>> Constant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = { vCard: CARD = LOOPHOLE[v]; gnd: Wire _ Static.UnconnectedOK[CoreOps.CreateWire[name: "Gnd"]]; vdd: Wire _ Static.UnconnectedOK[CoreOps.CreateWire[name: "Vdd"]]; output: Wire _ Static.UnconnectedOK[CoreOps.CreateWires[size: b, name: "Output"]]; SELECT b FROM <=32 => FOR i: NAT IN [0..b) DO output[i] _ IF BitOps.EBFD[vCard, i, b] THEN vdd ELSE gnd; ENDLOOP; >32 => {sign: Wire _ IF v<0 THEN vdd ELSE gnd; FOR i: NAT IN [0..b-32) DO output[i] _ sign; ENDLOOP; FOR i: NAT IN [b-32..b) DO output[i] _ IF BitOps.EBFD[vCard, i-b+32, 32] THEN vdd ELSE gnd; ENDLOOP; }; ENDCASE => ERROR; ct _ Cell[name: "Constant", public: Wires[gnd, vdd, output], instances: NIL]; }; <> <> LSEqual: PROC [ls1, ls2: Ports.LevelSequence] RETURNS [eq: Ports.Level] ~ { IF ls1.size#ls2.size THEN ERROR; eq _ H; FOR i: NAT IN [0..ls1.size) DO eq _ Ports.AndL[eq, LEqual[ls1[i], ls2[i]]]; ENDLOOP; }; LEqual: PROC [l1, l2: Ports.Level] RETURNS [eq: Ports.Level] ~ { eq _ SELECT l1 FROM L => Ports.NotL[l2], H => l2, ENDCASE => X; }; <> ComparatorRoseClass: ROPE = RoseClass["Comparator", ComparatorInit, ComparatorSimple]; Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { fullName: ROPE = IO.PutFR["Comparator b=%g", IO.int[b]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please specify a number of bits for the comparator"]; ct _ Extract["comparator.sch", LIST[["b", b]]]; SimulateMacro[ct, ComparatorRoseClass]; Ports.InitPorts[ct, ls, none, "A", "B"]; Ports.InitPorts[ct, l, drive, "AEqB"]; CacheStore[fullName, ct]; }; ComparatorState: TYPE = REF ComparatorStateRec; ComparatorStateRec: TYPE = RECORD [a, b, eq: NAT _ LAST[NAT]]; ComparatorInit: Rosemary.InitProc = { state: ComparatorState _ IF oldStateAny=NIL THEN NEW[ComparatorStateRec] ELSE NARROW[oldStateAny]; [state.a, state.b, state.eq] _ Ports.PortIndexes[cellType.public, "A", "B", "AEqB"]; stateAny _ state; }; ComparatorSimple: Rosemary.EvalProc = { state: ComparatorState _ NARROW[stateAny]; p[state.eq].l _ LSEqual[p[state.a].ls, p[state.b].ls]; }; <> EqConstantRoseClass: ROPE = RoseClass["EqConstant", EqConstantInit, EqConstantSimple]; EqConstant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = { <> eqConstantName: ROPE = "EqConstant"; vCard: CARD = LOOPHOLE[v]; n0, n1: NAT _ 0; int0, int1: Wire; in: Wire; wr0, wr1: LIST OF WR _ NIL; fullName: ROPE = IO.PutFR["EqConstant b=%g v=%g", IO.int[b], IO.int[v]]; ct _ CacheFetch[fullName]; IF ct#NIL THEN RETURN[ct]; IF b=0 THEN Error["Please specify a number of bits for the constant comparator"]; <<-- sort out the zeros from the ones, and create the internals>> in _ Seq["In", b]; FOR i: NAT IN [0..b) DO IF BitOps.EBFD[vCard, i, b] THEN {n1 _ n1+1; wr1 _ CONS[in[i], wr1]} ELSE {n0 _ n0+1; wr0 _ CONS[in[i], wr0]}; ENDLOOP; SELECT TRUE FROM n0+n1#b => ERROR; -- just a check n0=0 => { -- and[b] is enough ct _ Cell[name: eqConstantName, public: Wires["Vdd", "Gnd", in, "out"], instances: LIST[InstanceList[Logic.And[b], LIST[["X", "out"], ["I", in]]]]]; }; n1=0 => { -- nor[b] is enough ct _ Cell[name: eqConstantName, public: Wires["Vdd", "Gnd", in, "out"], instances: LIST[InstanceList[Logic.Nor[b], LIST[["X", "out"], ["I", in]]]]]; }; ENDCASE => { subCT: CellType = Extract["eqConstant2Inputs.sch", LIST[["n0", n0], ["n1", n1]]]; int0 _ WireList[wr0]; int1 _ WireList[wr1]; ct _ Cell[name: eqConstantName, public: Wires["Vdd", "Gnd", in, "out"], onlyInternal: Wires[int0, int1], instances: LIST[InstanceList[subCT, LIST[["out", "out"], ["in0", int0], ["in1", int1]]]]]; }; CoreProperties.PutCellTypeProp[ct, $value, NEW[INT _ v]]; SimulateMacro[ct, EqConstantRoseClass]; Ports.InitPorts[ct, ls, none, "In"]; Ports.InitPorts[ct, l, drive, "out"]; CacheStore[fullName, ct]; }; EqConstantState: TYPE = REF EqConstantStateRec; EqConstantStateRec: TYPE = RECORD [eqIn, eqOut: NAT, val: Ports.LevelSequence]; EqConstantInit: Rosemary.InitProc = { state: EqConstantState _ IF oldStateAny=NIL THEN NEW[EqConstantStateRec] ELSE NARROW[oldStateAny]; v: INT = NARROW[CoreProperties.GetCellTypeProp[cellType, $value], REF INT]^; [state.eqIn, state.eqOut] _ Ports.PortIndexes[cellType.public, "In", "out"]; state.val _ NEW[Ports.LevelSequenceRec[cellType.public[state.eqIn].size]]; Ports.LCToLS[LOOPHOLE [v], state.val]; stateAny _ state; }; EqConstantSimple: Rosemary.EvalProc = { state: EqConstantState _ NARROW[stateAny]; p[state.eqOut].l _ LSEqual[p[state.eqIn].ls, state.val]; }; END.