IFUSimImpl.mesa
Last Edited by Curry October 24, 1986 10:18:23 am PDT
Don Curry March 31, 1987 4:11:22 pm PST
Last Edited by: Louis Monier February 10, 1987 7:36:47 pm PST
DIRECTORY Convert, Core, CoreCreate, CoreFlat, CoreIO, CoreOps, CoreClasses, CoreName, CoreProperties, FS, HashTable, IFUSim, IO, PLASim, Ports, Rope, Rosemary, TerminalIO;
IFUSimImpl: CEDAR PROGRAM
IMPORTS Convert, CoreClasses, CoreCreate, CoreFlat, CoreName, CoreIO, CoreOps, CoreProperties, FS, HashTable, IFUSim, IO, PLASim, Ports, Rope, Rosemary, TerminalIO
EXPORTS IFUSim =
BEGIN
CellType:  TYPE = Core.CellType;
Properties: TYPE = Core.Properties;
Wire:   TYPE = Core.Wire;
Wires:   TYPE = Core.Wires;
ROPE:   TYPE = Core.ROPE;
Table:   TYPE = HashTable.Table;
Field:   TYPE = REF FieldRec;
FieldRec:  TYPE = RECORD[root: ROPE, wire: Wire, octalIdx: BOOL];
WR:   TYPE = REFNIL;
Context: TYPE = REF ContextRec;
ContextRec: TYPE = RECORD[
name:   ROPE,
cell:   CellType,
public:  Wire,
publics:  Wires,
internals:  Wires, -- publics with no actuals
regPubs:  Table,
nameFields: Table,
weakTrans: INT ];
transistorGateCount: PUBLIC ATOM ← CoreIO.RegisterProperty[
CoreProperties.RegisterProperty[
$TransistorGateCount,
CoreProperties.Props[
[CoreProperties.propPrint,  NEW[CoreProperties.PropPrintProc ← PrintTGC ]] ] ],
WriteINT,
ReadINT ];
WriteINT: CoreIO.PropWriteProc = {CoreIO.WriteInt[h, NARROW[value, REF INT]^]};
ReadINT: CoreIO.PropReadProc = {RETURN[ NEW[INT ← CoreIO.ReadInt[h] ] ]};
PrintTGC: CoreProperties.PropPrintProc =
{to.PutF[" Transistor Gate Count: %g", IO.int[NARROW[val, REF INT]^]]};
NewContext: PROC[name: ROPE, cell: CellType, public: Wire] RETURNS[ctx: Context] = {
register: CoreOps.EachWireProc = {
name: ROPE ← CoreName.WireNm[wire].n;
IF name.Length[]#0 THEN []←HashTable.Store[ctx.regPubs, name, wire]};
ctx ← NEW[ContextRec ← [
name:   name,
cell:   cell,
public:  public,
publics:  NIL,
regPubs:  HashTable.Create[],
nameFields: HashTable.Create[],
weakTrans: 0 ] ];
[]𡤌oreOps.VisitWire[public, register] };
BindingRec: TYPE = RECORD[
bot:  ROPE,
top:  ROPE,
size:  INT ← 0,
index:  INT ← -1,
octalIdx: BOOL ← FALSE];
ifuToClusterBindings: LIST OF BindingRec ← LIST[
["Pad-IPData",      "IPData",     32, -1, TRUE ],
["Pad-NewFetchBAA",    "IPCmdFetchA",     ],
["Pad-IPFaultingB",    "IPFaultingB"     ],
["Pad-IPRejectB",     "IPRejectB"      ],
["Pad-DPCmnd2BAA",    "DPCmdA",     8  ],
["Pad-DPFaultB",     "DPFaultB",      4  ],
["Pad-DPRejectB",     "DPRejectB"      ],
["Pad-UserMode2BAA",   "UserMode2BA",      ],
["Pad-EUAluOp2ABB",   "EUAluOp2AB",    4  ],
["Pad-EUCondSel2ABB",   "EUCondSel2AB",   4  ],
["Pad-EURdFromPBus3ABB",  "EURdFromPBus3AB"   ],
["Pad-EUWriteToPBus3ABB",  "EUWriteToPBus3AB"   ],
["Pad-EUCondition2B",   "EUCondition2B"    ],
["Pad-XBus",      "KBus",     32, -1, TRUE ],
["Pad-ResetAB",     "ResetAB"      ],
["Pad-RescheduleAB",    "RescheduleAB"     ],
["PhA",        "PhA"        ],
["PhB",        "PhB"        ],
["NotPhA",       "NotPhA"       ],
["NotPhB",       "NotPhB"       ],
["DShA",       "DShA"       ],
["DShB",        "DShB"       ],
["DShRd",       "DShRd"       ],
["DShWt",       "DShWt"       ],
["Pad-DShIn",      "DShIn"       ],
["Pad-DShOut",      "DShOut"       ],
["VDD",        "Vdd"        ],
["GND",        "Gnd"        ],
["PadVDD",       "PadVdd"       ],
["PadGND",       "PadGnd"       ],
["VBB",        "Vdd"        ],
["IDPlaFireV",      "Vdd"        ],
["IDPlaNotPhA",     "IDPlaNotPhA"     ] ];
MakeFlatBotPublicCtx: PROC[binds: LIST OF BindingRec] RETURNS[ctx: CoreName.Context] ={
publics: Wires ← NIL;
temp:  Wires ← NIL;
ctx ← CoreName.NewContext[];
FOR binds ← binds, binds.rest WHILE binds#NIL DO
b:  BindingRec ← binds.first;
IF b.size=0
THEN []𡤌oreName.CtxWire[ctx, b.bot]
ELSE
FOR i: INT IN [0..b.size) DO
[]𡤌oreName.CtxWire[ctx, (IF NOT b.octalIdx OR b.size<8
THENIO.PutFR["%g.%g",  IO.rope[b.bot], IO.int[i]]
ELSEIO.PutFR["%g.%02b", IO.rope[b.bot], IO.int[i]]) ]
ENDLOOP;
ENDLOOP};
RegTopBinds: PROC[
ctx:  Context,
binds:  LIST OF BindingRec] = {
FOR binds ← binds, binds.rest WHILE binds#NIL DO
b:  BindingRec ← binds.first;
f:  Field;
wire: Wire;
b.top ← CoreName.RopeNm[b.top];
wire ← NARROW[HashTable.Fetch[ctx.regPubs, b.top].value];
IF wire=NIL THEN {
wire ← CoreCreate.Seq[name: b.top, size: b.size];
[] ← HashTable.Store[ctx.regPubs, b.top, wire];
ctx.publics ← CONS[wire, ctx.publics]};
IF wire.size#b.size THEN ERROR;
f ← NEW[FieldRec ← [
root:  CoreName.RopeNm[b.bot],
wire:  (IF b.index#-1 THEN wire[b.index] ELSE wire),
octalIdx: b.octalIdx] ];
IF b.index#-1 THEN ctx.internals ← CONS[wire, ctx.internals]; -- partially connctd publics
[] ← HashTable.Store[ctx.nameFields, f.root, f];
ENDLOOP};
FormalCell: PUBLIC PROC[ctx: Context] RETURNS[formalCell: CellType] = {
rec:   CoreClasses.RecordCellType;
actual:  Wire  ← CoreOps.CreateWires[size: ctx.cell.public.size];
public:  Wire   ← IF ctx.publics#NIL
THEN CoreOps.CreateWire[ctx.publics]
ELSE ctx.public;
IF ctx.public#NIL AND ctx.public#public THEN Signal[];
TerminalIO.PutF["Recasting %g\n", IO.time[]];
TerminalIO.PutF["Marking Trans on VBB %g\n", IO.time[]];
ctx.weakTrans ← MarkGatedTransistorsWeak[ctx.cell, "VBB"];
TerminalIO.PutF["Marking Trans named driveWeak%g\n", IO.time[]];
[] ← MarkWeakTransistors[ctx.cell];
TerminalIO.PutF["Setting Up %g\n", IO.time[]];
SetUp[ctx.cell];
TerminalIO.PutF["Generate Formal %g\n", IO.time[]];
FOR index: INT IN [0..actual.size) DO
f:    Field;
name:   ROPE ← CoreName.WireNm[ctx.cell.public[index]].n;
sigRec:  CoreName.SigRec ← NameSig[name];
idx:   INT ← sigRec.idx;
IF ctx.cell.public[index].size#0 THEN ERROR;
sigRec.idx ← -1;
name   ← CoreName.SigName[sigRec];
f ← NARROW[HashTable.Fetch[ctx.nameFields, name].value];
IF f=NIL THEN ERROR;
actual[index] ← IF f.wire.size=0
THEN f.wire
ELSEIF f.octalIdx
THEN f.wire[ Adj[ idx ] ]
ELSE f.wire[  idx ];
ENDLOOP;
rec   ← NEW [CoreClasses.RecordCellTypeRec[1]];
formalCell ← NEW [Core.CellTypeRec ← [
class:  CoreClasses.recordCellClass,
public: public,
data:  rec ]];
IF ctx.internals=NIL
THEN rec.internal ← public -- this is ok
ELSE {
FOR i: INT IN [0..public.size) DO ctx.internals ← CONS[public[i], ctx.internals] ENDLOOP;
rec.internal ← CoreOps.CreateWire[ctx.internals]};
rec[0]   ← NEW [CoreClasses.CellInstanceRec ← [actual: actual, type: ctx.cell]];
[ ] ← CoreOps.SetCellTypeName[formalCell, ctx.name]};
CorrespondingWires: PROC[atomic1, wire1, wire2: Wire] RETURNS[atomic2s: Wires ← NIL] = {
visitProc: CoreOps.EachWirePairProc =
{IF actualWire=atomic1 THEN
FOR ws: Wires ← atomic2s, ws.rest WHILE ws #NIL DO
IF ws.first=publicWire THEN EXIT;
REPEAT FINISHED => atomic2s ← CONS[publicWire, atomic2s] ENDLOOP};
[ ] ← CoreOps.VisitBinding[wire1, wire2, visitProc]};
SubstituteRecasted: PUBLIC PROC [cell: CellType] RETURNS[recasted: CellType] = {
recasted ← cell;
SELECT cell.class FROM
CoreClasses.recordCellClass => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR child: NAT IN [0..data.size) DO
data.instances[child].typeSubstituteRecasted[data.instances[child].type]
ENDLOOP};
ENDCASE => IF cell.class.recast#NIL
THEN recasted ← SubstituteRecasted[CoreOps.Recast[cell]]};
MarkGatedTransistorsWeak: PUBLIC PROC [cell: CellType, wr: WR] RETURNS[count: INT ← 0]
= {RETURN[MarkGatedTypedTransistorsWeak[cell, wr, both]]};
MarkWeakTransistors: PROC [cell: CellType] = {
SELECT cell.class FROM
CoreClasses.transistorCellClass => ERROR;
CoreClasses.recordCellClass  => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR child: NAT IN [0..data.size) DO
IF data.instances[child].type.class # CoreClasses.transistorCellClass
THEN MarkWeakTransistors[ data.instances[child].type]
ELSE {
name: ROPENARROW
[CoreProperties.GetCellInstanceProp[data.instances[child], $CoreName]];
IF Rope.Equal[name, "driveWeak"] THEN
[] ← Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak]};
ENDLOOP };
ENDCASE => ERROR};
MarkGatedTypedTransistorsWeak: PROC [cell: CellType, wr: WR, ttype: {p, n, both}]
RETURNS[count: INT ← 0] = {
refInt: REF INT;
gate: Wire;
WITH wr SELECT FROM
wire: Wire    => gate ← wire;
rope: ROPE    => gate ← CoreOps.FindWire [cell.public, rope];
text: REF TEXT  => gate ← CoreOps.FindWire [cell.public, Rope.FromRefText[text]];
ENDCASE;
IF gate=NIL
THEN {TerminalIO.PutRope["Skipping misslabeled gate wire\n"]; RETURN}
ELSE refInt ← NARROW[CoreProperties.GetWireProp[gate, transistorGateCount].value];
IF refInt#NIL THEN RETURN[refInt^];
SELECT cell.class FROM
CoreClasses.transistorCellClass => ERROR;
CoreClasses.recordCellClass  => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR child: NAT IN [0..data.size) DO
wires: Wires ← CorrespondingWires
[gate, data.instances[child].actual, data.instances[child].type.public];
FOR wires ← wires, wires.rest WHILE wires#NIL DO
cnt: INT ← 0;
IF data.instances[child].type.class # CoreClasses.transistorCellClass
THEN cnt ← MarkGatedTransistorsWeak[ data.instances[child].type, wires.first ]
ELSE IF data.instances[child].type.public[0] = wires.first THEN {
td: CoreClasses.Transistor ← NARROW[data.instances[child].type.data];
doit: BOOLSELECT ttype FROM
p=>(td.type=pE), n=>(td.type=nE), ENDCASE=>TRUE;
IF doit THEN {
[ ] ← Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak];
cnt ← 1}};
count ← count + cnt ENDLOOP ENDLOOP };
ENDCASE => {
recast: CellType ← CoreOps.Recast[cell];
wires: Wires  ← CorrespondingWires[gate, cell.public, recast.public];
IF wires.rest#NIL THEN ERROR;
count ← MarkGatedTransistorsWeak[ recast, wires.first ]};
CoreProperties.PutWireProp[gate, transistorGateCount, NEW[INT ← count]]};
NameSig: PROC[name: ROPE] RETURNS[sigRec: CoreName.SigRec] = {
base: INT = 10;
val: INT ← -1;
DO-- Removes bracketed indexes
begin: INT ← name.Find["[", 0 ];
end: INT ← name.Find["]", 0 ];
last: ROPE ← IF (end+1) < name.Length[] THEN name.Substr[end+1] ELSE NIL;
IF begin=-1 THEN EXIT;
val ← MAX[0, val];
val ← val*base + Convert.IntFromRope[name.Substr[begin+1, end-begin-1]];
name ← Rope.Cat[name.Substr[0, begin], last]; ENDLOOP;
sigRec ← CoreName.NameSig[name];
sigRec.idx ← MAX[sigRec.idx, val]};
Adjustment for octal rope incorrectly converted using base 10. eg. 37 => 31, 40 => 32
Adj: PUBLIC PROC[dec: INT] RETURNS[oct: INT ← 0] = {
digits: LIST OF INTNIL;
WHILE dec#0  DO digits ← CONS[dec MOD 10, digits]; dec ← dec/10 ENDLOOP;
WHILE digits#NILDO oct ← oct*8 + digits.first; digits ← digits.rest ENDLOOP};
cacheQuick: CellType ← NIL;
cacheRouted: CellType ← NIL;
RoutedIFU: PROC[raw: BOOL] RETURNS[CellType] = {
IF cacheRouted=NIL THEN {
name: ROPEIF raw THEN "IFUCompleteRaw" ELSE "IFUComplete";
TerminalIO.PutF["Read/Recast: %g %g", IO.rope[name], IO.time[]];
cacheRouted ← CoreIO.RestoreCellType[name]; TerminalIO.PutF[". "];
cacheRouted ← SubstituteRecasted[cacheRouted];   TerminalIO.PutF[". "];
[ ] ← CoreName.CellNm[cacheRouted, "IFURouted"];
RemoveExtraneousProps[cacheRouted, keepPropTable];      TerminalIO.PutF[". "];
CoreIO.SaveCellType[cacheRouted];     TerminalIO.PutF["done\n"];
};
RETURN[cacheRouted]};
QuickIFU: PROC RETURNS[cell: CellType] = {
IF cacheQuick=NIL THEN
IF FilePresent["IFUQuick.core"]
THEN {
TerminalIO.PutF["Read: %g %g . . . ", IO.rope["IFUQuick"], IO.time[]];
cacheQuick ← CoreIO.RestoreCellType["IFUQuick"];
cacheQuick ← SubstituteRecasted[cacheQuick];
TerminalIO.PutF["done\n"]}
ELSE {
{
GetCell: PROC[subCellNm: ROPE] RETURNS[subCell: CellType] = {
TerminalIO.PutF["Read/Recast: %g %g . . ", IO.rope[subCellNm], IO.time[]];
subCell ← CoreIO.RestoreCellType[subCellNm]; TerminalIO.PutF[". "];
subCell ← SubstituteRecasted[subCell];   TerminalIO.PutF[". done\n"]};
wireTbl:  CoreName.Context ← MakeFlatBotPublicCtx[ifuToClusterBindings];
public:  Wire ← CoreName.WireFromCtx[wireTbl];
modules: LIST OF CellType = LIST[
GetCell["IFUDataColumnCore"],
GetCell["IFUControlPipe"],
GetCell["IFUABForm"],
GetCell["IFULSForm"],
GetCell["IFUStackBuf"],
GetCell["IFUPCFormBot"],
GetCell["IFUPCFormTop"],
GetCell["IFUXaForm"],
GetCell["IFUFetchBuf"],
GetCell["IFUFetch"],
GetCell["IFULeftColumnCore"],
GetCell["IFURightColumnCore"],
GetCell["IFUPadTopCore"],
GetCell["IFUPadLtCore"],
GetCell["IFUPadRtCore"],
GetCell["IFUPadBotCore"] ];
cacheQuick ← CoreName.BindModules[public, modules, "IFUQuick"];
};
TerminalIO.PutF["Remove Props: %g %g . . . ", IO.rope["IFUQuick"], IO.time[]];
RemoveExtraneousProps[cacheQuick, keepPropTable];
TerminalIO.PutF[" done\n"];
CoreIO.SaveCellType[cacheQuick]};
RETURN[cacheQuick]};
FormalIFU: PUBLIC PROC[public: Wire ← NIL, quick, raw: BOOL] RETURNS[ifu: CellType] = {
ctx: Context;
ifu ← IF quick THEN QuickIFU[] ELSE RoutedIFU[raw];
ctx ← NewContext["FormalIFU", ifu, public];
RegTopBinds[ctx, ifuToClusterBindings];
ifu ← FormalCell[ctx]};
FilePresent: PUBLIC PROC[name: ROPE] RETURNS[present: BOOLTRUE] = {
ENABLE FS.Error => {present ← FALSE; CONTINUE};
file: FS.OpenFile ← FS.Open[name];
IF present THEN FS.Close[file] ELSE TerminalIO.PutF["\n%g not present", IO.rope[name]]};
DrLatch Transistors
DrLatch-io  nDrLatch-io  GND
DrLatch-io  nDrLatch-io  VDD
nDrLatch-io  DrLatch-io  GND   weakTransistor
nDrLatch-io  DrLatch-io  VDD   weakTransistor
bit     nbit    GND
bit     nbit    VDD
nbit    bit     GND   weakTransistor
nbit    bit     VDD   weakTransistor
nDShDataOut DShDataOut  GND
nDShDataOut DShDataOut  VDD
DShDataOut  nDShDataOut GND   weakTransistor
DShDataOut  nDShDataOut VDD   weakTransistor
DShWt   nbit    DrLatch-io
DShRd   bit     nDrLatch-io
DShB    nbit    nDShDataOut
DShA    bit     DShDataIn
EnumPropLists: PROC
[cell: Core.CellType, eachList: PROC[pList: Properties] RETURNS[Properties]] = {
eachWireProc: CoreOps.EachWireProc = {wire.properties ← eachList[wire.properties]};
cell.properties ← eachList[cell.properties];
[]𡤌oreOps.VisitWire[cell.public, eachWireProc];
IF cell.class=CoreClasses.recordCellClass THEN {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
[]𡤌oreOps.VisitWire[data.internal, eachWireProc];
FOR child: NAT IN [0..data.size) DO
data[child].properties ← eachList[data[child].properties];
[]𡤌oreOps.VisitWire[data[child].actual, eachWireProc];
EnumPropLists[data[child].type, eachList] ENDLOOP } };
FindAllProps: PROC[cell: Core.CellType] RETURNS[atoms: LIST OF ATOMNIL]= {
propTable: HashTable.Table ← HashTable.Create[];
eachAtom: HashTable.EachPairAction = {
atoms ← CONS[NARROW[key, ATOM], atoms]};
eachProp: PROC [prop: ATOM, val: REF ANYNIL] =
{[]←HashTable.Store[propTable, prop, prop]};
eachList: PROC[pList: Properties] RETURNS[Properties] = {
CoreProperties.Enumerate[pList, eachProp];
RETURN[pList]};
EnumPropLists[cell, eachList];
[]←HashTable.Pairs[propTable, eachAtom]};
RemoveExtraneousProps: PROC[cell: Core.CellType, keepers: HashTable.Table] = {
eachList: PROC[pList: Properties] RETURNS[Properties] = {
atoms: LIST OF ATOMNIL;
eachProp: PROC [prop: ATOM, val: REF ANYNIL] =
{IF ~HashTable.Fetch[keepers, prop].found THEN atoms ← CONS[prop, atoms]};
CoreProperties.Enumerate[pList, eachProp];
FOR atoms ← atoms, atoms.rest WHILE atoms#NIL DO
pList ← CoreProperties.PutProp[pList, atoms.first, NIL] ENDLOOP;
RETURN[pList]};
EnumPropLists[cell, eachList]};
SetUp: PUBLIC PROC[cell: Core.CellType] = {
name: ROPE ← CoreName.CellNm[cell].n;
IF CoreProperties.GetCellTypeProp[cell, $RoseBehave].value#NIL THEN RETURN;
SELECT TRUE FROM
name=dpPreChg  => {
[]←Rosemary.BindCellType[cell, dpPreChg];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpPreChg];
InitPort[cell.public, "0",     b, none];
InitPort[cell.public, "out0",    b, drive]};
name=dpLatchPreChg  => {
[]←Rosemary.BindCellType[cell, dpLatchPreChg];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpPreChg];
InitPort[cell.public, "in0",    b, none];
InitPort[cell.public, "out0",    b, drive]};
name=dpDebugRec  => {
[]←Rosemary.BindCellType[cell, dpDebugRec];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpDebugRec];
InitPort[cell.public, "in0",    b, none];
InitPort[cell.public, "in1",    b, none];
InitPort[cell.public, "0",     b, none];
InitPort[cell.public, "1",     b, none];
InitPort[cell.public, "2",     b, none];
InitPort[cell.public, "out0",    b, drive]};
name=dpLatchG  => {
[]←Rosemary.BindCellType[cell, dpLatchG];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpLatch];
InitPort[cell.public, "out0",    b, drive];
[]←MarkGatedTypedTransistorsWeak[cell, CoreOps.FindWire[cell.public, "out0"], p]};
name=dpLatchV  => {
[]←Rosemary.BindCellType[cell, dpLatchV];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpLatch];
InitPort[cell.public, "out0",    b, drive];
[]←MarkGatedTypedTransistorsWeak[cell, CoreOps.FindWire[cell.public, "out0"], p]};
name=dpLatch  => {
[]←Rosemary.BindCellType[cell, dpLatch];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpLatch];
InitPort[cell.public, "in0",    b, none];
InitPort[cell.public, "0",     b, none];
InitPort[cell.public, "out0",    b, drive];
[]←MarkGatedTypedTransistorsWeak[cell, CoreOps.FindWire[cell.public, "out0"], p]};
name=dpLatchCtl  => {
[]←Rosemary.BindCellType[cell, dpLatchCtl];
[]𡤌oreFlat.CellTypeCutLabels[cell, dpLatch];
InitPort[cell.public, "in1",    b, none];
InitPort[cell.public, "in0",    b, none];
InitPort[cell.public, "out0",    b, drive];
[]←MarkGatedTypedTransistorsWeak[cell, CoreOps.FindWire[cell.public, "out0"], p]};
name=drLatch => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
[]←Rosemary.BindCellType[cell, drLatch];
[]𡤌oreFlat.CellTypeCutLabels[cell, drLatch];
[]←MarkGatedTransistorsWeak[cell, CoreOps.FindWire[data.internal, "nDrLatch-io"]];
[]←MarkGatedTransistorsWeak[cell, CoreOps.FindWire[data.internal, "nbit"]];
[]←MarkGatedTransistorsWeak[cell, CoreOps.FindWire[data.internal, "DShDataOut"]];
InitPort[cell.public, "DrLatch-io",  b, none];
InitPort[cell.public, "DShDataIn",  b, none];
InitPort[cell.public, "DShDataOut", b, drive];
InitPort[cell.public, "DShA",   b, none];
InitPort[cell.public, "DShB",   b, none];
InitPort[cell.public, "DShWt",   b, none];
InitPort[cell.public, "DShRd",   b, none]};
Rope.Equal[name.Substr[0,4], "Mux|"]  => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
ctl: ROPE← MuxNameField[name, ctl];
in:  ROPE← MuxNameField[name, in];
blankIns: INT ← 0;
IF data.size=0 THEN RETURN;
[]←Rosemary.BindCellType [cell, genericMux];
[]𡤌oreFlat.CellTypeCutLabels [cell, genericMux];
FOR child: NAT IN [0..data.size) DO
[] ← Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak];
ENDLOOP;
FOR i: INT IN [0..ctl.Length[]) DO
wire: Wire;
wire ← CoreOps.FindWire[cell.public, ctl.Substr[i,1]];
IF wire=NIL THEN Signal[];
[]←Ports.InitPort[wire: wire, levelType: b, initDrive: none];
wire ← CoreOps.FindWire[cell.public, in.Substr[i,1]];
IF wire#NIL
THEN []←Ports.InitPort[wire: wire, levelType: b, initDrive: none]
ELSE blankIns ← blankIns+1;
ENDLOOP;
IF (data.size+blankIns)#ctl.Length[] THEN Signal[];
InitPort[cell.public, MuxNameField[name, out].Substr[0,1], l, drive]};
name=ifuFetchBuf => IFUSim.FetchBufInitPort [cell];
name=ifuStackBuf => IFUSim.StackBufInitPort [cell];
ENDCASE => SELECT cell.class FROM
PLASim.simplePLAClass  => PLASim.SetUpRose[cell];
CoreClasses.transistorCellClass => ERROR;
CoreClasses.recordCellClass  => {
data: CoreClasses.RecordCellType ← NARROW[cell.data];
FOR child: NAT IN [0..data.size) DO
IF data.instances[child].type.class # CoreClasses.transistorCellClass
THEN SetUp[ data.instances[child].type]
ELSE {
trans: CoreClasses.Transistor ← NARROW[data.instances[child].type.data];
length: REAL ← trans.length;
width: REAL ← trans.width;
IF length/width > .5 THEN
[] ← Rosemary.SetTransistorInstanceSize[data.instances[child], driveWeak]};
ENDLOOP };
ENDCASE => {recast: CellType ← CoreOps.Recast[cell]; SetUp[ recast ]} };
ENDCASE => {Signal[]} };
InitPort: PROC
[wire: Wire, name: ROPE, levelType: Ports.LevelType, initDrive: Ports.Drive] ={
wire ← CoreOps.FindWire[wire, name];
IF wire#NIL THEN
[]←Ports.InitPort[wire: wire, levelType: levelType, initDrive: initDrive]};
dpPreChg:  ROPE ← Rosemary.Register[CoreName.RopeNm["DpPreChg"],
DpPreChgInit,  DpPreChgEval];
dpLatchPreChg: ROPE ← Rosemary.Register[CoreName.RopeNm["DpLatchPreChg"],
DpLatchPreChgInit, DpPreChgEval];
dpDebugRec:  ROPE ← Rosemary.Register[CoreName.RopeNm["DpDebugRec"],
DpDebugRecInit, DpDebugRecEval];
dpLatch:  ROPE ← Rosemary.Register[CoreName.RopeNm["DpLatch"],
DpLatchInit,  DpLatchEval];
dpLatchG: ROPE ← Rosemary.Register[CoreName.RopeNm["DpLatch-G-="],
DpLatchGVInit, DpLatchGEval];
dpLatchV: ROPE ← Rosemary.Register[CoreName.RopeNm["DpLatch-V-="],
DpLatchGVInit, DpLatchVEval];
dpLatchCtl: ROPE ← Rosemary.Register[CoreName.RopeNm["DpLatchCtl"],
DpLatchCtlInit, DpLatchEval];
drLatch:  ROPE ← Rosemary.Register[CoreName.RopeNm["DrLatch"],
DrLatchInit,  DrLatchEval];
genericMux:  ROPE ← Rosemary.Register[CoreName.RopeNm["GenericMux"],
MuxInit,  MuxEval];
ifuFetchBuf:  ROPE ← CoreName.RopeNm["IFUFetchBuf"];
ifuStackBuf:  ROPE ← CoreName.RopeNm["IFUStackBuf"];
upOneLevel:  ROPE ← CoreName.RopeNm["UpOneLevel"];
simpleMux:  ROPE ← CoreName.RopeNm["SimpleMux"];
DrLatchState:   TYPE = REF DrLatchStateRec;
DrLatchStateRec: TYPE = RECORD[
io, DShIn, DShOut, DShA, DShB, DShWt, DShRd: INT ← -1,
inside: BOOLFALSE];
DpPreChgState:  TYPE = REF DpPreChgStateRec;
DpPreChgStateRec: TYPE = RECORD[in, out: INT ← -1];
DpDebugRecState:  TYPE = REF DpDebugRecStateRec;
DpDebugRecStateRec: TYPE = RECORD
[in0, in1, ctl0, ctl1, ctl2, out: INT ← -1, bit: BOOLFALSE];
DpLatchState:  TYPE = REF DpLatchStateRec;
DpLatchStateRec: TYPE = RECORD[
in, ctl, out: INT ← -1,
inside: BOOLFALSE];
MuxState:    TYPE = REF MuxStateRec;
MuxStateRec: TYPE = RECORD[
ctl: MuxPinSeq,
in:  MuxPinSeq,
out: INT];
MuxPinSeq:   TYPE = REF MuxPinSeqRec;
MuxPinSeqRec:  TYPE = RECORD[SEQUENCE size: CARDINAL OF INTEGER];
DrLatchInit: Rosemary.InitProc = {
s: DrLatchState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DrLatchStateRec];
s^ ← [
io:   CoreOps.GetWireIndex[cellType.public, "DrLatch-io"],
DShIn: CoreOps.GetWireIndex[cellType.public, "DShDataIn"],
DShOut: CoreOps.GetWireIndex[cellType.public, "DShDataOut"],
DShA: CoreOps.GetWireIndex[cellType.public, "DShA"],
DShB: CoreOps.GetWireIndex[cellType.public, "DShB"],
DShWt: CoreOps.GetWireIndex[cellType.public, "DShWt"],
DShRd: CoreOps.GetWireIndex[cellType.public, "DShRd"],
inside: FALSE ];
RETURN[s]};
DpPreChgInit: Rosemary.InitProc = {
s: DpPreChgState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpPreChgStateRec];
s^ ← [
in:   CoreOps.GetWireIndex[cellType.public, "0"],
out:  CoreOps.GetWireIndex[cellType.public, "out0"]];
RETURN[s]};
DpLatchPreChgInit: Rosemary.InitProc = {
s: DpPreChgState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpPreChgStateRec];
s^ ← [
in:   CoreOps.GetWireIndex[cellType.public, "in0"],
out:  CoreOps.GetWireIndex[cellType.public, "out0"]];
RETURN[s]};
DpDebugRecInit: Rosemary.InitProc = {
s: DpDebugRecState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpDebugRecStateRec];
s^ ← [
in0:  CoreOps.GetWireIndex[cellType.public, "in0"],
in1:  CoreOps.GetWireIndex[cellType.public, "in1"],
ctl0:  CoreOps.GetWireIndex[cellType.public, "0"],
ctl1:  CoreOps.GetWireIndex[cellType.public, "1"],
ctl2:  CoreOps.GetWireIndex[cellType.public, "2"],
out:  CoreOps.GetWireIndex[cellType.public, "out0"],
bit:  FALSE ];
RETURN[s]};
DpLatchInit: Rosemary.InitProc = {
s: DpLatchState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpLatchStateRec];
s^ ← [
in:   CoreOps.GetWireIndex[cellType.public, "in0"],
ctl:  CoreOps.GetWireIndex[cellType.public, "0"],
out:  CoreOps.GetWireIndex[cellType.public, "out0"],
inside: FALSE ];
RETURN[s]};
DpLatchGVInit: Rosemary.InitProc = {
s: DpLatchState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpLatchStateRec];
s^ ← [out: CoreOps.GetWireIndex[cellType.public, "out0"] ];
RETURN[s]};
DpLatchCtlInit: Rosemary.InitProc = {
s: DpLatchState ← IF oldStateAny # NIL
THENNARROW[oldStateAny]
ELSENEW[DpLatchStateRec];
s^ ← [
in:   CoreOps.GetWireIndex[cellType.public, "in0"],
ctl:  CoreOps.GetWireIndex[cellType.public, "in1"],
out:  CoreOps.GetWireIndex[cellType.public, "out0"],
inside: FALSE ];
RETURN[s]};
MuxInit: Rosemary.InitProc = {
name:  ROPE ← CoreName.CellNm[cellType].n;
s:   MuxState;
ctl:  ROPE ← MuxNameField[name, ctl];
in:   ROPE ← MuxNameField[name, in];
s   ← NEW[MuxStateRec];
s.ctl  ← NEW[MuxPinSeqRec[ctl.Length[]]];
s.in  ← NEW[MuxPinSeqRec[ctl.Length[]]];
FOR i: CARDINAL IN [0..s.ctl.size) DO
s.ctl[i] ← CoreOps.GetWireIndex[cellType.public, ctl.Substr[i,1] ];
s.in[i]  ← CoreOps.GetWireIndex[cellType.public, in.Substr[i,1] ];
ENDLOOP;
s.out ← CoreOps.GetWireIndex[cellType.public, MuxNameField[name, out].Substr[0,1]];
RETURN[s]};
DrLatchEval: Rosemary.EvalProc = {
s: DrLatchState ← NARROW[stateAny];
IF p[s.DShRd].b AND p[s.DShA].b THEN Signal[];
IF p[s.DShRd].b AND p[s.DShWt].b THEN Signal[];
IF p[s.DShA].b THEN s.inside ←    p[s.DShIn].b;
IF p[s.DShRd].b THEN s.inside ← NOT p[s.io].b;
IF p[s.DShWt].b
THEN {p[s.io].b ← NOT s.inside; p[s.io].d ← drive}
ELSE p[s.io].d ← none;
IF p[s.DShB].b THEN p[s.DShOut].b ← s.inside };
DpPreChgEval: Rosemary.EvalProc = {
s: DpPreChgState ← NARROW[stateAny];
IF NOT p[s.in].b
THEN {p[s.out].d ← drive; p[s.out].b ← TRUE}
ELSE {p[s.out].d ← none}};
DpDebugRecEval: Rosemary.EvalProc = {
s: DpDebugRecState ← NARROW[stateAny];
IF p[s.ctl0].b AND p[s.ctl1].b THEN Signal[];
IF p[s.ctl0].b      THEN s.bit ←  p[s.in0].b;
IF p[s.ctl1].b      THEN s.bit ←  p[s.in1].b;
IF p[s.ctl2].b THEN p[s.out].b ← s.bit };
DpLatchEval: Rosemary.EvalProc = {
s: DpLatchState ← NARROW[stateAny];
IF p[s.ctl].b THEN s.inside ← p[s.in].b;
p[s.out].b ← s.inside };
DpLatchGEval: Rosemary.EvalProc = {
s: DpLatchState ← NARROW[stateAny];
p[s.out].b ← FALSE };
DpLatchVEval: Rosemary.EvalProc = {
s: DpLatchState ← NARROW[stateAny];
p[s.out].b ← TRUE };
MuxEval: Rosemary.EvalProc = {
s:   MuxState ← NARROW[stateAny];
count:  CARDINAL ← 0;
last:  CARDINAL ← 0;
FOR i: CARDINAL IN [0..s.ctl.size) DO
IF p[s.ctl[i]].b AND s.in[i]#-1 THEN {count ← count+1; last ← i} ENDLOOP;
SELECT count FROM
0   => { };
1   => IF s.in[last]#-1 THEN p[s.out].l ← IF p[s.in[last]].b THEN H ELSE L;
ENDCASE => p[s.out].l ← X};
MuxNameField: PROC[name: ROPE, type: {ctl, in, out}]
RETURNS[field: ROPENIL] = {
Must Agree with IFUCoreDataMuxImpl.ExpandDataMuxFrameHard CreateNameLetterCode
index: CARDINALSELECT type FROM ctl=>1, in=>2, ENDCASE=>3;
THROUGH [0..index] DO name ← name.Substr[name.Find["|"]+1] ENDLOOP;
field ← name.Substr[0, name.Find["|"]]};
Signal: SIGNAL = CODE;
keepPropTable: HashTable.Table ← HashTable.Create[];
[]←HashTable.Store[keepPropTable, $CoreName,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $Layout,      NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $WireCap,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $RootCap,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $CapaLabel,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $TransistorGateCount,  NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $TransistorCount,   NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $CoreIOGlobal,    NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $CoreBlockSides,   NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $GivenName,    NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $FusedByName,    NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $CoreNameToWireCache, NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $CoreWireToNamesCache NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $ClusterInfo,    NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $PortData,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $RoseFixedWire,   NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $RoseCutSet,     NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $RoseTransistorSize,  NEW[INT ← 0]];
[]←HashTable.Store[keepPropTable, $RoseBehave,    NEW[INT ← 0]];
END.