<> <> <> DIRECTORY Basics, CardTab, Core, CoreClasses, CoreCreate, IO, Ports, Rope, Rosemary; VRamImpl: CEDAR PROGRAM IMPORTS Basics, CardTab, CoreClasses, CoreCreate, IO, Ports, Rosemary ~ BEGIN Data, ColPDBb, ColPDB, ColPDA, RowPD0, RowPD1, RowPD2, EvenClkb, OddClkb, preb, preClkb, pullSense2Low, VRamWriteEn, wlLow, DummyGnd, Vdd, Gnd: NAT _ LAST[NAT]; ROPE: TYPE = Core.ROPE; Port: TYPE = Ports.Port; addWidth: CARDINAL = 40; Address: TYPE = [0..1024); dataWidth: CARDINAL = 40; Handle: TYPE = REF HandleRec; HandleRec: TYPE = RECORD [ prevClk: Ports.Level, master: Ports.LevelSequence, storage: CardTab.Ref _ NIL ]; BITSHIFT: PROC [value: WORD, count: INTEGER] RETURNS [WORD] = Basics.BITSHIFT; BITAND: Basics.BitOp = Basics.BITAND; BITOR: Basics.BitOp = Basics.BITOR; BITNOT: PROC [WORD] RETURNS [WORD] = Basics.BITNOT; VRamError: SIGNAL [msg: Rope.ROPE] = CODE; InitPortIndicies: PROC [ct: Core.CellType] = { [Data, ColPDBb, ColPDB, ColPDA, RowPD0, RowPD1, RowPD2, EvenClkb, OddClkb] _ Ports.PortIndexes[ct.public, "Data", "ColPDBb", "ColPDB", "ColPDA", "RowPD0", "RowPD1", "RowPD2", "EvenClkb", "OddClkb"]; [preb, preClkb, pullSense2Low, VRamWriteEn, wlLow, DummyGnd, Vdd, Gnd] _ Ports.PortIndexes[ct.public, "preb", "preClkb", "pullSense2Low", "VRamWriteEn", "wlLow", "DummyGnd", "Vdd", "Gnd"]; }; Create: PUBLIC PROC [] RETURNS [ct: Core.CellType] = { ct _ CoreClasses.CreateUnspecified[ public: CoreCreate.WireList[LIST[CoreCreate.Seq["Data", dataWidth], "ColPDBb", "ColPDB", CoreCreate.Seq["ColPDA", 4], CoreCreate.Seq["RowPD0", 4], CoreCreate.Seq["RowPD1", 4], CoreCreate.Seq["RowPD2", 4], "EvenClkb", "OddClkb", "preb", "preClkb", "pullSense2Low", "VRamWriteEn", "wlLow", "DummyGnd", "Vdd", "Gnd"], "VRam", NIL], name: vRamName ]; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: vRamName]; [] _ Ports.InitPorts[ct, l, none, "ColPDBb", "ColPDB", "EvenClkb", "OddClkb", "preClkb", "pullSense2Low", "VRamWriteEn"]; [] _ Ports.InitPorts[ct, l, drive, "preb", "wlLow"]; [] _ Ports.InitPorts[ct, ls, none, "ColPDA"]; [] _ Ports.InitPorts[ct, ls, none, "RowPD0"]; [] _ Ports.InitPorts[ct, ls, none, "RowPD1"]; [] _ Ports.InitPorts[ct, ls, none, "RowPD2"]; [] _ Ports.InitPorts[ct, ls, none, "Data"]; }; VRamInit: Rosemary.InitProc = { h: Handle _ NEW[HandleRec]; InitPortIndicies[cellType]; h.storage _ CardTab.Create[]; h.master _ NEW[Ports.LevelSequenceRec[dataWidth]]; stateAny _ h; }; VRamSimple: Rosemary.EvalProc = { <<--PROC [p: Ports.Port, stateAny: REF ANY]-->> h: Handle _ NARROW[stateAny]; clk: Ports.Level _ Ports.AndL[p[EvenClkb].l, p[OddClkb].l]; p[preb].l _ p[preClkb].l; p[wlLow].l _ clk; p[Data].d _ IF p[VRamWriteEn].l=H THEN none ELSE drive; IF clk=H THEN BusToMaster[h, p]; IF clk=L AND h.prevClk=H AND p[VRamWriteEn].l=H THEN MasterToStorage[h, p]; IF clk=L AND h.prevClk=H AND p[VRamWriteEn].l=L THEN StorageToBus[h, p]; h.prevClk _ clk; }; BusToMaster: PROC [h: Handle, p: Port] ~ { Ports.CopyLS[p[Data].ls, h.master]; }; MasterToStorage: PROC [h: Handle, p: Port] ~ { ls: Ports.LevelSequence _ NEW[Ports.LevelSequenceRec[dataWidth]]; Ports.CopyLS[p[Data].ls, ls]; [] _ CardTab.Store[h.storage, Add[p], ls]; }; StorageToBus: PROC [h: Handle, p: Port] ~ { found: BOOL _ FALSE; val: REF _ NIL; [found, val] _ CardTab.Fetch[h.storage, Add[p]]; IF found THEN Ports.CopyLS[NARROW[val, Ports.LevelSequence], p[Data].ls] ELSE Ports.SetLS[p[Data].ls, X]; }; Add: PROC [p: Port] RETURNS [add: CARDINAL] ~ { c: CARDINAL _ 0; add _ IF p[EvenClkb].l = L THEN 1 ELSE 0; c _ Demux[Ports.LSToLC[p[RowPD2].ls], FALSE]; add _ BITOR[add, BITSHIFT[c, 1]]; c _ Demux[Ports.LSToLC[p[RowPD1].ls], FALSE]; add _ BITOR[add, BITSHIFT[c, 3]]; c _ Demux[Ports.LSToLC[p[RowPD0].ls], FALSE]; add _ BITOR[add, BITSHIFT[c, 5]]; c _ Demux[Ports.LSToLC[p[ColPDA].ls]]; add _ BITOR[add, BITSHIFT[c, 7]]; c _ IF p[ColPDBb].l = L THEN 1 ELSE 0; add _ BITOR[add, BITSHIFT[c, 9]]; }; Demux: PROC [c: CARDINAL, pos: BOOL _ TRUE] RETURNS [CARDINAL] ~ { SELECT c FROM 0 => IF pos THEN RETURN[0] ELSE ERROR; 1 => IF pos THEN RETURN[3] ELSE ERROR; 2 => IF pos THEN RETURN[2] ELSE ERROR; 4 => IF pos THEN RETURN[1] ELSE ERROR; 8 => IF pos THEN RETURN[0] ELSE ERROR; 0fh => IF NOT pos THEN RETURN[0] ELSE ERROR; 0eh => IF NOT pos THEN RETURN[3] ELSE ERROR; 0dh => IF NOT pos THEN RETURN[2] ELSE ERROR; 0bh => IF NOT pos THEN RETURN[1] ELSE ERROR; 07h => IF NOT pos THEN RETURN[0] ELSE ERROR; ENDCASE => ERROR; }; PrintStorage: PROC [s: IO.STREAM, h: Handle] ~ { PrintIt: CardTab.EachPairAction ~ { IO.PutF[s, "Add: %x, Data: %g\n", IO.card[key], IO.rope[Ports.LSToRope[NARROW[val, Ports.LevelSequence]]]]; RETURN[FALSE]; }; [] _ CardTab.Pairs[h.storage, PrintIt]; }; vRamName: ROPE = Rosemary.Register[roseClassName: "VRam", init: VRamInit, evalSimple: VRamSimple]; END.