IFUCoreCtlImpl.mesa,
Copyright c 1986 by Xerox Corporation. All rights reserved.
Last Edited by Curry, October 21, 1986 8:51:28 pm PDT
Don Curry October 30, 1986 9:45:11 am PST
DIRECTORY Core, CoreFrame, CoreGlue, CoreName, CoreOps, CoreProperties, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, REFBit, Rope;
IFUCoreCtlImpl: CEDAR PROGRAM
IMPORTS CoreFrame, CoreGlue, CoreName, CoreOps, CoreProperties, IFUCoreCtl, IFUCoreDrive, IO, Lists, PLAOps, REFBit, Rope
EXPORTS IFUCoreCtl =
BEGIN
ROPE:    TYPE = Core.ROPE;
CellType:   TYPE = Core.CellType;
Wire:    TYPE = Core.Wire;
SigRec:   TYPE = CoreName.SigRec;
Section:   TYPE = IFUCoreCtl.Section;
PLASection:  TYPE = IFUCoreCtl.PLASection;
PLASectionRec: TYPE = IFUCoreCtl.PLASectionRec;
PLADescription: TYPE = IFUCoreCtl.PLADescription;
XsFormSeqRec: TYPE = IFUCoreCtl.XsFormSeqRec;
PublicRefRec: TYPE = IFUCoreCtl.PublicRefRec;
XlatePubSeqRec: TYPE = IFUCoreCtl.XlatePubSeqRec;
PLAType:  TYPE = IFUCoreDrive.PLAType;
Drive:    TYPE = IFUCoreDrive.Drive;
DriveRec:   TYPE = IFUCoreDrive.DriveRec;
RowType:  TYPE = IFUCoreDrive.RowType;
Dir:    TYPE = IFUCoreDrive.Dir;
DrGate:   TYPE = IFUCoreDrive.DrGate;
Ph:    TYPE = IFUCoreDrive.Ph;
Polarity:   TYPE = IFUCoreDrive.Polarity;
Signal: SIGNAL = CODE;
ctlCellClass: PUBLIC Core.CellClass ←
CoreOps.SetClassPrintProc[
NEW[Core.CellClassRec ← [name: "IFUCoreCtl", recast: NIL]],
ClassPrintProc];
ClassPrintProc: CoreOps.PrintClassProc = {
ref: PLASection ← NARROW[data];
out.PutF["\nControl: ", IO.rope[ ref.desc.name ] ] };
CellProc: PUBLIC PROC [
section: Section,
desc:  PLADescription ]
RETURNS [cellType: Core.CellType] = { -- ctlCellClass
SELECT section FROM
complete => {
name: ROPE ← desc.name.Cat["Cmpl"];
cellType ← CoreFrame.NewFrameCells[name: name, rec: [first: top], cells: LIST[
CellProc[outSec,  desc ],
CellProc[inSec,  desc  ] ] ] };
outSec => {
name: ROPE ← desc.name.Cat["OutSec"];
cellType ← CoreFrame.NewFrameCells[name: name, rec: [first: left], cells: LIST[
CellProc[outBody, desc ],
CellProc[outDr,  desc  ] ] ] };
inSec  => {
name: ROPE ← desc.name.Cat["InSec"];
desc.includeIns ← TRUE;
cellType ← CoreFrame.NewFrameCells[name: name, rec: [first: left], cells: LIST[
CellProc[inSB,  desc ],
CellProc[inDr,  desc  ] ] ] };
ENDCASE => {
name: ROPESELECT section FROM
outBody => desc.name.Cat["OutBody"],
outDr  => desc.name.Cat["OutDr"],
inSB  => desc.name.Cat["InSB"],
inDr  => desc.name.Cat["InDr"],
ENDCASE => ERROR;
cellType ← CoreOps.SetCellTypeName[
NEW [ Core.CellTypeRec ← [
class:  ctlCellClass,
public: CoreOps.CreateWires[0],
data:  NEW[PLASectionRec ← [desc: desc, section: section] ] ] ],
name];
CoreFrame.SetFrameExpandProc[soft, cellType, NEW[CoreFrame.ExpandProc← Expand]];
CoreFrame.SetFrameExpandProc[hard, cellType,NEW[CoreFrame.ExpandProc𡤎xpand]]}};
Expand: CoreFrame.ExpandProc = {
secRec: PLASection ← NARROW[frameCT.data];
MakePLA[secRec.desc];
SELECT secRec.section FROM
inDr  =>
{CoreFrame.Expand[hard, secRec.desc.inDrCT];  frameCT^ ← secRec.desc.inDrCT^};
outDr  =>
{CoreFrame.Expand[hard, secRec.desc.outDrCT]; frameCT^ ← secRec.desc.outDrCT^};
inSB  =>
{CoreFrame.Expand[hard, secRec.desc.inSBCT];  frameCT^ ← secRec.desc.inSBCT^};
outBody =>
{              frameCT^ ← secRec.desc.outBodyCT^};
ENDCASE => Signal[];
CoreFrame.SetFrameExpandProc[soft, frameCT, NIL];
CoreFrame.SetFrameExpandProc[hard, frameCT, NIL] };
MakePLA: PUBLIC PROC [desc: PLADescription] = {
MakePLA1[desc];
MakePLA2[desc]};
MakePLA1: PUBLIC PROC [desc: PLADescription] = {
OPEN desc;
bitForm: REFBit.Format;
IF valid THEN RETURN;
IF plaType=precharged AND termsPerHeader=1000 THEN termsPerHeader�
IF ttt=NIL THEN ttt ← PLAOps.ReadPLAFile[name.Cat[".ttt"], log];
bitForm ← REFBit.Desc[ttt.data].bitForm;
FOR bit: INT DECREASING IN [0..bitForm.size) DO
bitForm[bit].name  ← CoreName.BitRopeToSigRope[bitForm[bit].name];
bitForm[bit].nameInv ← CoreName.BitRopeToSigRope[bitForm[bit].nameInv];
ENDLOOP;
bitForm ← REFBit.Desc[ttt.out].bitForm;
FOR bit: INT DECREASING IN [0..bitForm.size) DO
bitForm[bit].name  ← CoreName.BitRopeToSigRope[bitForm[bit].name];
bitForm[bit].nameInv ← CoreName.BitRopeToSigRope[bitForm[bit].nameInv];
ENDLOOP;
IF inDrs=NIL THEN {
initial: IFUCoreDrive.DriveRec ← [
drDir:  in,
dualOut: TRUE,
in:   [pos, plaPhs[drIn]  ],
ref:  [pos, plaPhs[drInClk] ],
out:  [pos, plaPhs[plaIn]  ] ];
inDrs ← IFUCoreDrive.RefToDrives[ttt.data, initial]};
IF outDrs=NIL THEN {
initial: IFUCoreDrive.DriveRec ← [
drDir:  out,
in:   [
pol: SELECT desc.plaType FROM precharged, hot=>neg ENDCASE=>pos,
ph: plaPhs[drOutClk] ],
ref:  [pos, plaPhs[drOutClk] ],
out:  [pos, plaPhs[drOut]  ],
plaType: desc.plaType,
fire:  desc.fire,
fireV:  desc.fireV,
nPreChg: desc.nPreChg ];
outDrs ← IFUCoreDrive.RefToDrives[ttt.out, initial]} };
IF plaInNames=NIL THEN {
inForm:  REFBit.Format ← REFBit.Desc[ttt.data].bitForm;
FOR i: CARDINAL DECREASING IN [0..inForm.size) DO
sig: SigRec ← CoreName.NameSig[inForm[i].name];
sigI: SigRec ← CoreName.NameSig[inForm[i].nameInv];
name: ROPEIF sig.root#NIL THEN inForm[i].name ELSE plaInNames ← CONS[ Select
[[TRUE, inForm[i].name, inForm[i].nameInv, plaPhs[plaIn]]], plaInNames];
plaInNames ← CONS[ CoreName.SignalName
[FALSE, inForm[i].name, inForm[i].nameInv, plaPhs[plaIn]], plaInNames];
ENDLOOP};
IF plaOutNames=NIL THEN {
outForm:  REFBit.Format ← REFBit.Desc[ttt.out].bitForm;
FOR i: CARDINAL DECREASING IN [0..outForm.size) DO
plaOutNames ← CONS[ CoreName.SignalName
[FALSE, outForm[i].name, outForm[i].nameInv, plaPhs[drOut]], plaOutNames];
ENDLOOP};
IF drSignalOrder=NIL THEN {
outForm:  REFBit.Format ← REFBit.Desc[ttt.out].bitForm;
FOR i: CARDINAL DECREASING IN [0..outForm.size) DO
drSignalOrder ← CONS[ CoreName.SignalName
[FALSE, outForm[i].name, outForm[i].nameInv, plaPhs[drOut]], drSignalOrder];
ENDLOOP};
MakePLA2: PUBLIC PROC [desc: PLADescription] = {
OPEN desc;
IF valid THEN RETURN;
IF plaInNames=NIL THEN {
FOR list: IFUCoreDrive.Drives ← inDrs, list.rest WHILE list#NIL DO
IF list.first.drRowType#conn THEN LOOP;
plaInNames ← CONS[IFUCoreDrive.DriveName[list.first, out], plaInNames];
plaInNames ← CONS[IFUCoreDrive.DriveName[list.first, nout], plaInNames] ENDLOOP;
plaInNames ← Lists.ReverseList[plaInNames]};
IF plaOutNames=NIL THEN {
FOR list: IFUCoreDrive.Drives ← outDrs, list.rest WHILE list#NIL DO
IF list.first.drRowType#conn THEN LOOP;
plaOutNames ← CONS[IFUCoreDrive.DriveName[list.first, in], plaOutNames] ENDLOOP;
plaOutNames ← Lists.ReverseList[plaOutNames]};
IF drSignalOrder=NIL THEN {
FOR list: IFUCoreDrive.Drives ← outDrs, list.rest WHILE list#NIL DO
IF list.first.drRowType#conn THEN LOOP;
drSignalOrder ← CONS[IFUCoreDrive.DriveName[list.first, in], drSignalOrder] ENDLOOP;
drSignalOrder ← Lists.ReverseList[drSignalOrder]};
BuildConnTranslationArray[desc];
SELECT plaType FROM
hot    => IFUCoreCtl.MakeHotPLA[desc];
precharged  => IFUCoreCtl.MakePreChargedPLA[desc];
ENDCASE   => ERROR;
ENDCASE   => IFUCoreCtl.MakeStaticPLA[desc];
outSh ← inSh;
IF includeIns THEN
outSh ← IFUCoreDrive.ConnectDrives[inDrs,  outSh];
outSh ← IFUCoreDrive.ConnectDrives[outDrs, outSh];
IF desc.inSBCT  =NIL THEN desc.inSBCT ← CoreGlue.CellProc[t: conn, r: conn];
IF desc.inDrCT  =NIL
THEN desc.inDrCT ← IFUCoreDrive.DrivesToFrame[desc.name.Cat["InDr"], desc.inDrs];
IF desc.outDrCT  =NIL
THEN desc.outDrCT ← IFUCoreDrive.DrivesToFrame[desc.name.Cat["OutDr"], desc.outDrs];
RegisterSimulationProcs[desc];
valid ← TRUE};
ifuCoreCtlPLADesc: ATOM = CoreProperties.RegisterProperty[prop: $IFUCoreCtlPLADesc];
gnd: NAT ← 0; GND: ROPE ← CoreName.RopeNm["GND"];
vdd: NAT ← 1; VDD: ROPE ← CoreName.RopeNm["VDD"];
in:  NAT ← 2;
out: NAT ← 3;
FormatSignalName: PROC[format: REFBit.Format, bit: INT, not: BOOL, ph: Ph]
RETURNS[signal: ROPE] = {
name, nameInv: ROPE;
dual, inverted: BOOL;
cy, idx:  INT;
[name, nameInv, dual, inverted, cy, idx] ← CoreName.NormalFormatNames[format[bit]];
Ok, This proc should probably be using something in desc (they are ordered by fromat) rather than the format;
IF inverted THEN drive.in.pol ← SELECT drive.in.pol
FROM pos=>neg, neg=>pos, ENDCASE=>ERROR;
[inv, name] ← CoreName.SelectName[(relSig.pol=neg)#inv, drive.name, drive.nameInv];
name ← CoreName.SigName[[inv, name, relSig.ph, drive.cy, drive.idx]]};
signal ← CoreName.RopeNm[ CoreName.NormalFormatNames[format[bit]];
[not, format[bit].name, format[bit].nameInv, ph]] };
RegisterSimulationProcs: PROC[desc: PLADescription] = {
gnd:   INT ← 0;
vdd:   INT ← 0;
inCnt:   INT ← 0;
outCnt:  INT ← 0;
recCell: CellType ← CoreFrame.FCT[desc.outBodyCT].cell;
inForm: REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
outForm: REFBit.Format ← REFBit.Desc[desc.ttt.out].bitForm;
table:  HashTable.Table ←
HashTable.Create[equal: HashTable.RopeEqual, hash: HashTable.HashRope];
FOR bit: INT IN [0..inForm.size) DO
name:  ROPE ← FormatSignalName[inForm, bit, FALSE, desc.plaPhs[plaIn]];
nameInv: ROPE ← FormatSignalName[inForm, bit, TRUE, desc.plaPhs[plaIn]];
[ ] ← HashTable.Store[table, name,  NEW[PublicRefRec ← [in, FALSE, bit]]];
[ ] ← HashTable.Store[table, nameInv, NEW[PublicRefRec ← [in, TRUE, bit]]];
inCnt ← inCnt + 2 ENDLOOP;
FOR bit: INT IN [0..outForm.size) DO
name:  ROPE ← FormatSignalName[outForm, bit, FALSE, desc.plaPhs[drOutClk]];
nameInv: ROPE ← FormatSignalName[outForm, bit, TRUE,  desc.plaPhs[drOutClk]];
IF desc.plaType=precharged
THEN [] ← HashTable.Store[table, nameInv, NEW[PublicRefRec ← [in, TRUE, bit]]]
ELSE [] ← HashTable.Store[table, name,  NEW[PublicRefRec ← [in, FALSE, bit]]];
outCnt ← outCnt + 1 ENDLOOP;
desc.xlatePublic ← NEW[XlatePubSeqRec[recCell.public.size]];
IF recCell.public.size # inCnt + outCnt + 2 THEN Signal[];
FOR pub: NAT IN [0..recCell.public.size) DO
wireNm: ROPE ← CoreName.WireNm[recCell.public[pub]].n;
ref: REF PublicRefRec;
SELECT wireNm FROM
GND  => {ref←NIL; gnd ← pub; LOOP};
VDD  => {ref←NIL; vdd ← pub; LOOP};
ENDCASE => {
ref ← NARROW[HashTable.Fetch[table, wireNm].value];
IF ref=NIL THEN Signal[]};
desc.xlatePublic[pub] ← ref;
ENDLOOP;
[] ← Ports.InitPort[wire: recCell.public[gnd]];
[] ← Ports.InitPort[wire: recCell.public[vdd]];
[] ← Rosemary.SetFixedWire[recCell.public[vdd], H];
[] ← Rosemary.SetFixedWire[recCell.public[gnd], L];
FOR pub: NAT IN [0..recCell.public.size) DO
IF desc.xlatePublic[pub]#NIL THEN IF desc.xlatePublic[pub].dir=in
THEN [] ← Ports.InitPort[wire: recCell.public[pub], initType: b, initDrive: none]
ELSE [] ← Ports.InitPort[wire: recCell.public[pub], initType: b, initDrive: drive];
ENDLOOP;
[] ← Rosemary.BindCellType[
cellType:   recCell,
roseClassName: Rosemary.Register[
roseClassName: desc.name.Cat["Sim"],
init:    PLAInitProc,
evalSimple:  PLAEvalProc] ];
CoreProperties.PutCellTypeProp[on: recCell, prop: ifuCoreCtlPLADesc, value: desc];
[] ← Rosemary.AddCutSets[cellType: recCell, cs1: "JustAboveTransistors"]};
PLAInitProc: Rosemary.InitProc ~
{RETURN[CoreProperties.GetCellTypeProp[from: cellType, prop: ifuCoreCtlPLADesc]]};
PLAEvalProc: Rosemary.EvalProc ~ {
desc:    PLADescription ← NARROW[stateAny];
inForm:   REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
outForm:   REFBit.Format ← REFBit.Desc[desc.ttt.out].bitForm;
allUndefined: BOOL ← p[vdd].l#H OR p[gnd].l#L;
FOR pub: INT IN [0..p.size) DO
ref: REF PublicRefRec ← desc.xlatePublic[pub];
IF ref#NIL AND ref.dir=in THEN IF ref.inverted
THEN REFBit.Set[desc.ttt.data, ref.index, ~p[pub].b]
ELSE REFBit.Set[desc.ttt.data, ref.index, p[pub].b];
ENDLOOP;
PLAOps.GetOutForData[desc.ttt];
FOR pub: INT IN [0..p.size) DO
ref: REF PublicRefRec ← desc.xlatePublic[pub];
IF ref#NIL AND ref.dir=out THEN IF ref.inverted
THEN p[pub].b ← NOT REFBit.Get[desc.ttt.out, ref.index]
ELSE p[pub].b ←   REFBit.Get[desc.ttt.out, ref.index];
ENDLOOP };
RegisterSimulationProcs: PROC[desc: PLADescription] = {
IndexNames: TYPE = RECORD[index: NAT, name, nameInv: ROPE];
list:   LIST OF IndexNames;
cnt:   NAT ← 0;
recCell: CellType ← CoreFrame.FCT[desc.outBodyCT].cell;
newPub: Core.Wires;
intOnly: Core.Wires;
inForm: REFBit.Format ← REFBit.Desc[desc.ttt.data].bitForm;
outForm: REFBit.Format ← REFBit.Desc[desc.ttt.out].bitForm;
FOR bit: NAT DECREASING IN [0..inForm.size) DO
name:  ROPE ← FormatSignalName[inForm, bit, FALSE, desc.plaPhs[plaIn]];
nameInv: ROPE ← FormatSignalName[inForm, bit, TRUE, desc.plaPhs[plaIn]];
root:  ROPEIF inForm[bit].name#NIL
THEN inForm[bit].name
ELSE inForm[bit].nameInv;
IF IFUCoreDrive.FindDrive[root, desc.inDrs] = NIL
THEN Signal[]
ELSE {cnt ← cnt + 1; list ← CONS[[bit, name, nameInv], list]};
cnt ← cnt + 1; list ← CONS[[bit, name, nameInv], list];
ENDLOOP;
desc.xlateIn ← NEW[XsFormSeqRec[cnt]];
FOR bit: NAT DECREASING IN [0..cnt) DO
desc.xlateIn[bit] ← list.first.index;
newPub   ← CONS[CoreOps.CreateWires[0, list.first.name],  newPub];
newPub   ← CONS[CoreOps.CreateWires[0, list.first.nameInv], newPub];
list ← list.rest;
ENDLOOP;
list←NIL; cnt ← 0;
FOR bit: NAT DECREASING IN [0..outForm.size) DO
name:  ROPE ← FormatSignalName[outForm, bit, FALSE, desc.plaPhs[drOutClk]];
nameInv: ROPE ← FormatSignalName[outForm, bit, TRUE, desc.plaPhs[drOutClk]];
root:  ROPEIF outForm[bit].name#NIL
THEN outForm[bit].name
ELSE outForm[bit].nameInv;
IF IFUCoreDrive.FindDrive[root, desc.outDrs] = NIL
THEN Signal[]
ELSE {cnt ← cnt + 1; list ← CONS[[bit, name, nameInv], list]};
ENDLOOP;
desc.xlateOut  ← NEW[XsFormSeqRec[cnt]];
FOR bit: NAT DECREASING IN [0..cnt) DO
desc.xlateOut[bit] ← list.first.index;
IF desc.plaType=precharged
THEN {
newPub ← CONS[CoreOps.CreateWires[0, list.first.nameInv],  newPub];
intOnly ← CONS[CoreOps.CreateWires[0, list.first.name],   intOnly]}
ELSE {
newPub ← CONS[CoreOps.CreateWires[0, list.first.name],   newPub];
intOnly ← CONS[CoreOps.CreateWires[0, list.first.nameInv],  intOnly]};
list ← list.rest;
ENDLOOP;
newPub ← CONS[CoreOps.CreateWires[0, GND], newPub];
newPub ← CONS[CoreOps.CreateWires[0, VDD], newPub];
recCell ← CoreCreate.Cell[
public:  CoreOps.CreateWire[newPub],
onlyInternal: CoreOps.CreateWire[intOnly],
instances:  LIST[ CoreCreate.Instance[recCell]] ];
CoreBlock.PutCellSide[recCell, left];
CoreBlock.MergeSides[recCell];
PWC.SetAbutX[recCell];
[] ← Ports.InitPort[wire: recCell.public[gnd], initType: l];
[] ← Ports.InitPort[wire: recCell.public[vdd], initType: l];
[] ← Ports.InitPort[wire: recCell.public[in], initType: composite];
[] ← Ports.InitPort[wire: recCell.public[out], initType: composite, initDrive: drive];
FOR bit: NAT IN [0..recCell.public[in].size) DO
[] ← Ports.InitPort[wire: recCell.public[in][bit], initType: l] ENDLOOP;
FOR bit: NAT IN [0..recCell.public[out].size) DO
[] ← Ports.InitPort[wire: recCell.public[out][bit], initType: l, initDrive: drive] ENDLOOP;
[] ← Rosemary.BindCellType[
cellType:   recCell,
roseClassName: Rosemary.Register[
roseClassName: desc.name.Cat["Sim"],
init:    PLAInitProc,
evalSimple:  PLAEvalProc] ];
CoreProperties.PutCellTypeProp[on: recCell, prop: ifuCoreCtlPLADesc, value: desc];
[] ← Rosemary.AddCutSets[cellType: recCell, cs1: "JustAboveTransistors"]};
BuildConnTranslationArray: PROC [desc: PLADescription ] = {
index: INT ← -1;
smlOutNames: LIST OF ROPE;
log.PutRope["\n Building pla translation array"];
desc.connSeq will contain indexes relative to the big (original) PLA
desc.connSeq ← NEW[IFUCoreCtl.ConnSeq[Lists.ListLength[desc.drSignalOrder]]];
FOR list: LIST OF ROPE ← desc.drSignalOrder, list.rest WHILE list#NIL DO
pos: INT ← Lists.ListItemIndex[desc.plaInNames, list.first];
index ← index+1;
IF pos#-1 THEN {
desc.connSeq[index] ← [index: pos/2, isOutput: FALSE, isLeftSide: (pos MOD 2 = 0)];
LOOP};
pos ← Lists.ListItemIndex[desc.plaOutNames, list.first];
IF pos=-1 THEN ERROR; -- Signal name not found;
smlOutNames ← CONS[list.first, smlOutNames];
desc.connSeq[index] ← [index: pos, isOutput: TRUE, isLeftSide: FALSE];
ENDLOOP;
smlOutNames  ← Lists.ReverseList[smlOutNames];
desc.smlToBigOut ← NEW[IFUCoreCtl.XsFormSeqRec[Lists.ListLength[smlOutNames]]];
FOR i: CARDINAL IN [0..desc.smlToBigOut.size) DO
desc.smlToBigOut[i] ←
Lists.ListItemIndex[desc.plaOutNames, Lists.ListIndexItem[smlOutNames, i]]
ENDLOOP;
desc.plaOutNames ← smlOutNames;
FOR index: INT IN [0..desc.connSeq.size) DO
desc.connSeq[index].dr ← desc.outDrs.first; desc.outDrs ← desc.outDrs.rest ENDLOOP;
IF desc.outDrs#NIL THEN Signal};
log: IO.STREAM ← CoreFrame.GetLog[];
END.