IFUCoreDriveImpl:
CEDAR
PROGRAM
IMPORTS CDDirectory, CoreBlock, CoreFrame, CoreInstCell, CoreIOIFUProps, CoreLibrary, CoreName, CoreOps, CoreProperties, IFUCoreCells, IO, PW, REFBit, Rope
EXPORTS IFUCoreDrive =
BEGIN
ROPE: TYPE = Core.ROPE;
CellType: TYPE = Core.CellType;
Wire: TYPE = Core.Wire;
PLAType: TYPE = IFUCoreDrive.PLAType;
Drive: TYPE = IFUCoreDrive.Drive;
Drives: TYPE = IFUCoreDrive.Drives;
DriveRec: TYPE = IFUCoreDrive.DriveRec;
DrNmType: TYPE = IFUCoreDrive.DrNmType;
RowType: TYPE = IFUCoreDrive.RowType;
Dir: TYPE = IFUCoreDrive.Dir;
DrGate: TYPE = IFUCoreDrive.DrGate;
Ph: TYPE = IFUCoreDrive.Ph;
Polarity: TYPE = IFUCoreDrive.Polarity;
DrTileRec: TYPE = IFUCoreDrive.DrTileRec;
DrTileNonConn: TYPE = IFUCoreDrive.DrTileNonConn;
DrTileConn: TYPE = IFUCoreDrive.DrTileConn;
DrTileArray: TYPE = IFUCoreDrive.DrTileArray;
DriveTileType: TYPE = IFUCoreDrive.DriveTileType;
Signal: SIGNAL = CODE;
driveCellClass:
PUBLIC Core.CellClass ←
CoreOps.SetClassPrintProc[
NEW[Core.CellClassRec ← [name: "IFUCoreDrive", recast: NIL]],
ClassPrintProc];
ClassPrintProc: CoreOps.PrintClassProc = {
drData: Drive ← NARROW[data];
IO.PutF[out, "\nDriver: %g", IO.rope[ DrRope[drData] ] ] };
DrShiftInProp: PROC RETURNS[ATOM] = {RETURN[CoreIOIFUProps.drShiftIn]};
DrShiftOutProp: PROC RETURNS[ATOM] = {RETURN[CoreIOIFUProps.drShiftOut]};
SetDShiftIO:
PUBLIC
PROC[cellType: CellType, sIn, sOut:
ROPE] = {
CoreProperties.PutCellTypeProp[cellType, DrShiftInProp[], sIn];
CoreProperties.PutCellTypeProp[cellType, DrShiftOutProp[], sOut]};
GetDShiftIO:
PUBLIC
PROC[cellType: CellType]
RETURNS [sIn, sOut:
ROPE] = {
sIn ← NARROW[CoreProperties.GetCellTypeProp[cellType, DrShiftInProp[] ]];
sOut ← NARROW[CoreProperties.GetCellTypeProp[cellType, DrShiftOutProp[] ]]};
CellProc:
PUBLIC
PROC [
name: ROPE ← NIL,
data: Drive ←
NIL ]
RETURNS [cellType: CellType] = {
cellType ← CoreOps.SetCellTypeName[
NEW [ Core.CellTypeRec ← [
class: driveCellClass,
public: CoreOps.CreateWires[0],
data: data] ],
name];
CoreFrame.SetFrameExpandProc[soft, cellType, NEW[CoreFrame.ExpandProc ← Expand] ];
CoreFrame.SetFrameExpandProc[hard, cellType, NEW[CoreFrame.ExpandProc ← Expand] ]};
Expand: CoreFrame.ExpandProc = {
drive: Drive ← NARROW[frameCT.data];
frame: REF CoreFrame.FrameRec ← NEW[CoreFrame.FrameRec ← [first: left]];
genericDriver: CellType ← GetGenericDriver[drive];
driverName: ROPE ← DriveName[drive, out];
renameProc: CoreInstCell.RenameProc = {new ← SpecificNames[old, drive]};
frame.cell ← CoreInstCell.SpecificGeneric[genericDriver, renameProc];
frame.seq ← NEW[CoreFrame.FrameSeq[0]];
frameCT.data ← frame;
frameCT.class ← CoreFrame.frameCellClass;
CoreFrame.SetFrameExpandProc[soft, frameCT, NIL];
CoreFrame.SetFrameExpandProc[hard, frameCT,
NIL]};
OldExpand: CoreFrame.ExpandProc = {
drive: Drive ← NARROW[frameCT.data];
frame: REF CoreFrame.FrameRec ← NEW[CoreFrame.FrameRec ← [first: left]];
public: CoreName.Context ← CoreName.NewContext[];
genericDriver: CellType ← GetGenericDriver[drive];
driverName: ROPE ← DriveName[drive, out];
pas: LIST OF CoreCreate.PA;
eachWire: CoreOps.EachWireProc = {
specificName: ROPE;
specific: Wire;
IF wire.size#0 THEN RETURN;
specificName ← SpecificNames[CoreName.WireNm[wire].n, drive ];
IF specificName=NIL THEN Signal[];
specific ← CoreName.CtxWire[public, specificName ];
pas ← CONS[ [wire, specific], pas]};
[ ] ← CoreOps.VisitWire[genericDriver.public, eachWire];
frame.cell ← CoreCreate.Cell[
public: CoreName.WireFromCtx[public],
onlyInternal: NIL,
instances: LIST[CoreCreate.InstanceList[genericDriver, pas]],
name: driverName ];
public ← CoreName.KillContext[public];
CoreBlock.PutCellSide[frame.cell, CoreFrame.SideSides[frame.first]];
CoreBlock.MergeSides[frame.cell];
PWC.SetAbutX[frame.cell];
frame.seq ← NEW[CoreFrame.FrameSeq[0]];
frameCT.data ← frame;
frameCT.class ← CoreFrame.frameCellClass;
CoreFrame.SetFrameExpandProc[soft, frameCT, NIL];
CoreFrame.SetFrameExpandProc[hard, frameCT, NIL]};
GetGenericDriver:
PROC[drive: Drive]
RETURNS[genericDriver: CellType] = {
basicDrName, drName: ROPE;
decoderOut:
BOOL ← FALSE;
drive.plaType=decoder AND drive.drRowType=conn AND drive.drDir=out;
library: CoreLibrary.Library ← IFUCoreCells.library;
drTiles: REF DrTileRec ← GetDriverTiles[];
IF drive.drRowType#conn
THEN
RETURN[drTiles.nconn[drive.plaType][drive.drRowType]];
IF drive.drRowType#conn THEN {
plaType: PLAType ←
SELECT drive.plaType FROM hot, precharged => drive.plaType, ENDCASE => static;
RETURN[drTiles.nconn[plaType][drive.drRowType]]};
basicDrName ← GenericDriverName[drive];
drName ←
IF decoderOut
THEN Rope.Cat["D", basicDrName]
ELSE basicDrName;
genericDriver ← CoreLibrary.Get[library, basicDrName];
IF genericDriver=
NIL
THEN {
Inst: PROC[type: DriveTileType] = {cells ← CONS[ drTiles.conn[drive.drDir][type], cells]};
cells: LIST OF CellType ← NIL;
IF drive.ref.ph=unk
-- Debug driver, clears node on either phase
THEN {Inst[inBlank]; Inst[gndAB]}
ELSE {
IF drive.ref.pol=drive.in.pol
THEN Inst[inPos]
ELSE Inst[inNeg];
IF drive.ref.ph=A
THEN Inst[latchA]
ELSE Inst[latchB]};
Inst[latch];
SELECT drive.gate
FROM
pos => Inst[gateP];
neg => Inst[gateN];
negAc => Inst[gateNA];
negBc => Inst[gateNB];
ENDCASE => ERROR;
IF drive.dualOut
THEN {
IF (drive.ref.pol=drive.out.pol)=(drive.gate=pos)
THEN Inst[posDual]
ELSE Inst[negDual]}
ELSE
IF (drive.ref.pol=drive.out.pol)=(drive.gate=pos)
THEN Inst[posSing]
ELSE Inst[negSing];
genericDriver ← CoreBlock.AbutCellList
[basicDrName, (IF drive.drDir=out THEN right ELSE left), cells];
CoreLibrary.Set[library, basicDrName, genericDriver]};
genericDriver ← CoreLibrary.Get[library, drName];
IF genericDriver=
NIL
THEN Signal[] };
IF genericDriver=NIL THEN {
genericDriver ← CoreBlock.AbutCellList[drName, top, LIST[
CoreLibrary.Get[library, basicDrName],
drTiles.nconn[decoder][blank] ] ];
CoreLibrary.Set[library, drName, genericDriver]} };
inRp: ROPE ← CoreName.RopeNm["in"];
ioRp: ROPE ← CoreName.RopeNm["io"];
outRp: ROPE ← CoreName.RopeNm["out"];
out0Rp: ROPE ← CoreName.RopeNm["out0"];
out1Rp: ROPE ← CoreName.RopeNm["out1"];
dShDataRp: ROPE ← CoreName.RopeNm["DShData"];
dShDataInRp: ROPE ← CoreName.RopeNm["DShDataIn"];
dShDataOutRp: ROPE ← CoreName.RopeNm["DShDataOut"];
fire: ROPE ← CoreName.RopeNm["Fire"];
fireV: ROPE ← CoreName.RopeNm["FireControlV"];
nPreChg: ROPE ← CoreName.RopeNm["NotPreChg"];
SpecificNames:
PUBLIC
PROC[generic:
ROPE, drive: Drive]
RETURNS [specific: ROPE] = {
specific ←
SELECT generic
FROM
inRp => DriveName[drive,in],
out0Rp => DriveName[drive,out],
out1Rp => IF ~drive.dualOut THEN NIL ELSE DriveName[drive,nout],
dShDataRp =>
SELECT
TRUE
FROM
drive.inSh=NIL AND drive.outSh=NIL => CoreName.ID[generic],
drive.inSh = drive.outSh => drive.inSh,
drive.inSh#NIL AND drive.outSh=NIL => drive.inSh,
drive.inSh=NIL AND drive.outSh#NIL => drive.outSh,
ENDCASE => ERROR,
dShDataInRp => IF drive.inSh=NIL THEN CoreName.ID[generic] ELSE drive.inSh,
dShDataOutRp => IF drive.outSh=NIL THEN CoreName.ID[generic] ELSE drive.outSh,
fire => drive.fire,
fireV => drive.fireV,
nPreChg => drive.nPreChg,
ENDCASE => generic;
IF specific#NIL THEN specific ← CoreName.RopeNm[specific]};
tileBuffer: REF DrTileRec ← NIL;
GetDriverTiles:
PUBLIC PROC
RETURNS[tiles:
REF DrTileRec] = {
Get:
PROC[name:
ROPE]
RETURNS[cell: CellType] =
{cell ← CoreLibrary.Get[library, name]};
FlipY:
PROC[ref:
ROPE]
RETURNS[cell: CellType] = {
name: ROPE ← CoreName.RopeNm[ref.Cat["FlipY"]];
obj: CD.Object ← CDDirectory.Fetch[library.design, ref].object;
cell ← CoreLibrary.Get[library, name];
IF cell#NIL THEN RETURN[cell];
cell ← CoreLibrary.ObjCell[PW.FlipY[obj], name];
CoreLibrary.Set[library, name, cell]};
FlipX:
PROC[ref:
ROPE]
RETURNS[cell: CellType] = {
name: ROPE ← CoreName.RopeNm[ref.Cat["FlipX"]];
obj: CD.Object ← CDDirectory.Fetch[library.design, ref].object;
cell ← CoreLibrary.Get[library, name];
IF cell#NIL THEN RETURN[cell];
cell ← CoreLibrary.ObjCell[PW.FlipX[obj], name];
CoreLibrary.Set[library, name, cell]};
driveTop: CellType;
driveBot: CellType;
library: CoreLibrary.Library ← IFUCoreCells.library;
IF tileBuffer # NIL THEN RETURN[tileBuffer];
log.PutRope["\n Initialize drive tiles"];
tiles ← tileBuffer ← NEW[DrTileRec];
tiles.conn[in] ← NEW[DrTileArray];
tiles.conn[out] ← NEW[DrTileArray];
tiles.nconn [precharged][header] ← Get[ "DrHead" ];
tiles.nconn [precharged][xheader] ← Get[ "DrXHead"];
tiles.nconn [precharged][extend] ← Get[ "DrExtend" ];
tiles.nconn [precharged][blank] ← Get[ "DrBlank" ];
tiles.nconn [precharged][dataUp] ← tiles.nconn [precharged][blank];
tiles.nconn [precharged][dataDn] ← tiles.nconn [precharged][blank];
tiles.nconn [precharged][footer] ← FlipY[ "DrHead"];
tiles.nconn [precharged][xfooter] ← FlipY[ "DrXHead"];
tiles.nconn [hot][header] ← Get[ "HPlaDrHead" ];
tiles.nconn [hot][xheader] ← Get[ "DrXHead"];
tiles.nconn [hot][extend] ← Get[ "DrExtend" ];
tiles.nconn [hot][blank] ← Get[ "DrBlank" ];
tiles.nconn [hot][dataUp] ← tiles.nconn [hot][blank];
tiles.nconn [hot][dataDn] ← tiles.nconn [hot][blank];
tiles.nconn [hot][footer] ← FlipY[ "HPlaDrHead"];
tiles.nconn [hot][xfooter] ← FlipY[ "DrXHead"];
tiles.nconn [static][header] ← Get[ "SPlaDrHead" ];
tiles.nconn [static][xheader] ← Get[ "DrXHead" ];
tiles.nconn [static][extend] ← Get[ "DrExtend" ];
tiles.nconn [static][blank] ← Get[ "SPlaDrBlank24" ];
tiles.nconn [static][dataUp] ← tiles.nconn [static][blank];
tiles.nconn [static][dataDn] ← tiles.nconn [static][blank];
tiles.nconn [static][footer] ← FlipY[ "SPlaDrHead"];
tiles.nconn [static][xfooter] ← FlipY[ "DrXHead"];
tiles.nconn [decoder][blank] ← Get[ "DPlaDrBlank6" ]; --1 use
tiles.conn [in][inPos] ← FlipX[ "DrIn2" ];
tiles.conn [in][inNeg] ← FlipX[ "DrIn1" ];
tiles.conn [in][inBlank] ← FlipX[ "DrIn0" ];
tiles.conn [in][gndAB] ← FlipX[ "DrGateGnd" ];
tiles.conn [in][latchA] ← FlipX[ "DrGatePassA" ];
tiles.conn [in][latchB] ← FlipX[ "DrGatePassB" ];
tiles.conn [in][latch] ← Get[ "DrLatch" ];
tiles.conn [in][gateP] ← Get[ "DrGatePass" ];
tiles.conn [in][gateN] ← Get[ "DrGateInv" ];
tiles.conn [in][gateNA] ← Get[ "DrGateNandA" ];
tiles.conn [in][gateNB] ← Get[ "DrGateNandB" ];
tiles.conn [in][posSing] ← Get[ "DrPosSing" ];
tiles.conn [in][negSing] ← Get[ "DrNegSing" ];
tiles.conn [in][posDual] ← Get[ "DrPosDual" ];
tiles.conn [in][negDual] ← Get[ "DrNegDual" ];
tiles.conn [out][inPos] ← Get[ "DrIn2" ];
tiles.conn [out][inNeg] ← Get[ "DrIn1" ];
tiles.conn [out][inBlank] ← Get[ "DrIn0" ];
tiles.conn [out][gndAB] ← Get[ "DrGateGnd" ];
tiles.conn [out][latchA] ← Get[ "DrGatePassA" ];
tiles.conn [out][latchB] ← Get[ "DrGatePassB" ];
tiles.conn [out][latch] ← Get[ "DrLatch" ];
tiles.conn [out][gateP] ← FlipX[ "DrGatePass" ];
tiles.conn [out][gateN] ← FlipX[ "DrGateInv" ];
tiles.conn [out][gateNA] ← FlipX[ "DrGateNandA" ];
tiles.conn [out][gateNB] ← FlipX[ "DrGateNandB" ];
tiles.conn [out][posSing] ← FlipX[ "DrPosSing" ];
tiles.conn [out][negSing] ← FlipX[ "DrNegSing" ];
tiles.conn [out][posDual] ← FlipX[ "DrPosDual" ];
tiles.conn [out][negDual] ← FlipX[ "DrNegDual" ];
driveTop ← CoreLibrary.Get[library, "DrTop"];
driveBot ← CoreFrame.RotateCellType[driveTop, mirrorY];
CoreLibrary.Set[library, "DrBot", driveBot];
RETURN[tiles]};
DrRope:
PROC[rec: Drive]
RETURNS[rope:
ROPE] = {
dirRope: ARRAY Dir OF ROPE = [" in", "out"];
polRope: ARRAY Polarity OF ROPE = ["pos", "neg", "unk"];
phRope: ARRAY Ph OF ROPE ← CoreName.PhRope;
gateRope: ARRAY DrGate OF ROPE = [" neg", "negAc", "negBc", " pos"];
dualSing: ARRAY BOOL OF ROPE = ["sing", "dual"];
rowType:
ARRAY RowType
OF
ROPE=
["Header", "Xheader", "Footer", "Xfooter", "Conn", "DataUp", "DataDn", "Blank", "Extend"];
SELECT rec.drRowType
FROM
conn => {
rope ←
IO.PutFR["%3g %12g %12g",
IO.rope[dirRope[rec.drDir]],
IO.rope[rec.name],
IO.rope[rec.nameInv] ];
rope ← rope.Cat[
IO.PutFR[" %g.%g",
IO.int[rec.cy],
IO.int[rec.idx] ] ];
rope ← rope.Cat[
IO.PutFR[" %g",
IO.rope[rec.inNm] ] ];
rope ← rope.Cat[
IO.PutFR[" %g%g %g%g",
IO.rope[polRope [rec.in.pol]],
IO.rope[phRope [rec.in.ph]],
IO.rope[polRope [rec.ref.pol]],
IO.rope[phRope [rec.ref.ph]] ] ];
rope ← rope.Cat[
IO.PutFR[" %g %g %g%g",
IO.rope[gateRope [rec.gate]],
IO.rope[dualSing [rec.dualOut]],
IO.rope[polRope [rec.out.pol]],
IO.rope[phRope [rec.out.ph]] ] ]};
ENDCASE => rope ← rowType[rec.drRowType]};
DriverFill: PUBLIC PROC RETURNS[frame: Frame] = {
frame ← CDF.NewFrame[2, x, CDF.ID["DriverFill"]];
frame[0] ← CDF.Glue[];
frame[1] ← CDF.NewObjectFrame[DriverCell[static, extend]]};
DriverExt: PUBLIC PROC[up: BOOL ← FALSE] RETURNS[frame: Frame] = {
frame ← CDF.NewFrame[2, x, CDF.ID["DriverFill"]];
frame[0] ← IF up THEN CDF.Glue[t:ext, b:conn] ELSE CDF.Glue[t:conn, b:ext];
frame[1] ← CDF.NewObjectFrame[DriverCell[static, extend]]};
BuildDrivers: PUBLIC PROC[frame: Frame, design: CD.Design] = {
IF frame.seqSize > 0
THEN FOR index: INT IN [0..frame.seqSize)
DO BuildDrivers[frame[index], design] ENDLOOP
ELSE {
drive: Drive ← NARROW[frame.data];
frame.data ← DriverCell[static, conn, drive, design];
frame.shell ← CDF.ShellFromObject[NARROW[frame.data]]} };
GenericDriverName:
PUBLIC
PROC[drive: Drive]
RETURNS[name:
ROPE] = {
IF drive.out.ph=Ac THEN drive.gate ← negAc;
IF drive.out.ph=Bc THEN drive.gate ← negBc;
name ← "Drive";
name ← name.Cat[IF drive.drDir = in THEN "In" ELSE "Out"];
name ← name.Cat[IF drive.ref.pol=drive.in.pol THEN "Pos" ELSE "Neg"];
name ← name.Cat[
SELECT drive.ref.ph
FROM A => "A", B => "B", unk => "GndAB", ENDCASE => ERROR];
name ← name.Cat[
SELECT drive.gate
FROM
neg => "Neg",
negAc => "NAc",
negBc => "NBc",
pos => "",
ENDCASE => ERROR];
name ← name.Cat[
IF (drive.ref.pol=drive.out.pol)=(drive.gate=pos) THEN "Pos" ELSE "Neg"];
name ← name.Cat[IF drive.dualOut THEN "Dual" ELSE "Sing"]};
CapDrives:
PUBLIC PROC[drives: Drives, sIn, altOut:
ROPE ←
NIL]
RETURNS[newDrives: Drives, sOut: ROPE ← NIL] = {
sOut ← ConnectDrives[drives, sIn];
newDrives ← CONS[NEW[DriveRec ← [drRowType: xfooter, inSh: sIn, outSh: sIn]], drives];
FOR drives ← newDrives, drives.rest WHILE drives.rest#NIL DO ENDLOOP;
sOut ← IF altOut#NIL THEN altOut ELSE drives.first.outSh;
drives.first.outSh ← sOut;
drives.rest ← CONS[NEW[DriveRec ← [drRowType: xheader, inSh: sOut, outSh: sOut]], NIL]};
RefToDriverFrame:
PUBLIC
PROC[name:
ROPE, refRec:
REF, initial: DriveRec]
RETURNS[cell: CellType, outSh: ROPE]= {
top, bot: Drive;
drName:
ROPE ←
IF initial.drDir = in
THEN name.Cat["In"]
ELSE name.Cat["Out"];
[cell, outSh] ← RefToDriverFrameBasic[drName, refRec, initial];
top ← NEW[DriveRec ← [drRowType: xheader, inSh: outSh, outSh: outSh]];
bot ← NEW[DriveRec ← [drRowType: xfooter, inSh: initial.inSh, outSh: initial.inSh]];
cell ← CoreFrame.NewFrameCells[
name: name,
rec: [first: top],
cells:
LIST[
CellProc[name: DrRope[top], data: top],
cell,
CellProc[name: DrRope[bot], data: bot] ] ] };
RefToDriverFrameBasic:
PUBLIC
PROC [name:
ROPE, refRec:
REF, initial: DriveRec]
RETURNS[cell: CellType, outSh: ROPE]= {
drives: Drives ← RefToDrives[refRec, initial];
outSh ← ConnectDrives[drives];
cell ← DrivesToFrame[name, drives]};
RefToDrives:
PUBLIC
PROC [refRec:
REF, initial: DriveRec]
RETURNS[drives: Drives]= {
dualOut: BOOL ← FALSE;
bitForm: REFBit.Format ← REFBit.Desc[refRec].bitForm;
FOR bit:
INT
DECREASING
IN [0..bitForm.size)
DO
inverted: BOOL;
drive: Drive ← NEW[DriveRec ← initial];
[drive.name, drive.nameInv, dualOut, inverted, drive.cy, drive.idx] ←
CoreName.NormalFormatNames[bitForm[bit]];
drive.dualOut ← initial.dualOut OR dualOut;
IF inverted
THEN drive.in.pol ←
SELECT drive.in.pol
FROM pos=>neg, neg=>pos, ENDCASE=>ERROR;
drive.outSh ← DriveName[drive, outSh];
drives ← CONS[drive, drives];
ENDLOOP};
NormalFormatNames
name #NIL
nameInv =NIL <=> dual FALSE
NotFoo becomes Foo with inverted=TRUE
LatchPh:
PUBLIC
PROC[ph: Ph]
RETURNS[latch: Ph] = {
latch ←
SELECT ph
FROM
A, AB, ABB, ABBB, Bc => A,
B, BA, BAA, BAAA, Ac => B,
ENDCASE => unk};
LatchedPh:
PUBLIC
PROC[latch, ph: Ph]
RETURNS[Ph] = {
RETURN[
SELECT ph
FROM
A => SELECT latch FROM A => AB, ENDCASE => ERROR,
AB => SELECT latch FROM A => ABB, ENDCASE => BA,
ABB => SELECT latch FROM A => ABBB, ENDCASE => BA,
ABBB => SELECT latch FROM A => ERROR, ENDCASE => BA,
B => SELECT latch FROM A => ERROR, ENDCASE => BA,
BA => SELECT latch FROM A => AB, ENDCASE => BAA,
BAA => SELECT latch FROM A => AB, ENDCASE => BAAA,
BAAA => SELECT latch FROM A => AB, ENDCASE => ERROR,
ENDCASE => ERROR]};
Driver Configurations generated by SpecificDrive
polarities
Input > clk Ouput in ref out
Core To Control or Core To Pad (input)
Positive inv > inv pos inv pos
Negative inv-inv > inv inv inv pos
Control To Core or Pad To Core (output)
Positive UnClocked inv > pos inv pos inv pos
Negative UnClocked inv > inv inv inv pos pos
Positive Clocked inv-inv > invClk inv pos pos pos
Negative Clocked inv > invClk inv pos inv pos
SpecificDrive:
PUBLIC PROC[dir: Dir, in:
ROPE, out:
ROPE, inverted, dual:
BOOL ← FALSE]
RETURNS[dr: IFUCoreDrive.Drive] = {
sigIn: CoreName.SigRec ← CoreName.NameSig[in];
sigOut: CoreName.SigRec ← CoreName.NameSig[out];
clocked: BOOL ← SELECT sigOut.ph FROM Ac, Bc=>TRUE, ENDCASE=>FALSE;
IF sigOut.not THEN Signal[]; -- This is thrown away! Output name is computed.
dr
← NEW[ IFUCoreDrive.DriveRec ← [
name: sigOut.root,
inNm: in,
drDir: dir,
gate: SELECT sigOut.ph FROM Ac=>negAc, Bc=>negBc, ENDCASE=>pos,
idx: sigOut.idx,
cy: sigOut.cy,
dualOut: dual,
in: [ph: sigIn.ph ],
ref: [ph: LatchPh[ sigOut.ph ] ],
out: [ph: sigOut.ph, pol: pos ] ]];
IF dr.ref.ph=unk
THEN
IF dir=in
THEN {dr^ ← [sigOut.root, NIL, , , dir, pos, , ,,,,, , [pos], [pos], [pos], , ]; RETURN[dr]}
ELSE {dr^ ← [sigOut.root, NIL, , , dir, neg, , ,,,,, , [pos], [pos], [pos], , ]; RETURN[dr]};
SELECT dir
FROM
in => {
IF ~inverted
THEN {dr.in.pol ← pos; dr.ref.pol ← neg}
ELSE {dr.in.pol ← neg; dr.ref.pol ← neg};
IF clocked THEN Signal[]}; -- not possible
out =>
SELECT
TRUE
FROM
~inverted AND ~clocked => {dr.in.pol ← pos; dr.ref.pol ← neg; dr.gate ← pos};
inverted AND ~clocked => {dr.in.pol ← neg; dr.ref.pol ← pos; dr.gate ← neg};
~inverted AND clocked => {dr.in.pol ← pos; dr.ref.pol ← pos};
inverted AND clocked => {dr.in.pol ← pos; dr.ref.pol ← neg};
ENDCASE => ERROR;
ENDCASE};
AdjustDriveInPhRef:
PUBLIC
PROC[inLatchPh: Ph, drives: Drives, names:
ROPE] = {
lastDr: Drive ← NIL;
ris: IO.STREAM ← IO.RIS[names];
DO
drive: Drive;
signal: CoreName.SigRec;
item: ROPE ← ris.GetTokenRope[! IO.EndOfStream => EXIT].token;
IF item.Fetch[] = '←
THEN {
item ← ris.GetTokenRope[].token;
signal ← CoreName.NameSig[item];
drive ← lastDr;
lastDr ← NIL}
ELSE {
signal ← CoreName.NameSig[item];
drive ← lastDr ← FindSignalDrive[signal, drives]};
drive.name ← signal.root;
drive.idx ← signal.idx;
drive.cy ← signal.cy;
drive.ref.ph ← inLatchPh;
drive.in.ph ← signal.ph;
drive.out.ph ← LatchedPh[inLatchPh, drive.in.ph];
ENDLOOP };
AdjustDriveOutPh:
PUBLIC
PROC[drives: Drives, names:
ROPE] = {
ris: IO.STREAM ← IO.RIS[names];
DO
drive: Drive;
signal: CoreName.SigRec;
item: ROPE ← ris.GetTokenRope[! IO.EndOfStream => EXIT].token;
signal ← CoreName.NameSig[item];
drive ← FindSignalDrive[signal, drives];
drive.ref.ph ← unk;
drive.out.ph ← unk;
ENDLOOP;
ris ← IO.RIS[names];
DO
drive: Drive;
signal: CoreName.SigRec;
item: ROPE ← ris.GetTokenRope[! IO.EndOfStream => EXIT].token;
signal ← CoreName.NameSig[item];
drive ← FindSignalDrive[signal, drives];
IF signal.not THEN drive.dualOut ← TRUE;
drive.idx ← signal.idx;
drive.cy ← signal.cy;
IF drive.ref.ph#unk AND drive.ref.ph#LatchPh[signal.ph] THEN Signal[];
IF drive.out.ph#unk AND drive.out.ph#signal.ph THEN Signal[];
drive.ref.ph ← LatchPh[signal.ph];
drive.out.ph ← signal.ph;
ENDLOOP};
FindSignalDrive:
PROC[sig: CoreName.SigRec, drives: Drives]
RETURNS[drive: Drive] = {
FOR drives ← drives, drives.rest
WHILE drives #
NIL
DO
IF drives.first.name = sig.root
THEN {
IF drives.first.cy#-1 AND drives.first.cy#sig.cy THEN LOOP;
IF drives.first.idx#-1 AND drives.first.idx#sig.idx THEN LOOP;
RETURN[drives.first]};
IF drives.first.nameInv = sig.root
THEN {
IF drives.first.cy#-1 AND drives.first.cy#sig.cy THEN LOOP;
IF drives.first.idx#-1 AND drives.first.idx#sig.idx THEN LOOP;
RETURN[drives.first]};
ENDLOOP;
drive ← NIL; Signal[]};
ConnectDrives:
PUBLIC
PROC [drives: Drives, inSh:
ROPE ←
NIL]
RETURNS[outSh:
ROPE] = {
outSh ← inSh;
FOR list: Drives ← drives, list.rest
WHILE list#
NIL
DO
list.first.inSh ← IF outSh#NIL THEN outSh ELSE list.first.inSh;
list.first.outSh ← IF list.first.drRowType#conn THEN list.first.inSh ELSE list.first.outSh;
outSh ← list.first.outSh;
ENDLOOP};
DrivesToFrame:
PUBLIC
PROC [name:
ROPE, drives: Drives]
RETURNS[cell: CellType]= {
cnt: INT ← 0;
frame: CoreFrame.Frame;
FOR list: Drives ← drives, list.rest WHILE list#NIL DO cnt ← cnt+1 ENDLOOP;
cell ← CoreFrame.NewFrameCell[cnt, name, [first: bottom]];
frame ← CoreFrame.FCT[cell];
FOR bit:
INT IN [0..cnt)
DO
frame.seq[bit] ← CellProc[DriveName[drives.first, out], drives.first];
drives ← drives.rest ENDLOOP};
DriveName:
PUBLIC
PROC[drive: Drive, type: DrNmType ← unk]
RETURNS[ name:
ROPE] = {
relSig: CoreName.RelativeSignal;
inv: BOOL ← SELECT type FROM nin, nref, nout, ninSh, noutSh=>TRUE, ENDCASE=>FALSE;
IF type=unk THEN type ← IF drive.drDir=in THEN in ELSE out;
SELECT type
FROM
inSh => RETURN[drive.inSh];
outSh => RETURN[CoreName.RopeNm[Rope.Cat["drShOut", DriveName[drive, nref]]]];
ninSh => Signal[]; -- {RETURN[Rope.Cat["Not", drive.inSh]]};
noutSh => Signal[]; -- {RETURN[Rope.Cat["Not", drive.outSh]]};
in => {IF drive.inNm#NIL THEN RETURN[drive.inNm]; relSig ← drive.in};
nin => {IF drive.inNm#NIL THEN Signal[]; relSig ← drive.in};
ref, nref => relSig ← drive.ref;
out, nout => relSig ← drive.out;
ENDCASE => ERROR;
IF drive.drRowType#conn
THEN name ← DrRope[drive]
ELSE {
[inv, name] ← CoreName.SelectName[(relSig.pol=neg)#inv, drive.name, drive.nameInv];
name ← CoreName.SigName[[inv, name, relSig.ph, drive.cy, drive.idx]]};
name ← CoreName.RopeNm[name]};
FindDrive:
PUBLIC
PROC[drives: Drives, name:
ROPE]
RETURNS[drive: Drive] = {
FOR drives ← drives, drives.rest
WHILE drives #
NIL
DO
driveNm: ROPE ← DriveName[drives.first];
IF Rope.Equal[name, DriveName[drives.first]] THEN RETURN[drives.first] ENDLOOP;
RETURN[NIL]};
ReverseDrives:
PUBLIC PROC[drives: Drives]
RETURNS[new: Drives] = {
FOR drives ← drives, drives.rest
WHILE drives#
NIL
DO
new ← CONS[drives.first, new] ENDLOOP};
AddDrive: PUBLIC PROC[drive: Drive, drives: Drives] RETURNS[new: Drives] = {
found: BOOL ← FALSE;
name: ROPE ← IF drive.name # NIL THEN drive.name ELSE drive.nameInv;
FOR drives ← drives, drives.rest WHILE drives # NIL DO
new ← CONS[drives.first, new];
IF Rope.Equal[name, drives.first.name] OR Rope.Equal[name, drives.first.nameInv] THEN
{new ← CONS[drive, new]; found ← TRUE} ENDLOOP;
IF NOT found THEN new ← CONS[drive, new];
new ← ReverseDrives[new]};
ReplaceDrive: PUBLIC PROC[drive: Drive, drives: Drives] RETURNS[new: Drives] = {
found: BOOL ← FALSE;
name: ROPE ← IF drive.name # NIL THEN drive.name ELSE drive.nameInv;
FOR drives ← drives, drives.rest WHILE drives # NIL DO
IF Rope.Equal[name, drives.first.name] OR Rope.Equal[name, drives.first.nameInv]
THEN {new ← CONS[drive, new]; found ← TRUE}
ELSE {new ← CONS[drives.first, new]} ENDLOOP;
IF NOT found THEN Signal[];
new ← ReverseDrives[new]};
DelDrive: PUBLIC PROC[drive: Drive, drives: Drives] RETURNS [new: Drives] = {
found: BOOL ← FALSE;
name: ROPE ← IF drive.name # NIL THEN drive.name ELSE drive.nameInv;
FOR drives ← drives, drives.rest WHILE drives # NIL DO
IF Rope.Equal[name, drives.first.name] OR Rope.Equal[name, drives.first.nameInv]
THEN found ← TRUE
ELSE new ← CONS[drives.first, new] ENDLOOP;
IF NOT found THEN Signal[];
new ← ReverseDrives[new]};
log: IO.STREAM ← CoreFrame.GetLog[];
TestProc: PROC[name: ROPE] = {
cellName: ROPE ← "Testee";
refRec: REF ← name;
initial: DriveRec ← [
name: NIL,
nameInv: NIL,
drDir: in,
gate: pos,
dualOut: FALSE,
inSh: "testShDataIn",
in: [pol: pos, ph: A, cycle: 0],
ref: [pol: pos, ph: A, cycle: 0],
out: [pol: pos, ph: AB, cycle: 0],
pass: FALSE,
plaType: static,
drRowType: conn ];
cell: CellType ← RefToDriverFrame[cellName, refRec, initial].cell;
CoreFrame.Expand[cell];
[ ] ← CoreConnect.Connect[cell];
cell ← CoreOps.Recast[cell];
CoreOps.PrintCellType[cell, log];
[ ] ← PW.Draw[PWC.Layout[cell]] };
TestProc[ "Test.TestRec" ];
END.