<> <> <> DIRECTORY BitOps, CoreClasses, CoreCreate, CoreIO, CoreFlat, CoreProperties, Ports, Rosemary; BICTopLevel: CEDAR PROGRAM IMPORTS BitOps, CoreClasses, CoreCreate, CoreIO, CoreFlat, Ports, Rosemary = BEGIN OPEN CoreCreate; BICName: ROPE = Rosemary.Register[roseClassName: "BIC", init: BICInit, evalSimple: BICSimple]; AssertionFailed: SIGNAL [message: ROPE] = CODE; Assert: PROC [condition: BOOL, message: ROPE _ NIL] = {IF NOT condition THEN SIGNAL AssertionFailed[message]}; BtoN: PROC [b: BOOL] RETURNS [NAT] ~ {RETURN[IF b THEN 1 ELSE 0]}; MoreThanOne: PROC [a, b, c, d: BOOL _ FALSE] RETURNS [BOOL _ FALSE] ~ { RETURN[BtoN[a]+BtoN[b]+BtoN[c]+BtoN[d]>1]; }; Or4: PROC [a: CARD] RETURNS [b: BOOL] ~ { b _ BitOps.EBFD[a, 31] OR BitOps.EBFD[a, 30] OR BitOps.EBFD[a, 29] OR BitOps.EBFD[a, 28]; }; <<-- address on 8 bits, id = cid[3] cs[2] rs[3]>> ExplodeAddress: PROC [id: CARD] RETURNS [cid, cs, rs: CARDINAL] ~ { IF id NOT IN [0..256) THEN ERROR; cid _ BitOps.ECFD[id, 0, 3, 8]; -- 3 high-order bits: compare to Name cs _ BitOps.ECFD[id, 3, 2, 8]; -- next 2 bits: this BIC or a client circuit rs _ BitOps.ECFD[id, 5, 3, 8]; -- 3 low-order bits: scan path in BIC }; CreateBIC: PUBLIC PROC [fromFile: BOOL _ FALSE] RETURNS [ct: CellType ] = { IF fromFile THEN ct _ CoreIO.RestoreCellType["BIC", NIL] ELSE { <<-- this public conforms to BICForSim.icon in BIC.dale>> public: Wire _ WireList[LIST[ <<-- power>> "Vdd", "Gnd", "Gnd2V", "CKRecAdj", "RecAdj", <<-- clocks>> "nEClock", "Clock", "ChipCKIn", "ExtCKIn", "ChipCKOut", "ExtCKOut", "LocCKOut", <<-- board side>> Seq["nDInB", 3], Seq["nBInB", 24], Seq["nRqOutB", 2], Seq["nDOutB", 3], Seq["nBOutB", 24], "nOrOutB", <<-- hybrid side>> Seq["DInH", 3], Seq["BInH", 24], Seq["RqIn", 2], Seq["OrInH", 4], Seq["DOutH", 3], Seq["BOutH", 24], <<-- DBus et al.>> "nSStop", "DOEn", Seq["Name", 3], Seq["DBusIn", 7], Seq["Send", 4], "DBusOut", Seq["DCS", 3] ]]; ct _ CoreClasses.CreateUnspecified[public, BICName]; }; [] _ Rosemary.BindCellType[cellType: ct, roseClassName: BICName]; [] _ CoreFlat.CellTypeCutLabels[ct, "BIC"]; Ports.InitPorts[ct, b, none, "Vdd", "Gnd", "Gnd2V", "CKRecAdj", "RecAdj"]; Ports.InitPorts[ct, b, none, "nEClock", "Clock", "ChipCKIn", "ExtCKIn"]; Ports.InitPorts[ct, b, drive, "ChipCKOut", "ExtCKOut", "LocCKOut"]; Ports.InitPorts[ct, lc, none, "nDInB", "nBInB"]; Ports.InitPorts[ct, lc, drive, "nRqOutB", "nDOutB", "nBOutB"]; Ports.InitPorts[ct, b, drive, "nOrOutB"]; Ports.InitPorts[ct, lc, none, "DInH", "BInH", "RqIn", "OrInH"]; Ports.InitPorts[ct, lc, drive, "DOutH", "BOutH"]; Ports.InitPorts[ct, b, none, "nSStop", "DOEn"]; Ports.InitPorts[ct, lc, none, "Name"]; Ports.InitPorts[ct, bs, none, "DBusIn", "Send"]; Ports.InitPorts[ct, b, drive, "DBusOut"]; Ports.InitPorts[ct, lc, drive, "DCS"]; }; BICState: TYPE = REF BICStateRec; BICStateRec: TYPE = RECORD[ Vdd, Gnd, Gnd2V, CKRecAdj, RecAdj, nEClock, Clock, ChipCKIn, ExtCKIn, ChipCKOut, ExtCKOut, LocCKOut, nDInB, nBInB, nRqOutB, nDOutB, nBOutB, nOrOutB, DInH, BInH, RqIn, OrInH, DOutH, BOutH, nSStop, DOEn, Name, DBusIn, Send, DBusOut, DCS: NAT _ LAST[NAT], -- ports indexes resetM, normalM, freezeM, shiftM, normal, freeze, shift, reset: BOOL _ FALSE, <<-- from hybrid to board>> bMaster, bSlave: CARD _ 0, -- 24 orMaster, orSlave: BOOL _ FALSE, -- 1 rqMaster, rqSlave: CARD _ 0, -- 2 <<-- from board to hybrid>> nBMaster, nBSlave: CARD _ 0, -- 24 nOrFMaster, nOrFSlave: BOOL _ FALSE, -- 1 nRqFMaster, nRqFSlave: CARD _ 0, -- 2 <<-- control>> r1M, r2M, er1M, f1M, f2M, s1M, s2M, s3M, e1M, e2M: BOOL _ FALSE, r1S, r2S, er1S, f1S, f2S, s1S, s2S, s3S, e1S, e2S: BOOL _ FALSE, deviceIdM, deviceIdS: CARD _ 0, -- 8 bits chipIdM, chipIdS: CARD _ 0, -- 16 bits extCkM, extCkS: CARD _ 0, -- 4 bits intCkM, intCkS: CARD _ 0, -- 4 bits last: BOOL _ FALSE ]; BICInit: Rosemary.InitProc = { state: BICState _ NEW[BICStateRec]; {OPEN state; [Vdd, Gnd, Gnd2V, CKRecAdj, RecAdj] _ Ports.PortIndexes[cellType.public, "Vdd", "Gnd", "Gnd2V", "CKRecAdj", "RecAdj"]; [nEClock, Clock, ChipCKIn, ExtCKIn] _ Ports.PortIndexes[cellType.public, "nEClock", "Clock", "ChipCKIn", "ExtCKIn"]; [ChipCKOut, ExtCKOut, LocCKOut] _ Ports.PortIndexes[cellType.public, "ChipCKOut", "ExtCKOut", "LocCKOut"]; [nDInB, nBInB] _ Ports.PortIndexes[cellType.public, "nDInB", "nBInB"]; [nRqOutB, nDOutB, nBOutB, nOrOutB] _ Ports.PortIndexes[cellType.public, "nRqOutB", "nDOutB", "nBOutB", "nOrOutB"]; [DInH, BInH, RqIn, OrInH] _ Ports.PortIndexes[cellType.public, "DInH", "BInH", "RqIn", "OrInH"]; [DOutH, BOutH] _ Ports.PortIndexes[cellType.public, "DOutH", "BOutH"]; [nSStop, DOEn, Name, DBusIn, Send] _ Ports.PortIndexes[cellType.public, "nSStop", "DOEn", "Name", "DBusIn", "Send"]; [DBusOut, DCS] _ Ports.PortIndexes[cellType.public, "DBusOut", "DCS"]; }; stateAny _ state; }; ShiftOneLeft: PROC [from: CARD, size: NAT, lsb: BOOL] RETURNS [CARD] ~ { RETURN[BitOps.DShift[from, 1, size]+BtoN[lsb]]; }; Decoder: PROC [ad: CARD, en: BOOL, s: NAT] RETURNS [sel: CARD] ~ { sel _ IF ~en THEN 0 ELSE BitOps.TwoToThe[s-1-ad] }; BICSimple: Rosemary.EvalProc = { state: BICState _ NARROW[stateAny]; ck, grant, csOn: BOOL; cid, cs, rs, csOt, selScanPath: CARD _ 0; <<-- structure of DBusIn>> nDReset: NAT = 0; nDFreeze: NAT = 1; DExecute: NAT = 2; DShiftCK: NAT = 3; nDAddress: NAT = 4; DBusInIndex: NAT = 5; HybridSel: NAT = 6; <<-- structure of selScanPath>> ReadChipID: NAT = 128; AccessDP: NAT = 64; ReadExtCK: NAT = 32; ReadIntCK: NAT = 16; WriteExtCK: NAT = 8; WriteIntCK: NAT = 4; {OPEN state; <<-- Check that power supplies are well hooked up>> <> <> <> <<>> <<-- Unclocked stuff>> [cid, cs, rs] _ ExplodeAddress[deviceIdS]; csOn _ (cid=p[Name].lc) AND p[DBusIn].bs[nDAddress] AND p[DBusIn].bs[HybridSel]; csOt _ Decoder[ad: cs, en: csOn, s: 4]; selScanPath _ Decoder[ad: rs, en: csOt=8, s: 8]; grant _ p[Send].bs[0] OR p[Send].bs[1] OR p[Send].bs[2] OR p[Send].bs[3]; <<>> <<-- Clocks: we ignore Clock and ExtCKIn>> p[LocCKOut].b _ p[ExtCKOut].b _ NOT p[nEClock].b; <<-- at the Rosemary level, the delay lines are invisible>> ck _ p[ChipCKOut].b _ p[ChipCKIn].b; <<-- ck is the current clock distributed inside the chip>> <<>> <<-- Using DShiftCK as clock>> <<-- DBus address register>> SELECT p[DBusIn].bs[DShiftCK] FROM FALSE => { SELECT TRUE FROM NOT p[DBusIn].bs[nDAddress] => deviceIdM _ ShiftOneLeft[deviceIdS, 8, p[DBusIn].bs[DBusInIndex]]; -- shift chipID ENDCASE => NULL; }; TRUE => deviceIdS _ deviceIdM; ENDCASE => ERROR; <<>> <<-- (0) ChipID shift register>> SELECT p[DBusIn].bs[DShiftCK] FROM FALSE => { SELECT TRUE FROM NOT p[DBusIn].bs[nDAddress] => chipIdM _ 5081H; -- load chipID selScanPath=ReadChipID => chipIdM _ ShiftOneLeft[chipIdS, 16, p[DBusIn].bs[DBusInIndex]]; -- shift chipID ENDCASE => NULL; }; TRUE => chipIdS _ chipIdM; ENDCASE => ERROR; <<>> <<-- (2 and 4) External clock shift register>> SELECT p[DBusIn].bs[DShiftCK] FROM FALSE => IF selScanPath=ReadExtCK OR selScanPath=WriteExtCK THEN extCkM _ ShiftOneLeft[extCkS, 4, p[DBusIn].bs[DBusInIndex]]; -- shift extCkM TRUE => extCkS _ extCkM; ENDCASE => ERROR; <<>> <<-- (3 and 5) Internal clock shift register>> SELECT p[DBusIn].bs[DShiftCK] FROM FALSE => IF selScanPath=ReadIntCK OR selScanPath=WriteIntCK THEN intCkM _ ShiftOneLeft[intCkS, 4, p[DBusIn].bs[DBusInIndex]]; -- shift extCkM TRUE => intCkS _ intCkM; ENDCASE => ERROR; <<-- System clock: Control of slices>> IF NOT ck THEN { -- clock is low: sample the input in all masters f4: BOOL; r1M _ p[DBusIn].bs[nDReset]; r2M _ r1S; er1M _ p[nSStop].b; f1M _ p[DBusIn].bs[nDFreeze]; f2M _ f1S; s1M _ NOT(p[DBusIn].bs[DShiftCK] AND BitOps.EBFD[selScanPath, 1, 8]); -- AccessDP s2M _ s1S; s3M _ s2S; e1M _ p[DBusIn].bs[DExecute]; e2M _ e1S; <<-- the order of evaluation is important>> f4 _ ~(er1S AND f2S); resetM _ r2S; freezeM _ ~(r2S AND f4 AND ~(~s2S AND s3S)); shiftM _ ~(~s2S AND s3S AND ~e2S) ; normalM _ ~(resetM AND freezeM AND shiftM); -- leave as last expression! SELECT TRUE FROM normal => { bMaster _ IF grant THEN p[BInH].lc ELSE 0; orMaster _ Or4[p[OrInH].lc]; rqMaster _ p[RqIn].lc; nBMaster _ p[nBInB].lc; nOrFMaster _ TRUE; -- guess why! nRqFMaster _ 3; }; reset => { bMaster _ 0; orMaster _ FALSE; rqMaster _ 0; nBMaster _ 0FFFFFFFFH; nOrFMaster _ TRUE; nRqFMaster _ 3; }; shift => { -- p[DBusIn].bs[DBusIn] to Normal to Request to Or to DPShiftOut; lsb to msb <<-- chain is the chain of flops whose outputs, inverted, will become BOutH; the 3 ghost flops do not come out;>> chain: CARD _ 0; -- 27 bits bMaster _ nBSlave; rqMaster _ nRqFSlave; orMaster _ nOrFSlave; <> <> <> <> <> <> chain _ BitOps.ILID[bSlave, chain, 3, 24, 27]; chain _ BitOps.ICID[rqSlave, chain, 1, 2, 27]; chain _ BitOps.IBID[orSlave, chain, 0, 27]; chain _ ShiftOneLeft[chain, 27, NOT p[DBusIn].bs[DBusInIndex]]; <> nBMaster _ BitOps.ELFD[chain, 3, 24, 27]; nRqFMaster _ BitOps.ECFD[chain, 1, 2, 27]; nOrFMaster _ BitOps.EBFD[chain, 0, 27]; }; freeze => NULL; ENDCASE => NULL; } ELSE { -- clock is high: copy masters into slaves r1S _ r1M; r2S _ r2M; er1S _ er1M; f1S _ f1M; f2S _ f2M; s1S _ s1M; s2S _ s2M; s3S _ s3M; e1S _ e1M; e2S _ e2M; normal _ NOT normalM; freeze _ NOT freezeM; shift _ NOT shiftM; reset _ NOT resetM; bSlave _ bMaster; rqSlave _ rqMaster; orSlave _ orMaster; nBSlave _ nBMaster; nRqFSlave _ nRqFMaster; nOrFSlave _ nOrFMaster; }; <<-- Always copy slaves to outputs>> <<>> <<-- 2V outputs (remember to modify to express the wired or: value=0, drive changes)>> p[nDOutB].lc _ BitOps.DNOT[IF p[DOEn].b THEN p[DInH].lc ELSE 0]; p[nBOutB].lc _ BitOps.DNOT[bSlave]; p[nOrOutB].b _ ~ orSlave; p[nRqOutB].lc _ BitOps.DNOT[rqSlave]; <<-- 5V outputs>> p[DOutH].lc _ BitOps.DNOT[p[nDInB].lc]; p[BOutH].lc _ BitOps.DNOT[nBSlave]; p[DCS].lc _ csOt MOD 8; -- low-order three bits p[DBusOut].b _ SELECT selScanPath FROM 0 => TRUE, -- should be tristate ReadChipID => BitOps.EBFD[chipIdS, 0, 16], -- ChipID AccessDP => NOT orSlave, -- DPShiftOut ReadExtCK => BitOps.EBFD[extCkS, 0, 4], -- ExtCkDelay ReadIntCK => BitOps.EBFD[intCkS, 0, 4], -- IntCkDelay WriteExtCK => BitOps.EBFD[extCkS, 0, 4], -- ExtDelayState WriteIntCK => BitOps.EBFD[intCkS, 0, 4], -- IntDelayState ENDCASE => ERROR; }}; END.