<> <> <> <<>> DIRECTORY BitHacks, CoreClasses, CoreCreate, CoreProperties, Logic, Ports, Rosemary, Sisyph; LogicMacrosImpl: CEDAR PROGRAM IMPORTS BitHacks, CoreClasses, CoreCreate, CoreProperties, Logic, Rosemary, Sisyph EXPORTS Logic = BEGIN OPEN Logic, CoreCreate; <> RegisterName: ROPE = "Register"; RegisterRName: ROPE = "RegisterR"; registerVdd, registerGnd, registerCK, registerInput, registerOutput, registerEnable: NAT; registerRVdd, registerRGnd, registerRCK, registerRInput, registerROutput, registerREnable, registerRReset: NAT; Register: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ SequenceCell[name: RegisterName, baseCell: Sisyph.ES["reg1B.sch", cx], count: b, sequencePorts: Wires["Input", "Output"]]; [registerVdd, registerGnd, registerCK, registerInput, registerOutput, registerEnable] _ PortIndexes[ct.public, "Vdd", "Gnd", "CK", "Input", "Output", "en"]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, drive, "Output"]; }; RegisterR: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ SequenceCell[name: RegisterRName, baseCell: Sisyph.ES["reg1BitReset.sch", cx], count: b, sequencePorts: Wires["Input", "Output"]]; [registerRVdd, registerRGnd, registerRCK, registerRInput, registerROutput, registerREnable, registerRReset] _ PortIndexes[ct.public, "Vdd", "Gnd", "CK", "Input", "Output", "en", "r"]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "CK", "en", "r"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, drive, "Output"]; }; << Tristate Buffer>> TstBufferName: ROPE = Rosemary.Register[roseClassName: "TstBuffer", evalSimple: TstBufferSimple]; TstBufferInvName: ROPE = Rosemary.Register[roseClassName: "TstBufferInv", evalSimple: TstBufferInvSimple]; tstBufferVdd, tstBufferGnd, tstBufferInput, tstBufferOutput, tstBufferEnable: NAT; tstBufferInvVdd, tstBufferInvGnd, tstBufferInvInput, tstBufferInvOutput, tstBufferInvEnable: NAT; TristateBuffer: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: TstBufferName, public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferName]; [tstBufferVdd, tstBufferGnd, tstBufferInput, tstBufferOutput, tstBufferEnable] _ PortIndexes[ct.public, "Vdd", "Gnd", "Input", "Output", "enable"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "enable"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, none, "Output"]; }; TristateBufferInv: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: TstBufferInvName, public: Wires["Vdd", "Gnd", Seq["Input", b], Seq["Output", b], "enable"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: TstBufferInvName]; [tstBufferInvVdd, tstBufferInvGnd, tstBufferInvInput, tstBufferInvOutput, tstBufferInvEnable] _ PortIndexes[ct.public, "Vdd", "Gnd", "Input", "Output", "enable"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "enable"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, none, "Output"]; }; TstBufferSimple: Rosemary.EvalProc = { IF p[tstBufferEnable].l=H THEN { p[tstBufferOutput].d _ drive; CopyLS[from: p[tstBufferInput].ls, to: p[tstBufferOutput].ls]; } ELSE p[tstBufferOutput].d _ none; }; TstBufferInvSimple: Rosemary.EvalProc = { IF p[tstBufferInvEnable].l=H THEN { p[tstBufferInvOutput].d _ drive; CopyLS[from: p[tstBufferInvInput].ls, to: p[tstBufferInvOutput].ls]; } ELSE p[tstBufferInvOutput].d _ none; }; <> AdderName: ROPE = Rosemary.Register[roseClassName: "Adder", evalSimple: AdderSimple]; adderVdd, adderGnd, adderA, adderB, adderSum, adderCarryIn, adderCarryOut: NAT; <<-- b>1 please>> <<-- Sum[0] is the (wrong Mesa order) high-order bit>> Adder: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { oneBitAdder: CellType _ Sisyph.ES["oneBitAdder.sch", cx]; -- designed by Alfred insts: CellInstances _ LIST[Instance[oneBitAdder, ["A", "A[0]"], ["B", "B[0]"], ["Sum", "Sum[0]"], ["Cout", "carryOut"], ["C", "carry[0]"]]]; IF b<2 THEN ERROR; -- we'll be more graceful soon!!! FOR i: NAT IN [1..b-1) DO insts _ CONS[ Instance[oneBitAdder, ["A", Index["A", i]], ["B", Index["B", i]], ["Sum", Index["Sum", i]], ["Cout", Index["carry", i-1]], ["C", Index["carry", i]]], insts]; ENDLOOP; insts _ CONS[ Instance[oneBitAdder, ["A", Index["A", b-1]], ["B", Index["B", b-1]], ["Sum", Index["Sum", b-1]], ["Cout", Index["carry", b-2]], ["C", "carryIn"]], insts]; ct _ Cell[ name: AdderName, public: Wires["Vdd", "Gnd", "carryIn", Seq["A", b], Seq["B", b], Seq["Sum", b], "carryOut"], onlyInternal: Wires[Seq["carry", b-1]], instances: insts]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: AdderName]; [adderVdd, adderGnd, adderA, adderB, adderSum, adderCarryIn, adderCarryOut] _ PortIndexes[ct.public, "Vdd", "Gnd", "A", "B", "Sum", "carryIn", "carryOut"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "carryIn"]; [] _ InitPorts[ct, l, drive, "carryOut"]; [] _ InitPorts[ct, ls, none, "A", "B"]; [] _ InitPorts[ct, ls, drive, "Sum"]; }; AdderSimple: Rosemary.EvalProc = { carry: Ports.Level _ p[adderCarryIn].l; FOR i: NAT DECREASING IN [0..p[adderSum].ls.size) DO [carry, p[adderSum].ls[i]] _ SumL[p[adderA].ls[i], p[adderB].ls[i], carry]; ENDLOOP; p[adderCarryOut].l _ carry; }; <> ConstantName: ROPE = Rosemary.Register[roseClassName: "Constant", init: ConstantInit, evalSimple: ConstantSimple]; constantVdd, constantGnd, constantOutput: NAT; Constant: PUBLIC PROC [b: NAT, v: INT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: ConstantName, public: Wires["Vdd", "Gnd", Seq["Output", b]]]; CoreProperties.PutCellTypeProp[ct, $value, NEW[INT _ v]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ConstantName]; [constantVdd, constantGnd, constantOutput] _ PortIndexes[ct.public, "Vdd", "Gnd", "Output"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd"]; [] _ InitPorts[ct, lc, drive, "Output"]; }; ConstantInit: Rosemary.InitProc = { stateAny _ NARROW[CoreProperties.GetCellTypeProp[cellType, $value]]; }; ConstantSimple: Rosemary.EvalProc = { val: INT _ NARROW[stateAny, REF INT]^; p[constantOutput].lc _ val; }; <> ComparatorName: ROPE = Rosemary.Register[roseClassName: "Comparator", evalSimple: ComparatorSimple]; comparatorVdd, comparatorGnd, comparatorA, comparatorB, comparatorAEqB: NAT; Comparator: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: ComparatorName, public: Wires["Vdd", "Gnd", Seq["A", b], Seq["B", b], "AEqB"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: ComparatorName]; [comparatorVdd, comparatorGnd, comparatorA, comparatorB, comparatorAEqB] _ PortIndexes[ct.public, "Vdd", "Gnd", "A", "B", "AEqB"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd"]; [] _ InitPorts[ct, ls, none, "A", "B"]; [] _ InitPorts[ct, l, drive, "AEqB"]; }; ComparatorSimple: Rosemary.EvalProc = { p[comparatorAEqB].l _ H; FOR i: NAT IN [0..p[comparatorA].ls.size) DO IF p[comparatorA].ls[i]#p[comparatorB].ls[i] THEN p[comparatorAEqB].l _ L; ENDLOOP; }; <> Mux2Name: ROPE = Rosemary.Register[roseClassName: "Mux2", evalSimple: Mux2Simple]; mux2Vdd, mux2Gnd, mux2Select, mux2In0, mux2In1, mux2Output: NAT; Mux2: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: Mux2Name, public: Wires["Vdd", "Gnd", "Select", Seq["In0", b], Seq["In1", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: Mux2Name]; [mux2Vdd, mux2Gnd, mux2Select, mux2In0, mux2In1, mux2Output] _ PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "Output"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "Select"]; [] _ InitPorts[ct, ls, none, "In0", "In1"]; [] _ InitPorts[ct, ls, drive, "Output"]; }; Mux2Simple: Rosemary.EvalProc = { SELECT p[mux2Select].l FROM L => CopyLS[from: p[mux2In0].ls, to: p[mux2Output].ls]; H => CopyLS[from: p[mux2In1].ls, to: p[mux2Output].ls]; ENDCASE => SetLS[p[mux2In0].ls, X]; }; Mux3Name: ROPE = Rosemary.Register[roseClassName: "Mux3", evalSimple: Mux3Simple]; mux3Vdd, mux3Gnd, mux3Select, mux3In0, mux3In1, mux3In2, mux3Output: NAT; Mux3: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: Mux3Name, public: Wires["Vdd", "Gnd", Seq["Select", 2], Seq["In0", b], Seq["In1", b], Seq["In2", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: Mux3Name]; [mux3Vdd, mux3Gnd, mux3Select, mux3In0, mux3In1, mux3In2, mux3Output] _ PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "In2", "Output"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd"]; [] _ InitPorts[ct, c, none, "Select"]; [] _ InitPorts[ct, ls, none, "In0", "In1", "In2"]; [] _ InitPorts[ct, ls, drive, "Output"]; }; Mux3Simple: Rosemary.EvalProc = { SELECT p[mux3Select].c FROM 0 => CopyLS[from: p[mux3In0].ls, to: p[mux3Output].ls]; 1 => CopyLS[from: p[mux3In1].ls, to: p[mux3Output].ls]; 2 => CopyLS[from: p[mux3In2].ls, to: p[mux3Output].ls]; ENDCASE => ERROR; }; Mux4Name: ROPE = Rosemary.Register[roseClassName: "Mux4", evalSimple: Mux4Simple]; mux4Vdd, mux4Gnd, mux4Select, mux4In0, mux4In1, mux4In2, mux4In3, mux4Output: NAT; Mux4: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ct _ CoreClasses.CreateUnspecified[name: Mux4Name, public: Wires["Vdd", "Gnd", Seq["Select", 2], Seq["In0", b], Seq["In1", b], Seq["In2", b], Seq["In3", b], Seq["Output", b]]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: Mux4Name]; [mux4Vdd, mux4Gnd, mux4Select, mux4In0, mux4In1, mux4In2, mux4In3, mux4Output] _ PortIndexes[ct.public, "Vdd", "Gnd", "Select", "In0", "In1", "In2", "In3", "Output"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd"]; [] _ InitPorts[ct, c, none, "Select"]; [] _ InitPorts[ct, ls, none, "In0", "In1", "In2", "In3"]; [] _ InitPorts[ct, ls, drive, "Output"]; }; Mux4Simple: Rosemary.EvalProc = { SELECT p[mux4Select].c FROM 0 => CopyLS[from: p[mux4In0].ls, to: p[mux4Output].ls]; 1 => CopyLS[from: p[mux4In1].ls, to: p[mux4Output].ls]; 2 => CopyLS[from: p[mux4In2].ls, to: p[mux4Output].ls]; 3 => CopyLS[from: p[mux4In3].ls, to: p[mux4Output].ls]; ENDCASE => ERROR; }; <> DecoderName: ROPE = Rosemary.Register[roseClassName: "Decoder", evalSimple: DecoderSimple]; decoderVdd, decoderGnd, decoderAd, decoderNSel, decoderNEnable: NAT; Decoder: PUBLIC PROC [a: NAT, s: NAT _ 0] RETURNS [ct: CellType] = { IF s=0 THEN s _ BitHacks.TwoToThe[a]; ct _ CoreClasses.CreateUnspecified[name: DecoderName, public: Wires["Vdd", "Gnd", Seq["Address", a], Seq["nSelect", s], "nEnable"]]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: DecoderName]; [decoderVdd, decoderGnd, decoderAd, decoderNSel, decoderNEnable] _ PortIndexes[ct.public, "Vdd", "Gnd", "Address", "nSelect", "nEnable"]; [] _ Rosemary.AddCutSets[cellType: ct, cs1: macroCutSet]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "nEnable"]; [] _ InitPorts[ct, c, none, "Address"]; [] _ InitPorts[ct, ls, none, "nSelect"]; }; DecoderSimple: Rosemary.EvalProc = { ad: NAT _ p[decoderAd].c; IF ad>p[decoderNSel].size THEN ERROR; SELECT p[decoderNEnable].l FROM H => {p[decoderNSel].d _ drive; SetLS[p[decoderNSel].ls, H]; p[decoderNSel].ls[ad] _ L}; L => {p[decoderNSel].d _ none;}; ENDCASE => SetLS[p[decoderNSel].ls, X]; }; <> CounterName: ROPE = "Counter"; counterVdd, counterGnd, counters0, counters1, counterCin, counterCout, counterClock, counternInput, counterOutput: NAT; Counter: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { counter1B: CellType _ Sisyph.ES["counter1B.sch", cx]; -- designed by Alfred insts: CellInstances _ NIL; IF b<2 THEN ERROR; -- we'll be more graceful soon!!! FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[counter1B, ["dataIn", Index["Input", i]], ["Output", Index["Output", i]], ["carryIn", IF i=b-1 THEN "Cin" ELSE Index["carry", i]], ["carryOut", IF i=0 THEN "Cout" ELSE Index["carry", i-1]], ["nCount", "s1"], ["LoadOrDown", "s0"]], insts]; ENDLOOP; ct _ Cell[ name: CounterName, public: Wires["Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[Seq["carry", b-1]], instances: insts]; [counterVdd, counterGnd, counters0, counters1, counterCin, counterCout, counterClock, counternInput, counterOutput] _ PortIndexes[ct.public, "Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK", "Input", "Output"]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "s0", "s1", "Cin", "Cout", "CK"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, none, "Output"]; }; <> ShiftRegName: ROPE = "ShiftReg"; shiftRegVdd, shiftRegGnd, shiftRegs0, shiftRegs1, shiftRegClock, shiftRegInL, shiftRegInR, shiftRegnInput, shiftRegOutput: NAT; ShiftReg: PUBLIC PROC [b: NAT] RETURNS [ct: CellType] = { ff: CellType _ BasicFlipFlop[]; insts: CellInstances _ NIL; IF b<2 THEN ERROR; -- we'll be more graceful soon!!! FOR i: NAT IN [0..b) DO insts _ CONS[ Instance[ff, ["D0", IF i=0 THEN "inL" ELSE Index["Output", i-1]], ["D1", IF i=b-1 THEN "inR" ELSE Index["Output", i+1]], ["D2", Index["Output", i]], ["D3", Index["Input", i]], ["Q", Index["Output", i]], ["NQ", Index["fake", i]], ["s0", "s0"], ["s1", "s0"], ["s2", "s1"]], insts]; ENDLOOP; ct _ Cell[ name: ShiftRegName, public: Wires["Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", Seq["Input", b], Seq["Output", b]], onlyInternal: Wires[Seq["fake", b]], instances: insts]; [shiftRegVdd, shiftRegGnd, shiftRegs0, shiftRegs1, shiftRegClock, shiftRegInL, shiftRegInR, shiftRegnInput, shiftRegOutput] _ PortIndexes[ct.public, "Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR", "Input", "Output"]; [] _ InitPorts[ct, l, none, "Vdd", "Gnd", "s0", "s1", "CK", "inL", "inR"]; [] _ InitPorts[ct, ls, none, "Input"]; [] _ InitPorts[ct, ls, none, "Output"]; }; END.