BICTopLevel.mesa
Copyright Ó 1987 by Xerox Corporation. All rights reserved.
Louis Monier September 15, 1987 3:38:07 pm PDT
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
Assert[NOT p[Gnd].b AND NOT p[Gnd2V].b];
Assert[p[Vdd].b];
Assert[NOT MoreThanOne[normal, freeze, shift, reset]];
-- 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;
nChain ← BitOps.IBID[nOrFSlave, nChain, 0, 27];
nChain ← BitOps.ICID[nRqFSlave, nChain, 1, 2, 27];
nChain ← BitOps.ILID[nBSlave, nChain, 3, 24, 27];
orMaster ← BitOps.EBFD[nChain, 0, 27];
rqMaster ← BitOps.ECFD[nChain, 1, 2, 27];
bMaster ← BitOps.ELFD[nChain, 3, 24, 27];
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]];
chain ← 2*chain+BtoN[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.